summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/3c501.c4
-rw-r--r--drivers/net/3c503.c12
-rw-r--r--drivers/net/3c505.c6
-rw-r--r--drivers/net/3c507.c4
-rw-r--r--drivers/net/3c523.c4
-rw-r--r--drivers/net/3c527.c4
-rw-r--r--drivers/net/82596.c2
-rw-r--r--drivers/net/Config.in71
-rw-r--r--drivers/net/Makefile46
-rw-r--r--drivers/net/Space.c14
-rw-r--r--drivers/net/a2065.c3
-rw-r--r--drivers/net/ac3200.c4
-rw-r--r--drivers/net/acenic.c10
-rw-r--r--drivers/net/apne.c5
-rw-r--r--drivers/net/arc-rimi.c8
-rw-r--r--drivers/net/arcnet.c16
-rw-r--r--drivers/net/ariadne.c2
-rw-r--r--drivers/net/ariadne2.c7
-rw-r--r--drivers/net/arlan-proc.c1059
-rw-r--r--drivers/net/arlan.c2079
-rw-r--r--drivers/net/arlan.h574
-rw-r--r--drivers/net/atari_bionet.c4
-rw-r--r--drivers/net/atari_pamsnet.c4
-rw-r--r--drivers/net/atarilance.c20
-rw-r--r--drivers/net/atp.c10
-rw-r--r--drivers/net/com20020.c8
-rw-r--r--drivers/net/com90io.c8
-rw-r--r--drivers/net/com90xx.c10
-rw-r--r--drivers/net/cops.c6
-rw-r--r--drivers/net/cosa.c2
-rw-r--r--drivers/net/cs89x0.c24
-rw-r--r--drivers/net/de4x5.c49
-rw-r--r--drivers/net/de600.c4
-rw-r--r--drivers/net/de620.c12
-rw-r--r--drivers/net/defxx.c36
-rw-r--r--drivers/net/depca.c50
-rw-r--r--drivers/net/dgrs.c24
-rw-r--r--drivers/net/dlci.c2
-rw-r--r--drivers/net/dummy.c4
-rw-r--r--drivers/net/e2100.c4
-rw-r--r--drivers/net/eepro100.c5
-rw-r--r--drivers/net/eexpress.c8
-rw-r--r--drivers/net/eql.c26
-rw-r--r--drivers/net/es3210.c4
-rw-r--r--drivers/net/eth16i.c6
-rw-r--r--drivers/net/ethertap.c2
-rw-r--r--drivers/net/ewrk3.c99
-rw-r--r--drivers/net/fmv18x.c6
-rw-r--r--drivers/net/hamradio/6pack.c2
-rw-r--r--drivers/net/hamradio/baycom_par.c6
-rw-r--r--drivers/net/hamradio/baycom_ser_fdx.c6
-rw-r--r--drivers/net/hamradio/baycom_ser_hdx.c6
-rw-r--r--drivers/net/hamradio/bpqether.c2
-rw-r--r--drivers/net/hamradio/dmascc.c7
-rw-r--r--drivers/net/hamradio/hdlcdrv.c3
-rw-r--r--drivers/net/hamradio/mkiss.c4
-rw-r--r--drivers/net/hamradio/pi2.c4
-rw-r--r--drivers/net/hamradio/pt.c5
-rw-r--r--drivers/net/hamradio/scc.c2
-rw-r--r--drivers/net/hamradio/soundmodem/sm.c8
-rw-r--r--drivers/net/hamradio/soundmodem/sm.h2
-rw-r--r--drivers/net/hostess_sv11.c3
-rw-r--r--drivers/net/hp-plus.c4
-rw-r--r--drivers/net/hp.c4
-rw-r--r--drivers/net/hp100.c7
-rw-r--r--drivers/net/hplance.c4
-rw-r--r--drivers/net/hydra.c2
-rw-r--r--drivers/net/ibmtr.c16
-rw-r--r--drivers/net/irda/actisys.c2
-rw-r--r--drivers/net/irda/esi.c2
-rw-r--r--drivers/net/irda/girbil.c2
-rw-r--r--drivers/net/irda/irport.c2
-rw-r--r--drivers/net/irda/irtty.c2
-rw-r--r--drivers/net/irda/litelink.c2
-rw-r--r--drivers/net/irda/pc87108.c2
-rw-r--r--drivers/net/irda/smc-ircc.c4
-rw-r--r--drivers/net/irda/tekram.c2
-rw-r--r--drivers/net/irda/toshoboe.c6
-rw-r--r--drivers/net/irda/uircc.c4
-rw-r--r--drivers/net/irda/w83977af_ir.c2
-rw-r--r--drivers/net/lance.c4
-rw-r--r--drivers/net/lne390.c4
-rw-r--r--drivers/net/loopback.c2
-rw-r--r--drivers/net/ltpc.c6
-rw-r--r--drivers/net/myri_sbus.c2
-rw-r--r--drivers/net/ne.c6
-rw-r--r--drivers/net/ne2.c5
-rw-r--r--drivers/net/ne2k-pci.c183
-rw-r--r--drivers/net/ne3210.c4
-rw-r--r--drivers/net/olympic.c1663
-rw-r--r--drivers/net/olympic.h303
-rw-r--r--drivers/net/ppp.c1
-rw-r--r--drivers/net/rtl8139.c157
-rw-r--r--drivers/net/sealevel.c471
-rw-r--r--drivers/net/seeq8005.c54
-rw-r--r--drivers/net/slhc.c1
-rw-r--r--drivers/net/sunbmac.c1
-rw-r--r--drivers/net/sunhme.c2
-rw-r--r--drivers/net/sunlance.c1
-rw-r--r--drivers/net/tulip.c21
-rw-r--r--drivers/net/via-rhine.c21
-rw-r--r--drivers/net/wavelan.c92
-rw-r--r--drivers/net/z85230.c18
-rw-r--r--drivers/net/zlib.c4
104 files changed, 6910 insertions, 616 deletions
diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c
index 6c2a672ec..029571460 100644
--- a/drivers/net/3c501.c
+++ b/drivers/net/3c501.c
@@ -210,7 +210,7 @@ struct net_local
struct netdev_entry el1_drv = {"3c501", el1_probe1, EL1_IO_EXTENT, netcard_portlist};
#else
-__initfunc(int el1_probe(struct device *dev))
+int __init el1_probe(struct device *dev)
{
int i;
int base_addr = dev ? dev->base_addr : 0;
@@ -237,7 +237,7 @@ __initfunc(int el1_probe(struct device *dev))
* The actual probe.
*/
-__initfunc(static int el1_probe1(struct device *dev, int ioaddr))
+static int __init el1_probe1(struct device *dev, int ioaddr)
{
struct net_local *lp;
const char *mname; /* Vendor name */
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 9f922c43e..3c0ada25e 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -90,8 +90,8 @@ static void el2_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
If the ethercard isn't found there is an optional probe for
ethercard jumpered to programmed-I/O mode.
*/
-__initfunc(int
-el2_probe(struct device *dev))
+int __init
+el2_probe(struct device *dev)
{
int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0};
int base_addr = dev->base_addr;
@@ -125,8 +125,8 @@ el2_probe(struct device *dev))
#ifndef HAVE_DEVLIST
/* Try all of the locations that aren't obviously empty. This touches
a lot of locations, and is much riskier than the code above. */
-__initfunc(int
-el2_pio_probe(struct device *dev))
+int __init
+el2_pio_probe(struct device *dev)
{
int i;
int base_addr = dev ? dev->base_addr : 0;
@@ -151,8 +151,8 @@ el2_pio_probe(struct device *dev))
/* Probe for the Etherlink II card at I/O port base IOADDR,
returning non-zero on success. If found, set the station
address and memory parameters in DEVICE. */
-__initfunc(int
-el2_probe1(struct device *dev, int ioaddr))
+int __init
+el2_probe1(struct device *dev, int ioaddr)
{
int i, iobase_reg, membase_reg, saved_406, wordlength;
static unsigned version_printed = 0;
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index 34edf2200..5f5875953 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -1339,7 +1339,7 @@ static inline void elp_init(struct device *dev)
* Called only by elp_autodetect
************************************************************/
-__initfunc(static int elp_sense(struct device *dev))
+static int __init elp_sense(struct device *dev)
{
int timeout;
int addr = dev->base_addr;
@@ -1406,7 +1406,7 @@ __initfunc(static int elp_sense(struct device *dev))
* Called only by eplus_probe
*************************************************************/
-__initfunc(static int elp_autodetect(struct device *dev))
+static int __init elp_autodetect(struct device *dev)
{
int idx = 0;
@@ -1450,7 +1450,7 @@ __initfunc(static int elp_autodetect(struct device *dev))
* work at all if it was in a weird state).
*/
-__initfunc(int elplus_probe(struct device *dev))
+int __init elplus_probe(struct device *dev)
{
elp_device *adapter;
int i, tries, tries1, timeout, okay;
diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c
index b27fa2148..f53a17be8 100644
--- a/drivers/net/3c507.c
+++ b/drivers/net/3c507.c
@@ -305,7 +305,7 @@ struct netdev_entry netcard_drv =
device and return success.
*/
-__initfunc(int el16_probe(struct device *dev))
+int __init el16_probe(struct device *dev)
{
int base_addr = dev ? dev->base_addr : 0;
int i;
@@ -326,7 +326,7 @@ __initfunc(int el16_probe(struct device *dev))
return ENODEV;
}
-__initfunc(int el16_probe1(struct device *dev, int ioaddr))
+int __init el16_probe1(struct device *dev, int ioaddr)
{
static unsigned char init_ID_done = 0, version_printed = 0;
int i, irq, irqval;
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index 25daedb2d..958100d66 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -319,7 +319,7 @@ static int elmc_open(struct device *dev)
* Check to see if there's an 82586 out there.
*/
-__initfunc(static int check586(struct device *dev, unsigned long where, unsigned size))
+static int __init check586(struct device *dev, unsigned long where, unsigned size)
{
struct priv *p = (struct priv *) dev->priv;
char *iscp_addrs[2];
@@ -422,7 +422,7 @@ static int elmc_getinfo(char *buf, int slot, void *d)
/*****************************************************************/
-__initfunc(int elmc_probe(struct device *dev))
+int __init elmc_probe(struct device *dev)
{
static int slot = 0;
int base_addr = dev ? dev->base_addr : 0;
diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c
index 947cf6d2d..33297b0e1 100644
--- a/drivers/net/3c527.c
+++ b/drivers/net/3c527.c
@@ -147,7 +147,7 @@ static void mc32_set_multicast_list(struct device *dev);
* (detachable devices only).
*/
-__initfunc(int mc32_probe(struct device *dev))
+int __init mc32_probe(struct device *dev)
{
static int current_mca_slot = -1;
int i;
@@ -183,7 +183,7 @@ __initfunc(int mc32_probe(struct device *dev))
* probes on the ISA bus. A good device probes avoids doing writes, and
* verifies that the correct device exists and functions.
*/
-__initfunc(static int mc32_probe1(struct device *dev, int slot))
+static int __init mc32_probe1(struct device *dev, int slot)
{
static unsigned version_printed = 0;
int i;
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index cd3ab6bd6..1dcbd9f40 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -878,7 +878,7 @@ static void print_eth(char *add)
printk("type %2.2X%2.2X\n", (unsigned char) add[12], (unsigned char) add[13]);
}
-__initfunc(int i82596_probe(struct device *dev))
+int __init i82596_probe(struct device *dev)
{
int i;
struct i596_private *lp;
diff --git a/drivers/net/Config.in b/drivers/net/Config.in
index aefc79a30..79a89cb4b 100644
--- a/drivers/net/Config.in
+++ b/drivers/net/Config.in
@@ -2,6 +2,9 @@
# Network device configuration
#
+mainmenu_option next_comment
+comment 'ARCnet devices'
+
tristate 'ARCnet support' CONFIG_ARCNET
if [ "$CONFIG_ARCNET" != "n" ]; then
bool ' Enable arc0e (ARCnet "Ether-Encap" packet format)' CONFIG_ARCNET_ETH
@@ -12,6 +15,8 @@ if [ "$CONFIG_ARCNET" != "n" ]; then
dep_tristate ' ARCnet COM20020 chipset driver' CONFIG_ARCNET_COM20020 $CONFIG_ARCNET
fi
+endmenu
+
tristate 'Dummy net driver support' CONFIG_DUMMY
tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
@@ -22,6 +27,10 @@ fi
#
# Ethernet
#
+
+mainmenu_option next_comment
+comment 'Ethernet (10 or 100Mbit)'
+
bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET
if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
if [ "$CONFIG_ARM" = "y" ]; then
@@ -82,18 +91,15 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139
tristate 'Packet Engines Yellowfin Gigabit-NIC support' CONFIG_YELLOWFIN
- tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC
fi
bool 'Other ISA cards' CONFIG_NET_ISA
if [ "$CONFIG_NET_ISA" = "y" ]; then
- tristate 'AT1700/1720 support' CONFIG_AT1700
+ tristate 'AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700
tristate 'Cabletron E21xx support' CONFIG_E2100
tristate 'DEPCA, DE10x, DE200, DE201, DE202, DE422 support' CONFIG_DEPCA
tristate 'EtherWORKS 3 (DE203, DE204, DE205) support' CONFIG_EWRK3
tristate 'EtherExpress 16 support' CONFIG_EEXPRESS
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- tristate 'EtherExpressPro support' CONFIG_EEXPRESS_PRO
- fi
+ tristate 'EtherExpressPro support' CONFIG_EEXPRESS_PRO
tristate 'FMV-181/182/183/184 support' CONFIG_FMV18X
tristate 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS
tristate 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN
@@ -103,7 +109,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
fi
tristate 'NE2000/NE1000 support' CONFIG_NE2000
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool 'SEEQ8005 support (EXPERIMENTAL)' CONFIG_SEEQ8005
+ tristate 'SEEQ8005 support (EXPERIMENTAL)' CONFIG_SEEQ8005
fi
bool 'SK_G16 support' CONFIG_SK_G16
fi
@@ -115,6 +121,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
if [ "$CONFIG_NET_EISA" = "y" ]; then
tristate 'AMD PCnet32 (VLB and PCI) support' CONFIG_PCNET32
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC
tristate 'Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200
fi
@@ -145,6 +152,8 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
fi
fi
+endmenu
+
bool 'FDDI driver support' CONFIG_FDDI
if [ "$CONFIG_FDDI" = "y" ]; then
bool 'Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX
@@ -153,25 +162,20 @@ fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool 'HIPPI driver support (EXPERIMENTAL)' CONFIG_HIPPI
if [ "$CONFIG_HIPPI" = "y" ]; then
- bool 'CERN HIPPI PCI adapter support' CONFIG_CERN_HIPPI
- bool 'Essential RoadRunner HIPPI PCI adapter support' CONFIG_ROADRUNNER
+ tristate 'Essential RoadRunner HIPPI PCI adapter support' CONFIG_ROADRUNNER
if [ "$CONFIG_ROADRUNNER" != "n" ]; then
bool ' Use large TX/RX rings' CONFIG_ROADRUNNER_LARGE_RINGS
fi
fi
fi
-tristate 'Frame relay DLCI support' CONFIG_DLCI
-if [ "$CONFIG_DLCI" = "y" -o "$CONFIG_DLCI" = "m" ]; then
- int ' Max open DLCI' CONFIG_DLCI_COUNT 24
- int ' Max DLCI per device' CONFIG_DLCI_MAX 8
- dep_tristate ' SDLA (Sangoma S502/S508) support' CONFIG_SDLA $CONFIG_DLCI
-fi
-
#
# AppleTalk
#
+
if [ "$CONFIG_ATALK" != "n" ]; then
+ mainmenu_option next_comment
+ comment 'Appletalk devices'
dep_tristate 'Apple/Farallon LocalTalk PC support' CONFIG_LTPC $CONFIG_ATALK
dep_tristate 'COPS LocalTalk PC support' CONFIG_COPS $CONFIG_ATALK
if [ "$CONFIG_COPS" != "n" ]; then
@@ -183,6 +187,7 @@ if [ "$CONFIG_ATALK" != "n" ]; then
bool 'IP to Appletalk-IP Encapsulation support' CONFIG_IPDDP_ENCAP
bool 'Appletalk-IP to IP Decapsulation support' CONFIG_IPDDP_DECAP
fi
+ endmenu
fi
if [ ! "$CONFIG_PARPORT" = "n" ]; then
@@ -203,23 +208,38 @@ fi
bool 'Wireless LAN (non-hamradio)' CONFIG_NET_RADIO
if [ "$CONFIG_NET_RADIO" = "y" ]; then
- tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP
+ dep_tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP $CONFIG_INET
tristate 'AT&T WaveLAN & DEC RoamAbout DS support' CONFIG_WAVELAN
+ tristate 'Aironet Arlan 655 & IC2200 DS support' CONFIG_ARLAN
+
fi
+mainmenu_option next_comment
+comment 'Token ring devices'
+
bool 'Token Ring driver support' CONFIG_TR
if [ "$CONFIG_TR" = "y" ]; then
tristate 'IBM Tropic chipset based adaptor support' CONFIG_IBMTR
# tristate 'IBM Lanstreamer PCI adaptor support' CONFIG_IBMLS
+ tristate 'IBM Olympic chipset PCI adapter support' CONFIG_IBMOL
tristate 'SysKonnect adapter support' CONFIG_SKTR
fi
+endmenu
+
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Red Creek Hardware VPN (EXPERIMENTAL)' CONFIG_RCPCI
tristate 'Traffic Shaper (EXPERIMENTAL)' CONFIG_SHAPER
fi
+
#
# WAN drivers support
#
+
+mainmenu_option next_comment
+comment 'Wan interfaces'
+
+
# There is no way to detect a comtrol sv11 - force it modular for now.
#
dep_tristate 'Comtrol Hostess SV-11 support' CONFIG_HOSTESS_SV11 m
@@ -227,8 +247,22 @@ dep_tristate 'Comtrol Hostess SV-11 support' CONFIG_HOSTESS_SV11 m
# The COSA/SRP driver has not been tested as non-modular yet.
#
dep_tristate 'COSA/SRP sync serial boards support' CONFIG_COSA m
-tristate 'Red Creek Hardware VPN (EXPERIMENTAL)' CONFIG_RCPCI
#
+# There is no way to detect a Sealevel board. Force it modular
+#
+dep_tristate 'Sealevel Systems 4021 support' CONFIG_SEALEVEL_4021 m
+
+tristate 'Frame relay DLCI support' CONFIG_DLCI
+if [ "$CONFIG_DLCI" != "n" ]; then
+ int ' Max open DLCI' CONFIG_DLCI_COUNT 24
+ int ' Max DLCI per device' CONFIG_DLCI_MAX 8
+ dep_tristate ' SDLA (Sangoma S502/S508) support' CONFIG_SDLA $CONFIG_DLCI
+fi
+
+#
+# Wan router core.
+#
+
if [ "$CONFIG_WAN_ROUTER" != "n" ]; then
bool 'WAN drivers' CONFIG_WAN_DRIVERS
if [ "$CONFIG_WAN_DRIVERS" = "y" ]; then
@@ -247,6 +281,9 @@ if [ "$CONFIG_WAN_ROUTER" != "n" ]; then
fi
fi
fi
+
+endmenu
+
#
# X.25 network drivers
#
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 5e2a45bce..381ae5dfc 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -67,6 +67,14 @@ else
endif
endif
+ifeq ($(CONFIG_IBMOL),y)
+L_OBJS += olympic.o
+else
+ ifeq ($(CONFIG_IBMOL),m)
+ M_OBJS += olympic.o
+ endif
+endif
+
ifeq ($(CONFIG_SKTR),y)
L_OBJS += sktr.o
else
@@ -422,6 +430,14 @@ else
endif
endif
+ifeq ($(CONFIG_SUNBMAC),y)
+L_OBJS += sunbmac.o
+else
+ ifeq ($(CONFIG_SUNBMAC),m)
+ M_OBJS += sunbmac.o
+ endif
+endif
+
ifeq ($(CONFIG_MYRI_SBUS),y)
L_OBJS += myri_sbus.o
else
@@ -566,6 +582,14 @@ else
endif
endif
+ifeq ($(CONFIG_ARLAN),y)
+LX_OBJS += arlan.o arlan-proc.o
+else
+ ifeq ($(CONFIG_ARLAN),m)
+ MX_OBJS += arlan.o arlan-proc.o
+ endif
+endif
+
ifeq ($(CONFIG_TLAN),y)
L_OBJS += tlan.o
else
@@ -764,6 +788,19 @@ else
endif
endif
+ifeq ($(CONFIG_SEALEVEL_4021),y)
+L_OBJS += sealevel.o
+CONFIG_85230_BUILTIN = y
+CONFIG_SYNCPPP_BUILTIN = y
+else
+ ifeq ($(CONFIG_SEALEVEL_4021),m)
+ CONFIG_85230_MODULE = y
+ CONFIG_SYNCPPP_MODULE = y
+ M_OBJS += sealevel.o
+ endif
+endif
+
+
ifeq ($(CONFIG_COSA),y)
L_OBJS += cosa.o
CONFIG_SYNCPPP_BUILTIN = y
@@ -1064,15 +1101,6 @@ ifeq ($(CONFIG_CYCLADES_SYNC),y)
endif
endif
-ifeq ($(CONFIG_CYCLADES_SYNC),m)
- MX_OBJS += cycx_drv.o
- M_OBJS += cyclomx.o
- CYCLOMX_OBJS = cycx_main.o
- ifeq ($(CONFIG_CYCLOMX_X25),y)
- CYCLOMX_OBJS += cycx_x25.o
- endif
-endif
-
ifeq ($(CONFIG_X25_ASY),y)
L_OBJS += x25_asy.o
else
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index ce0e46784..fd660f2ab 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -67,6 +67,7 @@ extern int ewrk3_probe(struct device *);
extern int de4x5_probe(struct device *);
extern int el1_probe(struct device *);
extern int wavelan_probe(struct device *);
+extern int arlan_probe(struct device *);
extern int el16_probe(struct device *);
extern int elmc_probe(struct device *);
extern int skmca_probe(struct device *);
@@ -147,7 +148,7 @@ struct devprobe
* autoprobe (i.e. a probe that fails to find a card when autoprobing
* will not be asked to autoprobe again). It exits when a card is found.
*/
-__initfunc(static int probe_list(struct device *dev, struct devprobe *plist))
+static int __init probe_list(struct device *dev, struct devprobe *plist)
{
struct devprobe *p = plist;
unsigned long base_addr = dev->base_addr;
@@ -359,6 +360,9 @@ struct devprobe isa_probes[] __initdata = {
#ifdef CONFIG_WAVELAN /* WaveLAN */
{wavelan_probe, 0},
#endif
+#ifdef CONFIG_ARLAN /* Aironet */
+ {arlan_probe, 0},
+#endif
#ifdef CONFIG_EL16 /* 3c507 */
{el16_probe, 0},
#endif
@@ -474,7 +478,7 @@ struct devprobe arm_probes[] __initdata = {
* Unified ethernet device probe, segmented per architecture and
* per bus interface.
*/
-__initfunc(static int ethif_probe(struct device *dev))
+static int __init ethif_probe(struct device *dev)
{
unsigned long base_addr = dev->base_addr;
@@ -522,7 +526,7 @@ __initfunc(static int ethif_probe(struct device *dev))
}
#ifdef CONFIG_FDDI
-__initfunc(static int fddiif_probe(struct device *dev))
+static int __init fddiif_probe(struct device *dev)
{
unsigned long base_addr = dev->base_addr;
@@ -719,6 +723,7 @@ struct device eql_dev = {
#ifdef CONFIG_TR
/* Token-ring device probe */
extern int ibmtr_probe(struct device *);
+extern int olympic_probe(struct device *);
static int
trif_probe(struct device *dev)
@@ -727,6 +732,9 @@ trif_probe(struct device *dev)
#ifdef CONFIG_IBMTR
&& ibmtr_probe(dev)
#endif
+#ifdef CONFIG_IBMOL
+ && olympic_probe(dev)
+#endif
#ifdef CONFIG_SKTR
&& sktr_probe(dev)
#endif
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index 037fc8209..348b2e790 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -739,8 +739,7 @@ static void lance_set_multicast (struct device *dev)
mark_bh(NET_BH);
}
-
-__initfunc(int a2065_probe(struct device *dev))
+int __init a2065_probe(struct device *dev)
{
unsigned int key, is_cbm;
const struct ConfigDev *cd;
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index e5e2f572f..8f1246d85 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -95,7 +95,7 @@ static int ac_close_card(struct device *dev);
or the unique value in the station address PROM.
*/
-__initfunc(int ac3200_probe(struct device *dev))
+int __init ac3200_probe(struct device *dev)
{
unsigned short ioaddr = dev->base_addr;
@@ -117,7 +117,7 @@ __initfunc(int ac3200_probe(struct device *dev))
return ENODEV;
}
-__initfunc(static int ac_probe1(int ioaddr, struct device *dev))
+static int __init ac_probe1(int ioaddr, struct device *dev)
{
int i;
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 3cdc89475..38fa4b98f 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -177,7 +177,7 @@ static struct device *root_dev = NULL;
static int probed __initdata = 0;
-__initfunc(int acenic_probe (struct device *dev))
+int __init acenic_probe (struct device *dev)
{
int boards_found = 0;
int version_disp;
@@ -423,7 +423,7 @@ static inline void ace_issue_cmd(struct ace_regs *regs, struct cmd *cmd)
}
-__initfunc(static int ace_init(struct device *dev, int board_idx))
+static int __init ace_init(struct device *dev, int board_idx)
{
struct ace_private *ap;
struct ace_regs *regs;
@@ -1574,7 +1574,7 @@ static struct net_device_stats *ace_get_stats(struct device *dev)
}
-__initfunc(void ace_copy(struct ace_regs *regs, void *src, u32 dest, int size))
+void __init ace_copy(struct ace_regs *regs, void *src, u32 dest, int size)
{
unsigned long tdest;
u32 *wsrc;
@@ -1609,7 +1609,7 @@ __initfunc(void ace_copy(struct ace_regs *regs, void *src, u32 dest, int size))
}
-__initfunc(void ace_clear(struct ace_regs *regs, u32 dest, int size))
+void __init ace_clear(struct ace_regs *regs, u32 dest, int size)
{
unsigned long tdest;
short tsize = 0, i;
@@ -1642,7 +1642,7 @@ __initfunc(void ace_clear(struct ace_regs *regs, u32 dest, int size))
* This operation requires the NIC to be halted and is performed with
* interrupts disabled and with the spinlock hold.
*/
-__initfunc(int ace_load_firmware(struct device *dev))
+int __init ace_load_firmware(struct device *dev)
{
struct ace_private *ap;
struct ace_regs *regs;
diff --git a/drivers/net/apne.c b/drivers/net/apne.c
index f4e682f4d..28ac93605 100644
--- a/drivers/net/apne.c
+++ b/drivers/net/apne.c
@@ -121,7 +121,7 @@ static const char *version =
static int apne_owned = 0; /* signal if card already owned */
-__initfunc(int apne_probe(struct device *dev))
+int __init apne_probe(struct device *dev)
{
#ifndef MANUAL_CONFIG
char tuple[8];
@@ -161,8 +161,7 @@ __initfunc(int apne_probe(struct device *dev))
}
-
-__initfunc(static int apne_probe1(struct device *dev, int ioaddr))
+static int __init apne_probe1(struct device *dev, int ioaddr)
{
int i;
unsigned char SA_prom[32];
diff --git a/drivers/net/arc-rimi.c b/drivers/net/arc-rimi.c
index d27fbee7c..c0c8161ae 100644
--- a/drivers/net/arc-rimi.c
+++ b/drivers/net/arc-rimi.c
@@ -100,7 +100,7 @@ MODULE_PARM(irq, "i");
MODULE_PARM(device, "s");
MODULE_PARM (node, "i");
#else
-__initfunc(void arcrimi_setup (char *str, int *ints));
+void __init arcrimi_setup (char *str, int *ints);
extern struct device arcnet_devs[];
extern char arcnet_dev_names[][10];
extern int arcnet_num_devs;
@@ -140,7 +140,7 @@ static const char *version =
* them. In fact, we can't even get their node ID automatically. So, we
* need to be passed a specific shmem address, IRQ, and node ID.
*/
-__initfunc(int arcrimi_probe(struct device *dev))
+int __init arcrimi_probe(struct device *dev)
{
BUGLVL(D_NORMAL) printk(version);
BUGMSG(D_NORMAL,"Given: node %02Xh, shmem %lXh, irq %d\n",
@@ -167,7 +167,7 @@ __initfunc(int arcrimi_probe(struct device *dev))
/* Set up the struct device associated with this card. Called after
* probing succeeds.
*/
-__initfunc(int arcrimi_found(struct device *dev,int node,int airq, u_long shmem))
+int __init arcrimi_found(struct device *dev,int node,int airq, u_long shmem)
{
struct arcnet_local *lp;
u_long first_mirror,last_mirror;
@@ -797,7 +797,7 @@ void cleanup_module(void)
#else
-__initfunc(void arcrimi_setup (char *str, int *ints))
+void __init arcrimi_setup (char *str, int *ints)
{
struct device *dev;
diff --git a/drivers/net/arcnet.c b/drivers/net/arcnet.c
index 491a50257..5e61ca6bc 100644
--- a/drivers/net/arcnet.c
+++ b/drivers/net/arcnet.c
@@ -471,9 +471,16 @@ arcnet_open(struct device *dev)
#ifdef CONFIG_ARCNET_1051
/* Initialize the RFC1051-encap protocol driver */
- lp->sdev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
+ lp->sdev=(struct device *)kmalloc(sizeof(struct device)+10,GFP_KERNEL);
+ if(lp->sdev = NULL)
+ {
+ if(lp->edev)
+ kfree(lp->edev);
+ lp->edev=NULL;
+ return -ENOMEM;
+ }
memcpy(lp->sdev,dev,sizeof(struct device));
- lp->sdev->name=(char *)kmalloc(10,GFP_KERNEL);
+ lp->sdev->name=(char *)(lp+1);
sprintf(lp->sdev->name,"%ss",dev->name);
lp->sdev->init=arcnetS_init;
register_netdevice(lp->sdev);
@@ -562,7 +569,6 @@ arcnet_close(struct device *dev)
/* free the RFC1051-encap protocol device */
lp->sdev->priv=NULL;
unregister_netdevice(lp->sdev);
- kfree(lp->sdev->name);
kfree(lp->sdev);
lp->sdev=NULL;
#endif
@@ -1991,7 +1997,7 @@ struct device arcnet_devs[MAX_ARCNET_DEVS];
int arcnet_num_devs=0;
char arcnet_dev_names[MAX_ARCNET_DEVS][10];
-__initfunc(void arcnet_init(void))
+void __init arcnet_init(void)
{
int c;
@@ -2041,7 +2047,7 @@ __initfunc(void arcnet_init(void))
#ifdef MODULE
int init_module(void)
#else
-__initfunc(static int init_module(void))
+static int __init init_module(void)
#endif
{
#ifdef ALPHA_WARNING
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index 8a1cd4e9d..e08455cf8 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -146,7 +146,7 @@ static void memcpyw(u_short *dest, u_short *src, int len)
}
-__initfunc(int ariadne_probe(struct device *dev))
+int __init ariadne_probe(struct device *dev)
{
unsigned int key;
const struct ConfigDev *cd;
diff --git a/drivers/net/ariadne2.c b/drivers/net/ariadne2.c
index c58a90932..fc02ecbb5 100644
--- a/drivers/net/ariadne2.c
+++ b/drivers/net/ariadne2.c
@@ -81,8 +81,7 @@ static void ariadne2_block_output(struct device *dev, const int count,
const unsigned char *buf,
const int start_page);
-
-__initfunc(int ariadne2_probe(struct device *dev))
+int __init ariadne2_probe(struct device *dev)
{
unsigned int key;
const struct ConfigDev *cd;
@@ -101,8 +100,8 @@ __initfunc(int ariadne2_probe(struct device *dev))
return -ENODEV;
}
-__initfunc(static int ariadne2_init(struct device *dev, unsigned int key,
- unsigned long board))
+static int __init ariadne2_init(struct device *dev, unsigned int key,
+ unsigned long board)
{
int i;
unsigned char SA_prom[32];
diff --git a/drivers/net/arlan-proc.c b/drivers/net/arlan-proc.c
new file mode 100644
index 000000000..2d48479e0
--- /dev/null
+++ b/drivers/net/arlan-proc.c
@@ -0,0 +1,1059 @@
+#include <linux/config.h>
+#include "arlan.h"
+
+#ifdef CONFIG_PROC_FS
+
+
+#include <linux/sysctl.h>
+#include <linux/version.h>
+
+/* void enableReceive(struct device* dev);
+*/
+
+static int arlan_command(struct device * dev, int command);
+
+
+#define ARLAN_STR_SIZE 0x2ff0
+#define DEV_ARLAN_INFO 1
+#define DEV_ARLAN 1
+#define SARLG(type,var) {\
+ pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x%x\n", #var, READSHMB(priva->card->var)); \
+ }
+
+#define SARLBN(type,var,nn) {\
+ pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x",#var);\
+ for (i=0; i < nn; i++ ) pos += sprintf(arlan_drive_info+pos, "%02x",READSHMB(priva->card->var[i]));\
+ pos += sprintf(arlan_drive_info+pos, "\n"); \
+ }
+
+#define SARLBNpln(type,var,nn) {\
+ for (i=0; i < nn; i++ ) pos += sprintf(arlan_drive_info+pos, "%02x",READSHMB(priva->card->var[i]));\
+ }
+
+#define SARLSTR(var,nn) {\
+ char tmpStr[400];\
+ int tmpLn = nn;\
+ if (nn > 399 ) tmpLn = 399; \
+ memcpy(tmpStr,(char *) priva->conf->var,tmpLn);\
+ tmpStr[tmpLn] = 0; \
+ pos += sprintf(arlan_drive_info+pos, "%s\t=\t%s \n",#var,priva->conf->var);\
+ }
+
+#define SARLUC(var) SARLG(u_char, var)
+#define SARLUCN(var,nn) SARLBN(u_char,var, nn)
+#define SARLUS(var) SARLG(u_short, var)
+#define SARLUSN(var,nn) SARLBN(u_short,var, nn)
+#define SARLUI(var) SARLG(u_int, var)
+
+#define SARLUSA(var) {\
+ u_short tmpVar;\
+ memcpy(&tmpVar, (short *) priva->conf->var,2); \
+ pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x%x\n",#var, tmpVar);\
+}
+
+#define SARLUIA(var) {\
+ u_int tmpVar;\
+ memcpy(&tmpVar, (int* )priva->conf->var,4); \
+ pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x%x\n",#var, tmpVar);\
+}
+
+
+const char *arlan_diagnostic_info_string(struct device *dev)
+{
+
+ volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+ u_char diagnosticInfo;
+
+ READSHM(diagnosticInfo, arlan->diagnosticInfo, u_char);
+
+ switch (diagnosticInfo)
+ {
+ case 0xFF:
+ return "Diagnostic info is OK";
+ case 0xFE:
+ return "ERROR EPROM Checksum error ";
+ case 0xFD:
+ return "ERROR Local Ram Test Failed ";
+ case 0xFC:
+ return "ERROR SCC failure ";
+ case 0xFB:
+ return "ERROR BackBone failure ";
+ case 0xFA:
+ return "ERROR tranceiver not found ";
+ case 0xF9:
+ return "ERROR no more address space ";
+ case 0xF8:
+ return "ERROR Checksum error ";
+ case 0xF7:
+ return "ERROR Missing SS Code";
+ case 0xF6:
+ return "ERROR Invalid config format";
+ case 0xF5:
+ return "ERROR Reserved errorcode F5";
+ case 0xF4:
+ return "ERROR Invalid spreading code/channel number";
+ case 0xF3:
+ return "ERROR Load Code Error";
+ case 0xF2:
+ return "ERROR Reserver errorcode F2 ";
+ case 0xF1:
+ return "ERROR Invalid command receivec by LAN card ";
+ case 0xF0:
+ return "ERROR Invalid parameter found in command ";
+ case 0xEF:
+ return "ERROR On-chip timer failure ";
+ case 0xEE:
+ return "ERROR T410 timer failure ";
+ case 0xED:
+ return "ERROR Too Many TxEnable commands ";
+ case 0xEC:
+ return "ERROR EEPROM error on radio module ";
+ default:
+ return "ERROR unknown Diagnostic info reply code ";
+ }
+};
+
+static const char *arlan_hardware_type_string(struct device *dev)
+{
+ u_char hardwareType;
+ volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+
+ READSHM(hardwareType, arlan->hardwareType, u_char);
+ switch (hardwareType)
+ {
+ case 0x00:
+ return "type A450";
+ case 0x01:
+ return "type A650 ";
+ case 0x04:
+ return "type TMA coproc";
+ case 0x0D:
+ return "type A650E ";
+ case 0x18:
+ return "type TMA coproc Australian";
+ case 0x19:
+ return "type A650A ";
+ case 0x26:
+ return "type TMA coproc European";
+ case 0x2E:
+ return "type A655 ";
+ case 0x2F:
+ return "type A655A ";
+ case 0x30:
+ return "type A655E ";
+ case 0x0B:
+ return "type A670 ";
+ case 0x0C:
+ return "type A670E ";
+ case 0x2D:
+ return "type A670A ";
+ case 0x0F:
+ return "type A411T";
+ case 0x16:
+ return "type A411TA";
+ case 0x1B:
+ return "type A440T";
+ case 0x1C:
+ return "type A412T";
+ case 0x1E:
+ return "type A412TA";
+ case 0x22:
+ return "type A411TE";
+ case 0x24:
+ return "type A412TE";
+ case 0x27:
+ return "type A671T ";
+ case 0x29:
+ return "type A671TA ";
+ case 0x2B:
+ return "type A671TE ";
+ case 0x31:
+ return "type A415T ";
+ case 0x33:
+ return "type A415TA ";
+ case 0x35:
+ return "type A415TE ";
+ case 0x37:
+ return "type A672";
+ case 0x39:
+ return "type A672A ";
+ case 0x3B:
+ return "type A672T";
+ case 0x6B:
+ return "type IC2200";
+ default:
+ return "type A672T";
+ }
+}
+
+static void arlan_print_diagnostic_info(struct device *dev)
+{
+ int i;
+ u_char diagnosticInfo;
+ u_short diagnosticOffset;
+ u_char hardwareType;
+ volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+
+ // ARLAN_DEBUG_ENTRY("arlan_print_diagnostic_info");
+
+ if (READSHMB(arlan->configuredStatusFlag) == 0)
+ printk("Arlan: Card NOT configured\n");
+ else
+ printk("Arlan: Card is configured\n");
+
+ READSHM(diagnosticInfo, arlan->diagnosticInfo, u_char);
+ READSHM(diagnosticOffset, arlan->diagnosticOffset, u_short);
+
+ printk(KERN_INFO "%s\n", arlan_diagnostic_info_string(dev));
+
+ if (diagnosticInfo != 0xff)
+ printk("%s arlan: Diagnostic Offset %d \n", dev->name, diagnosticOffset);
+
+ printk("arlan: LAN CODE ID = ");
+ for (i = 0; i < 6; i++)
+ DEBUGSHM(1, "%03d:", arlan->lanCardNodeId[i], u_char);
+ printk("\n");
+
+ printk("arlan: Arlan BroadCast address = ");
+ for (i = 0; i < 6; i++)
+ DEBUGSHM(1, "%03d:", arlan->broadcastAddress[i], u_char);
+ printk("\n");
+
+ READSHM(hardwareType, arlan->hardwareType, u_char);
+ printk(KERN_INFO "%s\n", arlan_hardware_type_string(dev));
+
+
+ DEBUGSHM(1, "arlan: channelNumber=%d\n", arlan->channelNumber, u_char);
+ DEBUGSHM(1, "arlan: channelSet=%d\n", arlan->channelSet, u_char);
+ DEBUGSHM(1, "arlan: spreadingCode=%d\n", arlan->spreadingCode, u_char);
+ DEBUGSHM(1, "arlan: radioNodeId=%d\n", arlan->radioNodeId, u_short);
+ DEBUGSHM(1, "arlan: SID =%d\n", arlan->SID, u_short);
+ DEBUGSHM(1, "arlan: rxOffset=%d\n", arlan->rxOffset, u_short);
+
+ DEBUGSHM(1, "arlan: registration mode is %d\n", arlan->registrationMode, u_char);
+
+ printk("arlan: name= ");
+ IFDEBUG(1)
+
+ for (i = 0; i < 16; i++)
+ {
+ char c;
+ READSHM(c, arlan->name[i], char);
+ if (c)
+ printk("%c", c);
+ }
+ printk("\n");
+
+// ARLAN_DEBUG_EXIT("arlan_print_diagnostic_info");
+
+}
+
+
+/****************************** TEST MEMORY **************/
+
+static int arlan_hw_test_memory(struct device *dev)
+{
+ u_char *ptr;
+ int i;
+ int memlen = sizeof(struct arlan_shmem) - 0xF; /* avoid control register */
+ volatile char *arlan_mem = (char *) (dev->mem_start);
+ volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+ char pattern;
+
+ ptr = NULL;
+
+ /* hold card in reset state */
+ setHardwareReset(dev);
+
+ /* test memory */
+ pattern = 0;
+ for (i = 0; i < memlen; i++)
+ WRITESHM(arlan_mem[i], ((u_char) pattern++), u_char);
+
+ pattern = 0;
+ for (i = 0; i < memlen; i++)
+ {
+ char res;
+ READSHM(res, arlan_mem[i], char);
+ if (res != pattern++)
+ {
+ printk(KERN_ERR "Arlan driver memory test 1 failed \n");
+ return -1;
+ }
+ }
+
+ pattern = 0;
+ for (i = 0; i < memlen; i++)
+ WRITESHM(arlan_mem[i], ~(pattern++), char);
+
+ pattern = 0;
+ for (i = 0; i < memlen; i++)
+ {
+ char res;
+ READSHM(res, arlan_mem[i], char);
+ if (res != ~(pattern++))
+ {
+ printk(KERN_ERR "Arlan driver memory test 2 failed \n");
+ return -1;
+ }
+ }
+
+ /* zero memory */
+ for (i = 0; i < memlen; i++)
+ WRITESHM(arlan_mem[i], 0x00, char);
+
+ IFDEBUG(1) printk(KERN_INFO "Arlan: memory tests ok\n");
+
+ /* set reset flag and then release reset */
+ WRITESHM(arlan->resetFlag, 0xff, u_char);
+
+ clearChannelAttention(dev);
+ clearHardwareReset(dev);
+
+ /* wait for reset flag to become zero, we'll wait for two seconds */
+ if (arlan_command(dev, ARLAN_COMMAND_LONG_WAIT_NOW))
+ {
+ printk(KERN_ERR "%s arlan: failed to come back from memory test\n", dev->name);
+ return -1;
+ }
+ return 0;
+}
+
+
+static int arlan_setup_card_by_book(struct device *dev)
+{
+ u_char irqLevel, configuredStatusFlag;
+ volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+
+// ARLAN_DEBUG_ENTRY("arlan_setup_card");
+
+ READSHM(configuredStatusFlag, arlan->configuredStatusFlag, u_char);
+
+ IFDEBUG(10)
+ if (configuredStatusFlag != 0)
+ IFDEBUG(10) printk("arlan: CARD IS CONFIGURED\n");
+ else
+ IFDEBUG(10) printk("arlan: card is NOT configured\n");
+
+ if (testMemory || (READSHMB(arlan->diagnosticInfo) != 0xff))
+ if (arlan_hw_test_memory(dev))
+ return -1;
+
+ DEBUGSHM(4, "arlan configuredStatus = %d \n", arlan->configuredStatusFlag, u_char);
+ DEBUGSHM(4, "arlan driver diagnostic: 0x%2x\n", arlan->diagnosticInfo, u_char);
+
+ /* issue nop command - no interupt */
+ arlan_command(dev, ARLAN_COMMAND_NOOP);
+ if (arlan_command(dev, ARLAN_COMMAND_WAIT_NOW) != 0)
+ return -1;
+
+ IFDEBUG(50) printk("1st Noop successfully executed !!\n");
+
+ /* try to turn on the arlan interrupts */
+ clearClearInterrupt(dev);
+ setClearInterrupt(dev);
+ setInterruptEnable(dev);
+
+ /* issue nop command - with interrupt */
+
+ arlan_command(dev, ARLAN_COMMAND_NOOPINT);
+ if (arlan_command(dev, ARLAN_COMMAND_WAIT_NOW) != 0)
+ return -1;
+
+
+ IFDEBUG(50) printk("2nd Noop successfully executed !!\n");
+
+ READSHM(irqLevel, arlan->irqLevel, u_char)
+
+ if (irqLevel != dev->irq)
+ {
+ IFDEBUG(1) printk(KERN_WARNING "arlan dip switches set irq to %d\n", irqLevel);
+ printk(KERN_WARNING "device driver irq set to %d - does not match\n", dev->irq);
+ dev->irq = irqLevel;
+ }
+ else
+ IFDEBUG(2) printk("irq level is OK\n");
+
+
+ IFDEBUG(3) arlan_print_diagnostic_info(dev);
+
+ arlan_command(dev, ARLAN_COMMAND_CONF);
+
+ READSHM(configuredStatusFlag, arlan->configuredStatusFlag, u_char);
+ if (configuredStatusFlag == 0)
+ {
+ printk(KERN_WARNING "arlan configure failed\n");
+ return -1;
+ }
+ arlan_command(dev, ARLAN_COMMAND_LONG_WAIT_NOW);
+ arlan_command(dev, ARLAN_COMMAND_RX);
+ arlan_command(dev, ARLAN_COMMAND_LONG_WAIT_NOW);
+ printk(KERN_NOTICE "%s: arlan driver version %s loaded\n",
+ dev->name, arlan_version);
+
+// ARLAN_DEBUG_EXIT("arlan_setup_card");
+
+ return 0; /* no errors */
+}
+
+
+#ifdef ARLAN_PROC_INTERFACE
+#ifdef ARLAN_PROC_SHM_DUMP
+
+static char arlan_drive_info[ARLAN_STR_SIZE] = "A655\n\0";
+
+static int arlan_sysctl_info(ctl_table * ctl, int write, struct file *filp,
+ void *buffer, size_t * lenp)
+{
+ int i;
+ int retv, pos, devnum;
+ struct arlan_private *priva = NULL;
+ struct device *dev;
+ pos = 0;
+ if (write)
+ {
+ printk("wrirte: ");
+ for (i = 0; i < 100; i++)
+ printk("adi %x \n", arlan_drive_info[i]);
+ }
+ if (ctl->procname == NULL || arlan_drive_info == NULL)
+ {
+ printk(KERN_WARNING " procname is NULL in sysctl_table or arlan_drive_info is NULL \n at arlan module\n ");
+ return -1;
+ }
+ devnum = ctl->procname[5] - '0';
+ if (devnum < 0 || devnum > MAX_ARLANS - 1)
+ {
+ printk(KERN_WARNING "too strange devnum in procfs parse\n ");
+ return -1;
+ }
+ else if (arlan_device[devnum] == NULL)
+ {
+ if (ctl->procname)
+ pos += sprintf(arlan_drive_info + pos, "\t%s\n\n", ctl->procname);
+ pos += sprintf(arlan_drive_info + pos, "No device found here \n");
+ goto final;
+ }
+ else
+ priva = arlan_device[devnum]->priv;
+
+ if (priva == NULL)
+ {
+ printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n ");
+ return -1;
+ }
+ dev = arlan_device[devnum];
+
+ memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem));
+
+ pos = sprintf(arlan_drive_info, "Arlan info \n");
+ /* Header Signature */
+ SARLSTR(textRegion, 48);
+ SARLUC(resetFlag);
+ pos += sprintf(arlan_drive_info + pos, "diagnosticInfo\t=\t%s \n", arlan_diagnostic_info_string(dev));
+ SARLUC(diagnosticInfo);
+ SARLUS(diagnosticOffset);
+ SARLUCN(_1, 12);
+ SARLUCN(lanCardNodeId, 6);
+ SARLUCN(broadcastAddress, 6);
+ pos += sprintf(arlan_drive_info + pos, "hardwareType =\t %s \n", arlan_hardware_type_string(dev));
+ SARLUC(hardwareType);
+ SARLUC(majorHardwareVersion);
+ SARLUC(minorHardwareVersion);
+ SARLUC(radioModule);
+ SARLUC(defaultChannelSet);
+ SARLUCN(_2, 47);
+
+ /* Control/Status Block - 0x0080 */
+ SARLUC(interruptInProgress);
+ SARLUC(cntrlRegImage);
+
+ SARLUCN(_3, 14);
+ SARLUC(commandByte);
+ SARLUCN(commandParameter, 15);
+
+ /* Receive Status - 0x00a0 */
+ SARLUC(rxStatus);
+ SARLUC(rxFrmType);
+ SARLUS(rxOffset);
+ SARLUS(rxLength);
+ SARLUCN(rxSrc, 6);
+ SARLUC(rxBroadcastFlag);
+ SARLUC(rxQuality);
+ SARLUC(scrambled);
+ SARLUCN(_4, 1);
+
+ /* Transmit Status - 0x00b0 */
+ SARLUC(txStatus);
+ SARLUC(txAckQuality);
+ SARLUC(numRetries);
+ SARLUCN(_5, 14);
+ SARLUCN(registeredRouter, 6);
+ SARLUCN(backboneRouter, 6);
+ SARLUC(registrationStatus);
+ SARLUC(configuredStatusFlag);
+ SARLUCN(_6, 1);
+ SARLUCN(ultimateDestAddress, 6);
+ SARLUCN(immedDestAddress, 6);
+ SARLUCN(immedSrcAddress, 6);
+ SARLUS(rxSequenceNumber);
+ SARLUC(assignedLocaltalkAddress);
+ SARLUCN(_7, 27);
+
+ /* System Parameter Block */
+
+ /* - Driver Parameters (Novell Specific) */
+
+ SARLUS(txTimeout);
+ SARLUS(transportTime);
+ SARLUCN(_8, 4);
+
+ /* - Configuration Parameters */
+ SARLUC(irqLevel);
+ SARLUC(spreadingCode);
+ SARLUC(channelSet);
+ SARLUC(channelNumber);
+ SARLUS(radioNodeId);
+ SARLUCN(_9, 2);
+ SARLUC(scramblingDisable);
+ SARLUC(radioType);
+ SARLUS(routerId);
+ SARLUCN(_10, 9);
+ SARLUC(txAttenuation);
+ SARLUIA(systemId);
+ SARLUS(globalChecksum);
+ SARLUCN(_11, 4);
+ SARLUS(maxDatagramSize);
+ SARLUS(maxFrameSize);
+ SARLUC(maxRetries);
+ SARLUC(receiveMode);
+ SARLUC(priority);
+ SARLUC(rootOrRepeater);
+ SARLUCN(specifiedRouter, 6);
+ SARLUS(fastPollPeriod);
+ SARLUC(pollDecay);
+ SARLUSA(fastPollDelay);
+ SARLUC(arlThreshold);
+ SARLUC(arlDecay);
+ SARLUCN(_12, 1);
+ SARLUS(specRouterTimeout);
+ SARLUCN(_13, 5);
+
+ /* Scrambled Area */
+ SARLUIA(SID);
+ SARLUCN(encryptionKey, 12);
+ SARLUIA(_14);
+ SARLUSA(waitTime);
+ SARLUSA(lParameter);
+ SARLUCN(_15, 3);
+ SARLUS(headerSize);
+ SARLUS(sectionChecksum);
+
+ SARLUC(registrationMode);
+ SARLUC(registrationFill);
+ SARLUS(pollPeriod);
+ SARLUS(refreshPeriod);
+ SARLSTR(name, 16);
+ SARLUCN(NID, 6);
+ SARLUC(localTalkAddress);
+ SARLUC(codeFormat);
+ SARLUC(numChannels);
+ SARLUC(channel1);
+ SARLUC(channel2);
+ SARLUC(channel3);
+ SARLUC(channel4);
+ SARLUCN(SSCode, 59);
+
+/* SARLUCN( _16, 0x140);
+ */
+ /* Statistics Block - 0x0300 */
+ SARLUC(hostcpuLock);
+ SARLUC(lancpuLock);
+ SARLUCN(resetTime, 18);
+ SARLUIA(numDatagramsTransmitted);
+ SARLUIA(numReTransmissions);
+ SARLUIA(numFramesDiscarded);
+ SARLUIA(numDatagramsReceived);
+ SARLUIA(numDuplicateReceivedFrames);
+ SARLUIA(numDatagramsDiscarded);
+ SARLUS(maxNumReTransmitDatagram);
+ SARLUS(maxNumReTransmitFrames);
+ SARLUS(maxNumConsecutiveDuplicateFrames);
+ /* misaligned here so we have to go to characters */
+ SARLUIA(numBytesTransmitted);
+ SARLUIA(numBytesReceived);
+ SARLUIA(numCRCErrors);
+ SARLUIA(numLengthErrors);
+ SARLUIA(numAbortErrors);
+ SARLUIA(numTXUnderruns);
+ SARLUIA(numRXOverruns);
+ SARLUIA(numHoldOffs);
+ SARLUIA(numFramesTransmitted);
+ SARLUIA(numFramesReceived);
+ SARLUIA(numReceiveFramesLost);
+ SARLUIA(numRXBufferOverflows);
+ SARLUIA(numFramesDiscardedAddrMismatch);
+ SARLUIA(numFramesDiscardedSIDMismatch);
+ SARLUIA(numPollsTransmistted);
+ SARLUIA(numPollAcknowledges);
+ SARLUIA(numStatusTimeouts);
+ SARLUIA(numNACKReceived);
+ SARLUS(auxCmd);
+ SARLUCN(dumpPtr, 4);
+ SARLUC(dumpVal);
+ SARLUC(wireTest);
+
+ /* next 4 seems too long for procfs, over single page ?
+ SARLUCN( _17, 0x86);
+ SARLUCN( txBuffer, 0x800);
+ SARLUCN( rxBuffer, 0x800);
+ SARLUCN( _18, 0x0bff);
+ */
+
+ pos += sprintf(arlan_drive_info + pos, "rxRing\t=\t0x");
+ for (i = 0; i < 0x50; i++)
+ pos += sprintf(arlan_drive_info + pos, "%02x", ((char *) priva->conf)[priva->conf->rxOffset + i]);
+ pos += sprintf(arlan_drive_info + pos, "\n");
+
+ SARLUC(configStatus);
+ SARLUC(_22);
+ SARLUC(progIOCtrl);
+ SARLUC(shareMBase);
+ SARLUC(controlRegister);
+
+ pos += sprintf(arlan_drive_info + pos, " total %d chars\n", pos);
+ if (ctl)
+ if (ctl->procname)
+ pos += sprintf(arlan_drive_info + pos, " driver name : %s\n", ctl->procname);
+final:
+ *lenp = pos;
+
+ if (!write)
+ retv = proc_dostring(ctl, write, filp, buffer, lenp);
+ else
+ {
+ *lenp = 0;
+ return -1;
+ }
+ return retv;
+}
+
+
+static int arlan_sysctl_info161719(ctl_table * ctl, int write, struct file *filp,
+ void *buffer, size_t * lenp)
+{
+ int i;
+ int retv, pos, devnum;
+ struct arlan_private *priva = NULL;
+
+ pos = 0;
+ devnum = ctl->procname[5] - '0';
+ if (arlan_device[devnum] == NULL)
+ {
+ pos += sprintf(arlan_drive_info + pos, "No device found here \n");
+ goto final;
+ }
+ else
+ priva = arlan_device[devnum]->priv;
+ if (priva == NULL)
+ {
+ printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n ");
+ return -1;
+ }
+ memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem));
+ SARLUCN(_16, 0xC0);
+ SARLUCN(_17, 0x6A);
+ SARLUCN(_18, 14);
+ SARLUCN(_19, 0x86);
+ SARLUCN(_21, 0x3fd);
+
+final:
+ *lenp = pos;
+ retv = proc_dostring(ctl, write, filp, buffer, lenp);
+ return retv;
+}
+
+static int arlan_sysctl_infotxRing(ctl_table * ctl, int write, struct file *filp,
+ void *buffer, size_t * lenp)
+{
+ int i;
+ int retv, pos, devnum;
+ struct arlan_private *priva = NULL;
+
+ pos = 0;
+ devnum = ctl->procname[5] - '0';
+ if (arlan_device[devnum] == NULL)
+ {
+ pos += sprintf(arlan_drive_info + pos, "No device found here \n");
+ goto final;
+ }
+ else
+ priva = arlan_device[devnum]->priv;
+ if (priva == NULL)
+ {
+ printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n ");
+ return -1;
+ }
+ memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem));
+ SARLBNpln(u_char, txBuffer, 0x800);
+final:
+ *lenp = pos;
+ retv = proc_dostring(ctl, write, filp, buffer, lenp);
+ return retv;
+}
+
+static int arlan_sysctl_inforxRing(ctl_table * ctl, int write, struct file *filp,
+ void *buffer, size_t * lenp)
+{
+ int i;
+ int retv, pos, devnum;
+ struct arlan_private *priva = NULL;
+
+ pos = 0;
+ devnum = ctl->procname[5] - '0';
+ if (arlan_device[devnum] == NULL)
+ {
+ pos += sprintf(arlan_drive_info + pos, "No device found here \n");
+ goto final;
+ } else
+ priva = arlan_device[devnum]->priv;
+ if (priva == NULL)
+ {
+ printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n ");
+ return -1;
+ }
+ memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem));
+ SARLBNpln(u_char, rxBuffer, 0x800);
+final:
+ *lenp = pos;
+ retv = proc_dostring(ctl, write, filp, buffer, lenp);
+ return retv;
+}
+
+static int arlan_sysctl_info18(ctl_table * ctl, int write, struct file *filp,
+ void *buffer, size_t * lenp)
+{
+ int i;
+ int retv, pos, devnum;
+ struct arlan_private *priva = NULL;
+
+ pos = 0;
+ devnum = ctl->procname[5] - '0';
+ if (arlan_device[devnum] == NULL)
+ {
+ pos += sprintf(arlan_drive_info + pos, "No device found here \n");
+ goto final;
+ }
+ else
+ priva = arlan_device[devnum]->priv;
+ if (priva == NULL)
+ {
+ printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n ");
+ return -1;
+ }
+ memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem));
+ SARLBNpln(u_char, _18, 0x800);
+
+final:
+ *lenp = pos;
+ retv = proc_dostring(ctl, write, filp, buffer, lenp);
+ return retv;
+}
+
+
+#endif /* #ifdef ARLAN_PROC_SHM_DUMP */
+
+
+static char conf_reset_result[200];
+
+static int arlan_configure(ctl_table * ctl, int write, struct file *filp,
+ void *buffer, size_t * lenp)
+{
+ int pos = 0;
+ int devnum = ctl->procname[6] - '0';
+ struct arlan_private *priv;
+
+ if (devnum < 0 || devnum > MAX_ARLANS - 1)
+ {
+ printk(KERN_WARNING "too strange devnum in procfs parse\n ");
+ return -1;
+ }
+ else if (arlan_device[devnum] != NULL)
+ {
+ priv = arlan_device[devnum]->priv;
+
+ arlan_command(arlan_device[devnum], ARLAN_COMMAND_CLEAN_AND_CONF);
+ }
+ else
+ return -1;
+
+ *lenp = pos;
+ return proc_dostring(ctl, write, filp, buffer, lenp);
+}
+
+int arlan_sysctl_reset(ctl_table * ctl, int write, struct file *filp,
+ void *buffer, size_t * lenp)
+{
+ int pos = 0;
+ int devnum = ctl->procname[5] - '0';
+ struct arlan_private *priv;
+
+ if (devnum < 0 || devnum > MAX_ARLANS - 1)
+ {
+ printk(KERN_WARNING "too strange devnum in procfs parse\n ");
+ return -1;
+ }
+ else if (arlan_device[devnum] != NULL)
+ {
+ priv = arlan_device[devnum]->priv;
+ arlan_command(arlan_device[devnum], ARLAN_COMMAND_CLEAN_AND_RESET);
+
+ } else
+ return -1;
+ *lenp = pos + 3;
+ return proc_dostring(ctl, write, filp, buffer, lenp);
+}
+
+
+/* Place files in /proc/sys/dev/arlan */
+#define CTBLN(num,card,nam) \
+ {num , #nam, &(arlan_conf[card].nam), \
+ sizeof(int), 0600, NULL, &proc_dointvec}
+
+
+#define ARLAN_SYSCTL_TABLE_TOTAL(cardNo)\
+ CTBLN(1,cardNo,spreadingCode),\
+ CTBLN(2,cardNo, channelNumber),\
+ CTBLN(3,cardNo, scramblingDisable),\
+ CTBLN(4,cardNo, txAttenuation),\
+ CTBLN(5,cardNo, systemId), \
+ CTBLN(6,cardNo, maxDatagramSize),\
+ CTBLN(7,cardNo, maxFrameSize),\
+ CTBLN(8,cardNo, maxRetries),\
+ CTBLN(9,cardNo, receiveMode),\
+ CTBLN(10,cardNo, priority),\
+ CTBLN(11,cardNo, rootOrRepeater),\
+ CTBLN(12,cardNo, SID),\
+ CTBLN(13,cardNo, registrationMode),\
+ CTBLN(14,cardNo, registrationFill),\
+ CTBLN(15,cardNo, localTalkAddress),\
+ CTBLN(16,cardNo, codeFormat),\
+ CTBLN(17,cardNo, numChannels),\
+ CTBLN(18,cardNo, channel1),\
+ CTBLN(19,cardNo, channel2),\
+ CTBLN(20,cardNo, channel3),\
+ CTBLN(21,cardNo, channel4),\
+ CTBLN(22,cardNo, txClear),\
+ CTBLN(23,cardNo, txRetries),\
+ CTBLN(24,cardNo, txRouting),\
+ CTBLN(25,cardNo, txScrambled),\
+ CTBLN(26,cardNo, rxParameter),\
+ CTBLN(27,cardNo, txTimeoutMs),\
+ CTBLN(28,cardNo, waitCardTimeout),\
+ CTBLN(29,cardNo, channelSet), \
+ {30, "name", arlan_conf[cardNo].siteName, \
+ 16, 0600, NULL, &proc_dostring},\
+ CTBLN(31,cardNo,waitTime),\
+ CTBLN(32,cardNo,lParameter),\
+ CTBLN(33,cardNo,_15),\
+ CTBLN(34,cardNo,headerSize),\
+ CTBLN(35,cardNo,async),\
+ CTBLN(36,cardNo,tx_delay_ms),\
+ CTBLN(37,cardNo,retries),\
+ CTBLN(38,cardNo,ReTransmitPacketMaxSize),\
+ CTBLN(39,cardNo,waitReTransmitPacketMaxSize),\
+ CTBLN(40,cardNo,fastReTransCount),\
+ CTBLN(41,cardNo,driverRetransmissions),\
+ CTBLN(42,cardNo,txAckTimeoutMs),\
+ CTBLN(43,cardNo,registrationInterrupts),\
+ CTBLN(44,cardNo,hardwareType),\
+ CTBLN(45,cardNo,radioType),\
+ CTBLN(46,cardNo,writeEEPROM),\
+ CTBLN(47,cardNo,writeRadioType),\
+ {48, "entry_exit_debug", &arlan_entry_and_exit_debug, \
+ sizeof(int), 0600, NULL, &proc_dointvec},\
+ {49, "debug", &arlan_debug, \
+ sizeof(int), 0600, NULL, &proc_dointvec},\
+ CTBLN(50,cardNo,in_speed),\
+ CTBLN(51,cardNo,out_speed),\
+ CTBLN(52,cardNo,in_speed10),\
+ CTBLN(53,cardNo,out_speed10),\
+ CTBLN(54,cardNo,in_speed_max),\
+ CTBLN(55,cardNo,out_speed_max),\
+ CTBLN(56,cardNo,measure_rate),\
+ CTBLN(57,cardNo,pre_Command_Wait),\
+ CTBLN(58,cardNo,rx_tweak1),\
+ CTBLN(59,cardNo,rx_tweak2),\
+ CTBLN(60,cardNo,tx_queue_len),\
+
+
+
+static ctl_table arlan_conf_table0[] =
+{
+ ARLAN_SYSCTL_TABLE_TOTAL(0)
+
+#ifdef ARLAN_PROC_SHM_DUMP
+ {150, "arlan0-txRing", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing},
+ {151, "arlan0-rxRing", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing},
+ {152, "arlan0-18", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18},
+ {153, "arlan0-ring", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719},
+ {154, "arlan0-shm-cpy", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info},
+#endif
+ {155, "config0", &conf_reset_result, \
+ 100, 0400, NULL, &arlan_configure}, \
+ {156, "reset0", &conf_reset_result, \
+ 100, 0400, NULL, &arlan_sysctl_reset}, \
+ {0}
+};
+
+static ctl_table arlan_conf_table1[] =
+{
+
+ ARLAN_SYSCTL_TABLE_TOTAL(1)
+
+#ifdef ARLAN_PROC_SHM_DUMP
+ {150, "arlan1-txRing", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing},
+ {151, "arlan1-rxRing", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing},
+ {152, "arlan1-18", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18},
+ {153, "arlan1-ring", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719},
+ {154, "arlan1-shm-cpy", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info},
+#endif
+ {155, "config1", &conf_reset_result,
+ 100, 0400, NULL, &arlan_configure},
+ {156, "reset1", &conf_reset_result,
+ 100, 0400, NULL, &arlan_sysctl_reset},
+ {0}
+};
+
+static ctl_table arlan_conf_table2[] =
+{
+
+ ARLAN_SYSCTL_TABLE_TOTAL(2)
+
+#ifdef ARLAN_PROC_SHM_DUMP
+ {150, "arlan2-txRing", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing},
+ {151, "arlan2-rxRing", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing},
+ {152, "arlan2-18", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18},
+ {153, "arlan2-ring", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719},
+ {154, "arlan2-shm-cpy", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info},
+#endif
+ {155, "config2", &conf_reset_result,
+ 100, 0400, NULL, &arlan_configure},
+ {156, "reset2", &conf_reset_result,
+ 100, 0400, NULL, &arlan_sysctl_reset},
+ {0}
+};
+
+static ctl_table arlan_conf_table3[] =
+{
+
+ ARLAN_SYSCTL_TABLE_TOTAL(3)
+
+#ifdef ARLAN_PROC_SHM_DUMP
+ {150, "arlan3-txRing", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing},
+ {151, "arlan3-rxRing", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing},
+ {152, "arlan3-18", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18},
+ {153, "arlan3-ring", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719},
+ {154, "arlan3-shm-cpy", &arlan_drive_info,
+ ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info},
+#endif
+ {155, "config3", &conf_reset_result,
+ 100, 0400, NULL, &arlan_configure},
+ {156, "reset3", &conf_reset_result,
+ 100, 0400, NULL, &arlan_sysctl_reset},
+ {0}
+};
+
+
+
+static ctl_table arlan_table[] =
+{
+ {0, "arlan0", NULL, 0, 0600, arlan_conf_table0},
+ {0, "arlan1", NULL, 0, 0600, arlan_conf_table1},
+ {0, "arlan2", NULL, 0, 0600, arlan_conf_table2},
+ {0, "arlan3", NULL, 0, 0600, arlan_conf_table3},
+ {0}
+};
+
+#else
+
+static ctl_table arlan_table[MAX_ARLANS + 1] =
+{
+ {0}
+};
+#endif
+#endif
+
+static int mmtu = 1234;
+
+static ctl_table arlan_root_table[] =
+{
+ {254, "arlan", NULL, 0, 0555, arlan_table},
+ {0}
+};
+
+/* Make sure that /proc/sys/dev is there */
+static ctl_table arlan_device_root_table[] =
+{
+ {CTL_DEV, "dev", NULL, 0, 0555, arlan_root_table},
+ {0}
+};
+
+
+
+static struct ctl_table_header *arlan_device_sysctl_header = NULL;
+
+int init_arlan_proc(void)
+{
+
+ int i = 0;
+ if (arlan_device_sysctl_header)
+ return 0;
+ for (i = 0; i < MAX_ARLANS && arlan_device[i]; i++)
+ arlan_table[i].ctl_name = i + 1;
+ arlan_device_sysctl_header = register_sysctl_table(arlan_root_table, 0);
+ if (!arlan_device_sysctl_header)
+ return -1;
+
+ return 0;
+
+};
+
+
+
+#ifdef MODULE
+
+int init_module(void)
+{
+
+ return init_arlan_proc();
+};
+
+void cleanup_module(void)
+{
+ unregister_sysctl_table(arlan_device_sysctl_header);
+ arlan_device_sysctl_header = NULL;
+
+ return;
+};
+
+#endif // MODULE
diff --git a/drivers/net/arlan.c b/drivers/net/arlan.c
new file mode 100644
index 000000000..d8f9ee74f
--- /dev/null
+++ b/drivers/net/arlan.c
@@ -0,0 +1,2079 @@
+/*
+ * Copyright (C) 1997 Cullen Jennings
+ * Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500
+ * Gnu Public License applies
+ * This module provides support for the Arlan 655 card made by Aironet
+ */
+
+#include <linux/config.h>
+#include "arlan.h"
+
+static const char *arlan_version = "C.Jennigs 97 & Elmer.Joandi@ut.ee Oct'98, http://www.ylenurme.ee/~elmer/655/";
+
+struct device *arlan_device[MAX_ARLANS];
+int last_arlan = 0;
+
+static int SID = SIDUNKNOWN;
+static int radioNodeId = radioNodeIdUNKNOWN;
+static char encryptionKey[12] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
+static char *siteName = siteNameUNKNOWN;
+static int irq = irqUNKNOWN;
+static int mem = memUNKNOWN;
+static int arlan_debug = debugUNKNOWN;
+static int probe = probeUNKNOWN;
+static int numDevices = numDevicesUNKNOWN;
+static int testMemory = testMemoryUNKNOWN;
+static int spreadingCode = spreadingCodeUNKNOWN;
+static int channelNumber = channelNumberUNKNOWN;
+static int channelSet = channelSetUNKNOWN;
+static int systemId = systemIdUNKNOWN;
+static int registrationMode = registrationModeUNKNOWN;
+static int txScrambled = 1;
+static int keyStart = 0;
+static int mdebug = 0;
+static int tx_delay_ms = 0;
+static int retries = 5;
+static int async = 1;
+static int tx_queue_len = 1;
+static int arlan_entry_debug = 0;
+static int arlan_exit_debug = 0;
+static int arlan_entry_and_exit_debug = 0;
+static int arlan_EEPROM_bad = 0;
+
+#if LINUX_VERSION_CODE > 0x20100
+MODULE_PARM(irq, "i");
+MODULE_PARM(mem, "i");
+MODULE_PARM(probe, "i");
+MODULE_PARM(arlan_debug, "i");
+MODULE_PARM(numDevices, "i");
+MODULE_PARM(testMemory, "i");
+MODULE_PARM(spreadingCode, "i");
+MODULE_PARM(channelNumber, "i");
+MODULE_PARM(channelSet, "i");
+MODULE_PARM(systemId, "i");
+MODULE_PARM(registrationMode, "i");
+MODULE_PARM(radioNodeId, "i");
+MODULE_PARM(SID, "i");
+MODULE_PARM(txScrambled, "i");
+MODULE_PARM(keyStart, "i");
+MODULE_PARM(mdebug, "i");
+MODULE_PARM(tx_delay_ms, "i");
+MODULE_PARM(retries, "i");
+MODULE_PARM(async, "i");
+MODULE_PARM(tx_queue_len, "i");
+MODULE_PARM(arlan_entry_debug, "i");
+MODULE_PARM(arlan_exit_debug, "i");
+MODULE_PARM(arlan_entry_and_exit_debug, "i");
+MODULE_PARM(arlan_EEPROM_bad, "i");
+
+EXPORT_SYMBOL(arlan_device);
+EXPORT_SYMBOL(last_arlan);
+
+
+// #warning kernel 2.1.110 tested
+#define myATOMIC_INIT(a,b) atomic_set(&(a),b)
+#define __initfunctio(a) __initfunc(a)
+
+#else
+#define test_and_set_bit set_bit
+#define __initfunctio(a) a
+#if LINUX_VERSION_CODE != 0x20024
+ // #warning kernel 2.0.36 tested
+#endif
+#define myATOMIC_INIT(a,b) a = b;
+
+#endif
+
+struct arlan_conf_stru arlan_conf[MAX_ARLANS];
+int arlans_found = 0;
+
+static int arlan_probe_here(struct device *dev, int ioaddr);
+static int arlan_open(struct device *dev);
+static int arlan_tx(struct sk_buff *skb, struct device *dev);
+static void arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static int arlan_close(struct device *dev);
+static struct enet_statistics *
+ arlan_statistics (struct device *dev);
+static void arlan_set_multicast (struct device *dev);
+static int arlan_hw_tx (struct device* dev, char *buf, int length );
+static int arlan_hw_config (struct device * dev);
+static void arlan_tx_done_interrupt (struct device * dev, int status);
+static void arlan_rx_interrupt (struct device * dev, u_char rxStatus, u_short, u_short);
+static void arlan_process_interrupt (struct device * dev);
+static int arlan_command(struct device * dev, int command);
+
+EXPORT_SYMBOL(arlan_command);
+
+extern inline long long arlan_time(void)
+{
+ struct timeval timev;
+ do_gettimeofday(&timev);
+ return ((long long) timev.tv_sec * 1000000 + timev.tv_usec);
+};
+
+#ifdef ARLAN_ENTRY_EXIT_DEBUGING
+#define ARLAN_DEBUG_ENTRY(name) \
+ {\
+ struct timeval timev;\
+ do_gettimeofday(&timev);\
+ if (arlan_entry_debug || arlan_entry_and_exit_debug)\
+ printk("--->>>" name " %ld " "\n",((long int) timev.tv_sec * 1000000 + timev.tv_usec));\
+ }
+#define ARLAN_DEBUG_EXIT(name) \
+ {\
+ struct timeval timev;\
+ do_gettimeofday(&timev);\
+ if (arlan_exit_debug || arlan_entry_and_exit_debug)\
+ printk("<<<---" name " %ld " "\n",((long int) timev.tv_sec * 1000000 + timev.tv_usec) );\
+ }
+#else
+#define ARLAN_DEBUG_ENTRY(name)
+#define ARLAN_DEBUG_EXIT(name)
+#endif
+
+
+#define arlan_interrupt_ack(dev)\
+ clearClearInterrupt(dev);\
+ setClearInterrupt(dev);
+
+
+#define ARLAN_COMMAND_LOCK(dev) \
+ if (atomic_dec_and_test(&((struct arlan_private * )dev->priv)->card_users))\
+ arlan_wait_command_complete_short(dev,__LINE__);
+#define ARLAN_COMMAND_UNLOCK(dev) \
+ atomic_inc(&((struct arlan_private * )dev->priv)->card_users);
+
+
+#define ARLAN_COMMAND_INC(dev) \
+ {((struct arlan_private *) dev->priv)->under_command++;}
+#define ARLAN_COMMAND_ZERO(dev) \
+ {((struct arlan_private *) dev->priv)->under_command =0;}
+#define ARLAN_UNDER_COMMAND(dev)\
+ (((struct arlan_private *) dev->priv)->under_command)
+
+#define ARLAN_COMMAND_START(dev) ARLAN_COMMAND_INC(dev)
+#define ARLAN_COMMAND_END(dev) ARLAN_COMMAND_ZERO(dev)
+#define ARLAN_TOGGLE_START(dev)\
+ {((struct arlan_private *) dev->priv)->under_toggle++;}
+#define ARLAN_TOGGLE_END(dev)\
+ {((struct arlan_private *) dev->priv)->under_toggle=0;}
+#define ARLAN_UNDER_TOGGLE(dev)\
+ (((struct arlan_private *) dev->priv)->under_toggle)
+
+
+
+extern inline int arlan_drop_tx(struct device *dev)
+{
+ struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+ priv->stats.tx_errors++;
+ if (priv->Conf->tx_delay_ms)
+ {
+ priv->tx_done_delayed = jiffies + priv->Conf->tx_delay_ms * HZ / 1000 + 1;
+ }
+ else
+ {
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_TX;
+ TXHEAD(dev).offset = 0;
+ TXTAIL(dev).offset = 0;
+ priv->txLast = 0;
+ priv->txOffset = 0;
+ priv->bad = 0;
+ if (!priv->under_reset && !priv->under_config)
+ {
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+ }
+ }
+ return 1;
+};
+
+
+static int arlan_command(struct device *dev, int command_p)
+{
+
+ volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+ struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
+ struct arlan_private *priv = (struct arlan_private *) dev->priv;
+ int udelayed = 0;
+ int i = 0;
+ long long time_mks = arlan_time();
+
+ ARLAN_DEBUG_ENTRY("arlan_command");
+
+ if (priv->card_polling_interval)
+ priv->card_polling_interval = 1;
+
+ if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS)
+ printk(KERN_DEBUG "arlan_command, %lx lock %x commandByte %x waiting %x incoming %x \n",
+ jiffies, priv->command_lock, READSHMB(arlan->commandByte),
+ priv->waiting_command_mask, command_p);
+
+ priv->waiting_command_mask |= command_p;
+
+ if (priv->waiting_command_mask & ARLAN_COMMAND_RESET)
+ if (jiffies - priv->lastReset < 5 * HZ)
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_RESET;
+
+ if (priv->waiting_command_mask & ARLAN_COMMAND_INT_ACK)
+ {
+ arlan_interrupt_ack(dev);
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_ACK;
+ }
+ if (priv->waiting_command_mask & ARLAN_COMMAND_INT_ENABLE)
+ {
+ setInterruptEnable(dev);
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_ENABLE;
+ }
+
+ /* Card access serializing lock */
+
+ if (test_and_set_bit(0, (void *) &priv->command_lock))
+ {
+ if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS)
+ printk(KERN_DEBUG "arlan_command: entered when command locked \n");
+ goto command_busy_end;
+ }
+ /* Check cards status and waiting */
+
+ if (priv->waiting_command_mask & (ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW))
+ {
+ while (priv->waiting_command_mask & (ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW))
+ {
+ if (READSHMB(arlan->resetFlag) ||
+ READSHMB(arlan->commandByte)) /* ||
+ (readControlRegister(dev) & ARLAN_ACCESS))
+ */
+ udelay(40);
+ else
+ priv->waiting_command_mask &= ~(ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW);
+
+ udelayed++;
+
+ if (priv->waiting_command_mask & ARLAN_COMMAND_LONG_WAIT_NOW)
+ {
+ if (udelayed * 40 > 1000000)
+ {
+ printk(KERN_ERR "%s long wait too long \n", dev->name);
+ priv->waiting_command_mask |= ARLAN_COMMAND_RESET;
+ break;
+ }
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_WAIT_NOW)
+ {
+ if (udelayed * 40 > 1000)
+ {
+ printk(KERN_ERR "%s short wait too long \n", dev->name);
+ goto bad_end;
+ }
+ }
+ }
+ }
+ else
+ {
+ i = 0;
+ while ((READSHMB(arlan->resetFlag) ||
+ READSHMB(arlan->commandByte)) &&
+ conf->pre_Command_Wait > (i++) * 10)
+ udelay(10);
+
+
+ if ((READSHMB(arlan->resetFlag) ||
+ READSHMB(arlan->commandByte)) &&
+ !(priv->waiting_command_mask & ARLAN_COMMAND_RESET))
+ {
+ goto card_busy_end;
+ }
+ }
+ if (priv->waiting_command_mask & ARLAN_COMMAND_RESET)
+ {
+ priv->under_reset = 1;
+ dev->start = 0;
+ }
+ if (priv->waiting_command_mask & ARLAN_COMMAND_CONF)
+ {
+ priv->under_config = 1;
+ dev->start = 0;
+ }
+
+ /* Issuing command */
+ arlan_lock_card_access(dev);
+ if (priv->waiting_command_mask & ARLAN_COMMAND_POWERUP)
+ {
+ // if (readControlRegister(dev) & (ARLAN_ACCESS && ARLAN_POWER))
+ setPowerOn(dev);
+ arlan_interrupt_lancpu(dev);
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_POWERUP;
+ priv->waiting_command_mask |= ARLAN_COMMAND_RESET;
+ priv->card_polling_interval = HZ / 10;
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_ACTIVATE)
+ {
+ WRITESHMB(arlan->commandByte, ARLAN_COM_ACTIVATE);
+ arlan_interrupt_lancpu(dev);
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_ACTIVATE;
+ priv->card_polling_interval = HZ / 10;
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_RX_ABORT)
+ {
+ if (priv->rx_command_given)
+ {
+ WRITESHMB(arlan->commandByte, ARLAN_COM_RX_ABORT);
+ arlan_interrupt_lancpu(dev);
+ priv->rx_command_given = 0;
+ }
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_RX_ABORT;
+ priv->card_polling_interval = 1;
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_TX_ABORT)
+ {
+ if (priv->tx_command_given)
+ {
+ WRITESHMB(arlan->commandByte, ARLAN_COM_TX_ABORT);
+ arlan_interrupt_lancpu(dev);
+ priv->tx_command_given = 0;
+ }
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_TX_ABORT;
+ priv->card_polling_interval = 1;
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_RESET)
+ {
+ arlan_drop_tx(dev);
+ if (priv->tx_command_given || priv->rx_command_given)
+ {
+ printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name);
+ };
+ if (arlan_debug & ARLAN_DEBUG_RESET)
+ printk(KERN_ERR "%s: Doing chip reset\n", dev->name);
+ priv->lastReset = jiffies;
+ WRITESHM(arlan->commandByte, 0, u_char);
+ /* hold card in reset state */
+ setHardwareReset(dev);
+ /* set reset flag and then release reset */
+ WRITESHM(arlan->resetFlag, 0xff, u_char);
+ clearChannelAttention(dev);
+ clearHardwareReset(dev);
+ priv->numResets++;
+ priv->card_polling_interval = HZ / 4;
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_RESET;
+ priv->waiting_command_mask |= ARLAN_COMMAND_INT_RACK;
+// priv->waiting_command_mask |= ARLAN_COMMAND_INT_RENABLE;
+// priv->waiting_command_mask |= ARLAN_COMMAND_RX;
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_INT_RACK)
+ {
+ clearHardwareReset(dev);
+ clearClearInterrupt(dev);
+ setClearInterrupt(dev);
+ setInterruptEnable(dev);
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_RACK;
+ priv->waiting_command_mask |= ARLAN_COMMAND_CONF;
+ priv->under_config = 1;
+ priv->under_reset = 0;
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_INT_RENABLE)
+ {
+ setInterruptEnable(dev);
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_RENABLE;
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_CONF)
+ {
+ if (priv->tx_command_given || priv->rx_command_given)
+ {
+ printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name);
+ }
+ dev->start = 0;
+ arlan_drop_tx(dev);
+ setInterruptEnable(dev);
+ arlan_hw_config(dev);
+ arlan_interrupt_lancpu(dev);
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF;
+ priv->card_polling_interval = HZ / 10;
+// priv->waiting_command_mask |= ARLAN_COMMAND_INT_RACK;
+// priv->waiting_command_mask |= ARLAN_COMMAND_INT_ENABLE;
+ priv->waiting_command_mask |= ARLAN_COMMAND_CONF_WAIT;
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_CONF_WAIT)
+ {
+ if (READSHMB(arlan->configuredStatusFlag) != 0 &&
+ READSHMB(arlan->diagnosticInfo) == 0xff)
+ {
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF_WAIT;
+ priv->waiting_command_mask |= ARLAN_COMMAND_RX;
+ priv->card_polling_interval = HZ / 10;
+ priv->tx_command_given = 0;
+ priv->under_config = 0;
+ if (dev->tbusy || !dev->start)
+ {
+ dev->tbusy = 0;
+ dev->start = 1;
+ mark_bh(NET_BH);
+ };
+ }
+ else
+ {
+ priv->card_polling_interval = 1;
+ if (arlan_debug & ARLAN_DEBUG_TIMING)
+ printk(KERN_ERR "configure delayed \n");
+ }
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_RX)
+ {
+ if (!registrationBad(dev))
+ {
+ setInterruptEnable(dev);
+ memset_io((void *) arlan->commandParameter, 0, 0xf);
+ WRITESHMB(arlan->commandByte, ARLAN_COM_INT | ARLAN_COM_RX_ENABLE);
+ WRITESHMB(arlan->commandParameter[0], conf->rxParameter);
+ arlan_interrupt_lancpu(dev);
+ priv->rx_command_given;
+ priv->last_rx_time = arlan_time();
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_RX;
+ priv->card_polling_interval = 1;
+ }
+ else
+ priv->card_polling_interval = 2;
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_TX)
+ {
+ if (!test_and_set_bit(0, (void *) &priv->tx_command_given))
+ {
+ if ((time_mks - priv->last_tx_time > conf->rx_tweak1) ||
+ (time_mks - priv->last_rx_int_ack_time < conf->rx_tweak2))
+ {
+ setInterruptEnable(dev);
+ memset_io((void *) arlan->commandParameter, 0, 0xf);
+ WRITESHMB(arlan->commandByte, ARLAN_COM_TX_ENABLE | ARLAN_COM_INT);
+ memcpy_toio((void *) arlan->commandParameter, &TXLAST(dev), 14);
+// for ( i=1 ; i < 15 ; i++) printk("%02x:",READSHMB(arlan->commandParameter[i]));
+ priv->last_command_was_rx = 0;
+ priv->tx_last_sent = jiffies;
+ arlan_interrupt_lancpu(dev);
+ priv->last_tx_time = arlan_time();
+ priv->tx_command_given = 1;
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_TX;
+ priv->card_polling_interval = 1;
+ }
+ else
+ {
+ priv->tx_command_given = 0;
+ priv->card_polling_interval = 1;
+ }
+ }
+ else if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS)
+ printk(KERN_ERR "tx command when tx chain locked \n");
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_NOOPINT)
+ {
+ {
+ WRITESHMB(arlan->commandByte, ARLAN_COM_NOP | ARLAN_COM_INT);
+ }
+ arlan_interrupt_lancpu(dev);
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_NOOPINT;
+ priv->card_polling_interval = HZ / 3;
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_NOOP)
+ {
+ WRITESHMB(arlan->commandByte, ARLAN_COM_NOP);
+ arlan_interrupt_lancpu(dev);
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_NOOP;
+ priv->card_polling_interval = HZ / 3;
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_SLOW_POLL)
+ {
+ WRITESHMB(arlan->commandByte, ARLAN_COM_GOTO_SLOW_POLL);
+ arlan_interrupt_lancpu(dev);
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_SLOW_POLL;
+ priv->card_polling_interval = HZ / 3;
+ }
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_POWERDOWN)
+ {
+ setPowerOff(dev);
+ if (arlan_debug & ARLAN_DEBUG_CARD_STATE)
+ printk(KERN_WARNING "%s: Arlan Going Standby\n", dev->name);
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_POWERDOWN;
+ priv->card_polling_interval = 3 * HZ;
+ }
+ arlan_unlock_card_access(dev);
+ for (i = 0; READSHMB(arlan->commandByte) && i < 20; i++)
+ udelay(10);
+ if (READSHMB(arlan->commandByte))
+ if (arlan_debug & ARLAN_DEBUG_CARD_STATE)
+ printk(KERN_ERR "card busy leaving command %x \n", priv->waiting_command_mask);
+
+ priv->command_lock = 0;
+ ARLAN_DEBUG_EXIT("arlan_command");
+ priv->last_command_buff_free_time = jiffies;
+ return 0;
+
+card_busy_end:
+ if (jiffies - priv->last_command_buff_free_time > HZ)
+ priv->waiting_command_mask |= ARLAN_COMMAND_CLEAN_AND_RESET;
+
+ if (arlan_debug & ARLAN_DEBUG_CARD_STATE)
+ printk(KERN_ERR "%s arlan_command card busy end \n", dev->name);
+ priv->command_lock = 0;
+ ARLAN_DEBUG_EXIT("arlan_command");
+ return 1;
+
+bad_end:
+ printk(KERN_ERR "%s arlan_command bad end \n", dev->name);
+
+ priv->command_lock = 0;
+ ARLAN_DEBUG_EXIT("arlan_command");
+
+ return -1;
+
+command_busy_end:
+ if (arlan_debug & ARLAN_DEBUG_CARD_STATE)
+ printk(KERN_ERR "%s arlan_command command busy end \n", dev->name);
+ ARLAN_DEBUG_EXIT("arlan_command");
+ return 2;
+
+};
+
+extern inline void arlan_command_process(struct device *dev)
+{
+ struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+ int times = 0;
+ while (priv->waiting_command_mask && times < 8)
+ {
+ if (priv->waiting_command_mask)
+ {
+ if (arlan_command(dev, 0))
+ break;
+ times++;
+ }
+ /* if long command, we wont repeat trying */ ;
+ if (priv->card_polling_interval > 1)
+ break;
+ times++;
+ }
+}
+
+
+extern inline void arlan_retransmit_now(struct device *dev)
+{
+ struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+
+ ARLAN_DEBUG_ENTRY("arlan_retransmit_now");
+ if (TXLAST(dev).offset == 0)
+ {
+ if (TXHEAD(dev).offset)
+ {
+ priv->txLast = 0;
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_DEBUG "TX buff switch to head \n");
+
+ }
+ else if (TXTAIL(dev).offset)
+ {
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_DEBUG "TX buff switch to tail \n");
+ priv->txLast = 1;
+ }
+ else
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_ERR "ReTransmit buff empty");
+ priv->txOffset = 0;
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+ return;
+
+ }
+ arlan_command(dev, ARLAN_COMMAND_TX);
+
+ priv->nof_tx++;
+
+ priv->Conf->driverRetransmissions++;
+ priv->retransmissions++;
+
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("Retransmit %d bytes \n", TXLAST(dev).length);
+
+ ARLAN_DEBUG_EXIT("arlan_retransmit_now");
+}
+
+
+
+static void arlan_registration_timer(unsigned long data)
+{
+ struct device *dev = (struct device *) data;
+ struct arlan_private *priv = (struct arlan_private *) dev->priv;
+
+ int lostTime = ((int) (jiffies - priv->registrationLastSeen)) * 1000 / HZ;
+ int bh_mark_needed = 0;
+ int next_tick = 1;
+
+
+ priv->timer_chain_active = 1;
+
+
+ if (registrationBad(dev))
+ {
+ //debug=100;
+ priv->registrationLostCount++;
+ if (lostTime > 7000 && lostTime < 7200)
+ {
+ printk(KERN_NOTICE "%s registration Lost \n", dev->name);
+ }
+ if (lostTime / priv->reRegisterExp > 2000)
+ arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_CONF);
+ if (lostTime / (priv->reRegisterExp) > 3500)
+ arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET);
+ if (priv->reRegisterExp < 400)
+ priv->reRegisterExp += 2;
+ if (lostTime > 7200)
+ {
+ next_tick = HZ;
+ arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET);
+ }
+ }
+ else
+ {
+ if (priv->Conf->registrationMode && lostTime > 10000 &&
+ priv->registrationLostCount)
+ {
+ printk(KERN_NOTICE "%s registration is back after %d milliseconds\n", dev->name,
+ ((int) (jiffies - priv->registrationLastSeen) * 1000) / HZ);
+ }
+ priv->registrationLastSeen = jiffies;
+ priv->registrationLostCount = 0;
+ priv->reRegisterExp = 1;
+ if (dev->start == 0)
+ {
+ dev->start = 1;
+ mark_bh(NET_BH);
+ }
+ }
+
+
+ if (!registrationBad(dev) && priv->ReTransmitRequested)
+ {
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+ printk(KERN_ERR "Retranmit from timer \n");
+ priv->ReTransmitRequested = 0;
+ arlan_retransmit_now(dev);
+ }
+ if (!registrationBad(dev) &&
+ priv->tx_done_delayed < jiffies &&
+ priv->tx_done_delayed != 0)
+ {
+ TXLAST(dev).offset = 0;
+ if (priv->txLast)
+ priv->txLast = 0;
+ else if (TXTAIL(dev).offset)
+ priv->txLast = 1;
+ if (TXLAST(dev).offset)
+ {
+ arlan_retransmit_now(dev);
+ dev->trans_start = jiffies;
+ }
+ if (!(TXHEAD(dev).offset && TXTAIL(dev).offset))
+ {
+ priv->txOffset = 0;
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+ }
+ priv->tx_done_delayed = 0;
+ bh_mark_needed = 1;
+ }
+ if (bh_mark_needed)
+ {
+ priv->txOffset = 0;
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+ }
+ arlan_process_interrupt(dev);
+
+ if (next_tick < priv->card_polling_interval)
+ next_tick = priv->card_polling_interval;
+
+ priv->timer_chain_active = 0;
+ priv->timer.expires = jiffies + next_tick;
+
+ add_timer(&priv->timer);
+}
+
+
+
+
+static void arlan_print_registers(struct device *dev, int line)
+{
+ volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+
+ u_char hostcpuLock, lancpuLock, controlRegister, cntrlRegImage,
+ txStatus, rxStatus, interruptInProgress, commandByte;
+
+
+ ARLAN_DEBUG_ENTRY("arlan_print_registers");
+ READSHM(interruptInProgress, arlan->interruptInProgress, u_char);
+ READSHM(hostcpuLock, arlan->hostcpuLock, u_char);
+ READSHM(lancpuLock, arlan->lancpuLock, u_char);
+ READSHM(controlRegister, arlan->controlRegister, u_char);
+ READSHM(cntrlRegImage, arlan->cntrlRegImage, u_char);
+ READSHM(txStatus, arlan->txStatus, u_char);
+ READSHM(rxStatus, arlan->rxStatus, u_char);
+ READSHM(commandByte, arlan->commandByte, u_char);
+
+ printk(KERN_WARNING "line %04d IP %02x HL %02x LL %02x CB %02x CR %02x CRI %02x TX %02x RX %02x\n",
+ line, interruptInProgress, hostcpuLock, lancpuLock, commandByte,
+ controlRegister, cntrlRegImage, txStatus, rxStatus);
+
+ ARLAN_DEBUG_EXIT("arlan_print_registers");
+}
+
+
+static int arlan_hw_tx(struct device *dev, char *buf, int length)
+{
+ int i;
+
+ struct arlan_private *priv = (struct arlan_private *) dev->priv;
+ volatile struct arlan_shmem *arlan = priv->card;
+ struct arlan_conf_stru *conf = priv->Conf;
+
+ int tailStarts = 0x800;
+ int headEnds = 0x0;
+
+
+ ARLAN_DEBUG_ENTRY("arlan_hw_tx");
+ if (TXHEAD(dev).offset)
+ headEnds = (((TXHEAD(dev).offset + TXHEAD(dev).length - (((int) arlan->txBuffer) - ((int) arlan))) / 64) + 1) * 64;
+ if (TXTAIL(dev).offset)
+ tailStarts = 0x800 - (((TXTAIL(dev).offset - (((int) arlan->txBuffer) - ((int) arlan))) / 64) + 2) * 64;
+
+
+ if (!TXHEAD(dev).offset && length < tailStarts)
+ {
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+ printk(KERN_ERR "TXHEAD insert, tailStart %d\n", tailStarts);
+
+ TXHEAD(dev).offset =
+ (((int) arlan->txBuffer) - ((int) arlan));
+ TXHEAD(dev).length = length - ARLAN_FAKE_HDR_LEN;
+ for (i = 0; i < 6; i++)
+ TXHEAD(dev).dest[i] = buf[i];
+ TXHEAD(dev).clear = conf->txClear;
+ TXHEAD(dev).retries = conf->txRetries; /* 0 is use default */
+ TXHEAD(dev).routing = conf->txRouting;
+ TXHEAD(dev).scrambled = conf->txScrambled;
+ memcpy_toio(((char *) arlan + TXHEAD(dev).offset), buf + ARLAN_FAKE_HDR_LEN, TXHEAD(dev).length);
+ }
+ else if (!TXTAIL(dev).offset && length < (0x800 - headEnds))
+ {
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+ printk(KERN_ERR "TXTAIL insert, headEnd %d\n", headEnds);
+
+ TXTAIL(dev).offset =
+ (((int) arlan->txBuffer) - ((int) arlan)) + 0x800 - (length / 64 + 2) * 64;
+ TXTAIL(dev).length = length - ARLAN_FAKE_HDR_LEN;
+ for (i = 0; i < 6; i++)
+ TXTAIL(dev).dest[i] = buf[i];
+ TXTAIL(dev).clear = conf->txClear;
+ TXTAIL(dev).retries = conf->txRetries;
+ TXTAIL(dev).routing = conf->txRouting;
+ TXTAIL(dev).scrambled = conf->txScrambled;
+ memcpy_toio(((char *) arlan + TXTAIL(dev).offset), buf + ARLAN_FAKE_HDR_LEN, TXTAIL(dev).length);
+ }
+ else
+ {
+ dev->tbusy = 1;
+ return -1;
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+ printk(KERN_ERR "TX TAIL & HEAD full, return, tailStart %d headEnd %d\n", tailStarts, headEnds);
+ }
+ priv->out_bytes += length;
+ priv->out_bytes10 += length;
+ if (conf->measure_rate < 1)
+ conf->measure_rate = 1;
+ if (jiffies - priv->out_time > conf->measure_rate * HZ)
+ {
+ conf->out_speed = priv->out_bytes / conf->measure_rate;
+ priv->out_bytes = 0;
+ priv->out_time = jiffies;
+ }
+ if (jiffies - priv->out_time10 > conf->measure_rate * HZ * 10)
+ {
+ conf->out_speed10 = priv->out_bytes10 / (10 * conf->measure_rate);
+ priv->out_bytes10 = 0;
+ priv->out_time10 = jiffies;
+ }
+ if (TXHEAD(dev).offset && TXTAIL(dev).offset)
+ {
+ dev->tbusy = 1;
+ return 0;
+ }
+ else
+ dev->tbusy = 0;
+
+
+ IFDEBUG(ARLAN_DEBUG_HEADER_DUMP)
+ printk(KERN_WARNING "%s Transmit t %2x:%2x:%2x:%2x:%2x:%2x f %2x:%2x:%2x:%2x:%2x:%2x \n", dev->name,
+ (unsigned char) buf[0], (unsigned char) buf[1], (unsigned char) buf[2], (unsigned char) buf[3],
+ (unsigned char) buf[4], (unsigned char) buf[5], (unsigned char) buf[6], (unsigned char) buf[7],
+ (unsigned char) buf[8], (unsigned char) buf[9], (unsigned char) buf[10], (unsigned char) buf[11]);
+
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_ERR "TX command prepare for buffer %d\n", priv->txLast);
+
+ arlan_command(dev, ARLAN_COMMAND_TX);
+
+ priv->last_command_was_rx = 0;
+ priv->tx_last_sent = jiffies;
+ priv->nof_tx++;
+
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("%s TX Qued %d bytes \n", dev->name, length);
+
+ ARLAN_DEBUG_EXIT("arlan_hw_tx");
+
+ return 0;
+}
+
+
+static int arlan_hw_config(struct device *dev)
+{
+ volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+ struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
+ struct arlan_private *priv = (struct arlan_private *) dev->priv;
+
+ ARLAN_DEBUG_ENTRY("arlan_hw_config");
+
+ printk(KERN_NOTICE "%s arlan configure called \n", dev->name);
+ if (arlan_EEPROM_bad)
+ printk(KERN_NOTICE "arlan configure with eeprom bad option \n");
+
+
+ WRITESHM(arlan->spreadingCode, conf->spreadingCode, u_char);
+ WRITESHM(arlan->channelSet, conf->channelSet, u_char);
+
+ if (arlan_EEPROM_bad)
+ WRITESHM(arlan->defaultChannelSet, conf->channelSet, u_char);
+
+ WRITESHM(arlan->channelNumber, conf->channelNumber, u_char);
+
+ WRITESHM(arlan->scramblingDisable, conf->scramblingDisable, u_char);
+ WRITESHM(arlan->txAttenuation, conf->txAttenuation, u_char);
+
+ WRITESHM(arlan->systemId, conf->systemId, u_int);
+
+ WRITESHM(arlan->maxRetries, conf->maxRetries, u_char);
+ WRITESHM(arlan->receiveMode, conf->receiveMode, u_char);
+ WRITESHM(arlan->priority, conf->priority, u_char);
+ WRITESHM(arlan->rootOrRepeater, conf->rootOrRepeater, u_char);
+ WRITESHM(arlan->SID, conf->SID, u_int);
+
+ WRITESHM(arlan->registrationMode, conf->registrationMode, u_char);
+
+ WRITESHM(arlan->registrationFill, conf->registrationFill, u_char);
+ WRITESHM(arlan->localTalkAddress, conf->localTalkAddress, u_char);
+ WRITESHM(arlan->codeFormat, conf->codeFormat, u_char);
+ WRITESHM(arlan->numChannels, conf->numChannels, u_char);
+ WRITESHM(arlan->channel1, conf->channel1, u_char);
+ WRITESHM(arlan->channel2, conf->channel2, u_char);
+ WRITESHM(arlan->channel3, conf->channel3, u_char);
+ WRITESHM(arlan->channel4, conf->channel4, u_char);
+ WRITESHM(arlan->radioNodeId, conf->radioNodeId, u_short);
+ WRITESHM(arlan->SID, conf->SID, u_int);
+ WRITESHM(arlan->waitTime, conf->waitTime, u_short);
+ WRITESHM(arlan->lParameter, conf->lParameter, u_short);
+ memcpy_toio(&(arlan->_15), &(conf->_15), 3);
+ WRITESHM(arlan->_15, conf->_15, u_short);
+ WRITESHM(arlan->headerSize, conf->headerSize, u_short);
+ if (arlan_EEPROM_bad)
+ WRITESHM(arlan->hardwareType, conf->hardwareType, u_char);
+ WRITESHM(arlan->radioType, conf->radioType, u_char);
+ if (arlan_EEPROM_bad)
+ WRITESHM(arlan->radioModule, conf->radioType, u_char);
+
+ memcpy_toio(arlan->encryptionKey + keyStart, encryptionKey, 8);
+ memcpy_toio(arlan->name, conf->siteName, 16);
+
+ WRITESHMB(arlan->commandByte, ARLAN_COM_INT | ARLAN_COM_CONF); /* do configure */
+ memset_io(arlan->commandParameter, 0, 0xf); /* 0xf */
+ memset_io(arlan->commandParameter + 1, 0, 2);
+ if (conf->writeEEPROM)
+ {
+ memset_io(arlan->commandParameter, conf->writeEEPROM, 1);
+// conf->writeEEPROM=0;
+ }
+ if (conf->registrationMode && conf->registrationInterrupts)
+ memset_io(arlan->commandParameter + 3, 1, 1);
+ else
+ memset_io(arlan->commandParameter + 3, 0, 1);
+
+ priv->irq_test_done = 0;
+
+ if (conf->tx_queue_len)
+ dev->tx_queue_len = conf->tx_queue_len;
+ udelay(100);
+
+ ARLAN_DEBUG_EXIT("arlan_hw_config");
+ return 0;
+}
+
+
+static int arlan_read_card_configuration(struct device *dev)
+{
+ u_char tlx415;
+ volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+ struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
+
+ ARLAN_DEBUG_ENTRY("arlan_read_card_configuration");
+
+ if (radioNodeId == radioNodeIdUNKNOWN)
+ {
+ READSHM(conf->radioNodeId, arlan->radioNodeId, u_short);
+ }
+ else
+ conf->radioNodeId = radioNodeId;
+
+ if (SID == SIDUNKNOWN)
+ {
+ READSHM(conf->SID, arlan->SID, u_int);
+ }
+ else conf->SID = SID;
+
+ if (spreadingCode == spreadingCodeUNKNOWN)
+ {
+ READSHM(conf->spreadingCode, arlan->spreadingCode, u_char);
+ }
+ else
+ conf->spreadingCode = spreadingCode;
+
+ if (channelSet == channelSetUNKNOWN)
+ {
+ READSHM(conf->channelSet, arlan->channelSet, u_char);
+ }
+ else conf->channelSet = channelSet;
+
+ if (channelNumber == channelNumberUNKNOWN)
+ {
+ READSHM(conf->channelNumber, arlan->channelNumber, u_char);
+ }
+ else conf->channelNumber = channelNumber;
+
+ READSHM(conf->scramblingDisable, arlan->scramblingDisable, u_char);
+ READSHM(conf->txAttenuation, arlan->txAttenuation, u_char);
+
+ if (systemId == systemIdUNKNOWN)
+ {
+ READSHM(conf->systemId, arlan->systemId, u_int);
+ }
+ else conf->systemId = systemId;
+
+ READSHM(conf->maxDatagramSize, arlan->maxDatagramSize, u_short);
+ READSHM(conf->maxFrameSize, arlan->maxFrameSize, u_short);
+ READSHM(conf->maxRetries, arlan->maxRetries, u_char);
+ READSHM(conf->receiveMode, arlan->receiveMode, u_char);
+ READSHM(conf->priority, arlan->priority, u_char);
+ READSHM(conf->rootOrRepeater, arlan->rootOrRepeater, u_char);
+
+ if (SID == SIDUNKNOWN)
+ {
+ READSHM(conf->SID, arlan->SID, u_int);
+ }
+ else conf->SID = SID;
+
+ if (registrationMode == registrationModeUNKNOWN)
+ {
+ READSHM(conf->registrationMode, arlan->registrationMode, u_char);
+ }
+ else conf->registrationMode = registrationMode;
+
+ READSHM(conf->registrationFill, arlan->registrationFill, u_char);
+ READSHM(conf->localTalkAddress, arlan->localTalkAddress, u_char);
+ READSHM(conf->codeFormat, arlan->codeFormat, u_char);
+ READSHM(conf->numChannels, arlan->numChannels, u_char);
+ READSHM(conf->channel1, arlan->channel1, u_char);
+ READSHM(conf->channel2, arlan->channel2, u_char);
+ READSHM(conf->channel3, arlan->channel3, u_char);
+ READSHM(conf->channel4, arlan->channel4, u_char);
+ READSHM(conf->waitTime, arlan->waitTime, u_short);
+ READSHM(conf->lParameter, arlan->lParameter, u_short);
+ READSHM(conf->_15, arlan->_15, u_short);
+ READSHM(conf->headerSize, arlan->headerSize, u_short);
+ READSHM(conf->hardwareType, arlan->hardwareType, u_char);
+ READSHM(conf->radioType, arlan->radioModule, u_char);
+
+ if (conf->radioType == 0)
+ conf->radioType = 0xc;
+
+ WRITESHM(arlan->configStatus, 0xA5, u_char);
+ READSHM(tlx415, arlan->configStatus, u_char);
+
+ if (tlx415 != 0xA5)
+ printk(KERN_INFO "%s tlx415 chip \n", dev->name);
+
+ conf->txClear = 0;
+ conf->txRetries = 1;
+ conf->txRouting = 1;
+ conf->txScrambled = 0;
+ conf->rxParameter = 1;
+ conf->txTimeoutMs = 4000;
+ conf->waitCardTimeout = 100000;
+ conf->receiveMode = ARLAN_RCV_CLEAN;
+ memcpy_fromio(conf->siteName, arlan->name, 16);
+ conf->siteName[16] = '\0';
+ conf->retries = retries;
+ conf->tx_delay_ms = tx_delay_ms;
+ conf->async = async;
+ conf->ReTransmitPacketMaxSize = 200;
+ conf->waitReTransmitPacketMaxSize = 200;
+ conf->txAckTimeoutMs = 900;
+ conf->fastReTransCount = 3;
+
+ ARLAN_DEBUG_EXIT("arlan_read_card_configuration");
+
+ return 0;
+}
+
+
+static int lastFoundAt = 0xbe000;
+
+
+/*
+ * 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.
+ */
+
+__initfunctio(static int arlan_check_fingerprint(int memaddr))
+{
+ static char probeText[] = "TELESYSTEM SLW INC. ARLAN \0";
+ char tempBuf[49];
+ volatile struct arlan_shmem *arlan = (struct arlan_shmem *) memaddr;
+
+ ARLAN_DEBUG_ENTRY("arlan_check_fingerprint");
+ memcpy_fromio(tempBuf, arlan->textRegion, 29);
+ tempBuf[30] = 0;
+
+ /* check for card at this address */
+ if (0 != strncmp(tempBuf, probeText, 29))
+ return -ENODEV;
+
+// printk(KERN_INFO "arlan found at 0x%x \n",memaddr);
+ ARLAN_DEBUG_EXIT("arlan_check_fingerprint");
+
+ return 0;
+
+
+}
+
+__initfunctio(int arlan_probe_everywhere(struct device *dev))
+{
+ int m;
+ int probed = 0;
+ int found = 0;
+
+ ARLAN_DEBUG_ENTRY("arlan_probe_everywhere");
+ if (mem != 0 && numDevices == 1) /* Check a single specified location. */
+ {
+ if (arlan_probe_here(dev, mem) == 0)
+ return 0;
+ else
+ return -ENODEV;
+ }
+ for (m = lastFoundAt + 0x2000; m <= 0xDE000; m += 0x2000)
+ {
+ if (arlan_probe_here(dev, m) == 0)
+ {
+ found++;
+ lastFoundAt = m;
+ break;
+ }
+ probed++;
+ }
+ if (found == 0 && probed != 0)
+ {
+ if (lastFoundAt == 0xbe000)
+ printk(KERN_ERR "arlan: No Arlan devices found \n");
+ return ENODEV;
+ }
+ else
+ return 0;
+
+ ARLAN_DEBUG_EXIT("arlan_probe_everywhere");
+
+ return ENODEV;
+}
+
+__initfunctio(int arlan_find_devices(void))
+{
+ int m;
+ int found = 0;
+
+ ARLAN_DEBUG_ENTRY("arlan_find_devices");
+ if (mem != 0 && numDevices == 1) /* Check a single specified location. */
+ return 1;
+ for (m = 0xc000; m <= 0xDE000; m += 0x2000)
+ {
+ if (arlan_check_fingerprint(m) == 0)
+ found++;
+ }
+ ARLAN_DEBUG_EXIT("arlan_find_devices");
+
+ return found;
+}
+
+
+static int arlan_change_mtu(struct device *dev, int new_mtu)
+{
+ struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
+
+ ARLAN_DEBUG_ENTRY("arlan_change_mtu");
+ if ((new_mtu < 68) || (new_mtu > 2032))
+ return -EINVAL;
+ dev->mtu = new_mtu;
+ if (new_mtu < 256)
+ new_mtu = 256; /* cards book suggests 1600 */
+ conf->maxDatagramSize = new_mtu;
+ conf->maxFrameSize = new_mtu + 48;
+
+ arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_CONF);
+ printk(KERN_NOTICE "%s mtu changed to %d \n", dev->name, new_mtu);
+
+ ARLAN_DEBUG_EXIT("arlan_change_mtu");
+
+ return 0;
+}
+
+static int arlan_mac_addr(struct device *dev, void *p)
+{
+ struct sockaddr *addr = p;
+
+
+ ARLAN_DEBUG_ENTRY("arlan_mac_addr");
+ return -EINVAL;
+
+ if (dev->start)
+ return -EBUSY;
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ ARLAN_DEBUG_EXIT("arlan_mac_addr");
+ return 0;
+}
+
+
+
+
+__initfunctio(static int
+ arlan_allocate_device(int num, struct device *devs))
+{
+
+ struct device *dev;
+
+ ARLAN_DEBUG_ENTRY("arlan_allocate_device");
+
+ if (!devs)
+ dev = init_etherdev(0, sizeof(struct arlan_private));
+ else
+ {
+ dev = devs;
+ dev->priv = kmalloc(sizeof(struct arlan_private), GFP_KERNEL);
+ };
+
+ if (dev == NULL || dev->priv == NULL)
+ {
+ printk(KERN_CRIT "init_etherdev failed ");
+ return 0;
+ }
+ ((struct arlan_private *) dev->priv)->conf =
+ kmalloc(sizeof(struct arlan_shmem), GFP_KERNEL);
+
+ if (dev == NULL || dev->priv == NULL ||
+ ((struct arlan_private *) dev->priv)->conf == NULL)
+ {
+ return 0;
+ printk(KERN_CRIT " No memory at arlan_allocate_device \n");
+ }
+ /* Fill in the 'dev' fields. */
+ dev->base_addr = 0;
+ dev->mem_start = 0;
+ dev->mem_end = 0;
+ dev->mtu = 1500;
+ dev->flags = 0; /* IFF_BROADCAST & IFF_MULTICAST & IFF_PROMISC; */
+ dev->irq = 0;
+ dev->dma = 0;
+ dev->tx_queue_len = tx_queue_len;
+ ether_setup(dev);
+ dev->tx_queue_len = tx_queue_len;
+ dev->open = arlan_open;
+ dev->stop = arlan_close;
+ dev->hard_start_xmit = arlan_tx;
+ dev->get_stats = arlan_statistics;
+ dev->set_multicast_list = arlan_set_multicast;
+ dev->change_mtu = arlan_change_mtu;
+ dev->set_mac_address = arlan_mac_addr;
+ ((struct arlan_private *) dev->priv)->irq_test_done = 0;
+ arlan_device[num] = dev;
+ ((struct arlan_private *) arlan_device[num]->priv)->Conf = &(arlan_conf[num]);
+
+ ((struct arlan_private *) dev->priv)->Conf->pre_Command_Wait = 40;
+ ((struct arlan_private *) dev->priv)->Conf->rx_tweak1 = 30;
+ ((struct arlan_private *) dev->priv)->Conf->rx_tweak2 = 0;
+
+ ARLAN_DEBUG_EXIT("arlan_allocate_device");
+ return (int) dev;
+}
+
+
+__initfunctio(int arlan_probe_here(struct device *dev, int memaddr))
+{
+ volatile struct arlan_shmem *arlan;
+
+ ARLAN_DEBUG_ENTRY("arlan_probe_here");
+
+ if (arlan_check_fingerprint(memaddr))
+ return -ENODEV;
+
+ printk(KERN_NOTICE "%s: Arlan found at %#5x, \n ", dev->name, memaddr);
+
+ if (!arlan_allocate_device(arlans_found, dev))
+ return -1;
+
+ ((struct arlan_private *) dev->priv)->card = (struct arlan_shmem *) memaddr;
+ arlan = (void *) memaddr;
+
+ dev->mem_start = memaddr;
+ dev->mem_end = memaddr + 0x1FFF;
+
+ if (dev->irq < 2)
+ {
+ READSHM(dev->irq, arlan->irqLevel, u_char);
+ } else if (dev->irq == 2)
+ dev->irq = 9;
+
+ arlan_read_card_configuration(dev);
+
+ ARLAN_DEBUG_EXIT("arlan_probe_here");
+ return 0;
+}
+
+
+
+
+static int arlan_open(struct device *dev)
+{
+ struct arlan_private *priv = (struct arlan_private *) dev->priv;
+ volatile struct arlan_shmem *arlan = priv->card;
+ int ret = 0;
+
+ ARLAN_DEBUG_ENTRY("arlan_open");
+
+ if (dev->mem_start == 0)
+ ret = arlan_probe_everywhere(dev);
+ if (ret != 0)
+ return ret;
+
+ arlan = ((struct arlan_private *) dev->priv)->card;
+
+ if (request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev))
+ {
+ printk(KERN_ERR "%s: unable to get IRQ %d .\n",
+ dev->name, dev->irq);
+ return -EAGAIN;
+ }
+ arlan_command(dev, ARLAN_COMMAND_POWERUP | ARLAN_COMMAND_LONG_WAIT_NOW);
+
+ priv->bad = 0;
+ priv->lastReset = 0;
+ priv->reset = 0;
+ priv->open_time = jiffies;
+ memcpy_fromio(dev->dev_addr, arlan->lanCardNodeId, 6);
+ memset(dev->broadcast, 0xff, 6);
+ dev->tbusy = 1;
+ priv->txOffset = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+ dev->tx_queue_len = tx_queue_len;
+ init_timer(&priv->timer);
+ priv->timer.expires = jiffies + HZ / 10;
+ priv->timer.data = (unsigned long) dev;
+ priv->timer.function = &arlan_registration_timer; /* timer handler */
+ priv->interrupt_processing_active = 0;
+ priv->command_lock = 0;
+ add_timer(&priv->timer);
+
+ init_mutex(&priv->card_lock);
+ myATOMIC_INIT(priv->card_users, 1); /* damn 2.0.33 */
+ priv->registrationLostCount = 0;
+ priv->registrationLastSeen = jiffies;
+ priv->txLast = 0;
+ priv->tx_command_given = 0;
+
+ priv->reRegisterExp = 1;
+ priv->nof_tx = 0;
+ priv->nof_tx_ack = 0;
+ priv->last_command_was_rx = 0;
+ priv->tx_last_sent = jiffies - 1;
+ priv->tx_last_cleared = jiffies;
+ priv->Conf->writeEEPROM = 0;
+ priv->Conf->registrationInterrupts = 1;
+
+ dev->tbusy = 0;
+
+ MOD_INC_USE_COUNT;
+#ifdef CONFIG_PROC_FS
+#ifndef MODULE
+ if (arlan_device[0])
+ init_arlan_proc();
+#endif
+#endif
+ ARLAN_DEBUG_EXIT("arlan_open");
+ return 0;
+}
+
+
+
+
+static int arlan_tx(struct sk_buff *skb, struct device *dev)
+{
+ struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+ struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
+
+ ARLAN_DEBUG_ENTRY("arlan_tx");
+
+ if (dev->tbusy)
+ {
+ /*
+ * If we get here, some higher level has decided we are broken.
+ * There should really be a "kick me" function call instead.
+ */
+ int tickssofar = jiffies - dev->trans_start;
+
+ if (((tickssofar * 1000) / HZ) * 2 > conf->txTimeoutMs)
+ arlan_command(dev, ARLAN_COMMAND_TX_ABORT);
+
+ if (((tickssofar * 1000) / HZ) < conf->txTimeoutMs)
+ {
+ // up(&priv->card_lock);
+ goto bad_end;
+ }
+ printk(KERN_ERR "%s: arlan transmit timed out, kernel decided\n", dev->name);
+ /* Try to restart the adaptor. */
+ arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET);
+ dev->trans_start = jiffies;
+ goto bad_end;
+
+ }
+ /*
+ * Block a timer-based transmit from overlapping. This could better be
+ * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
+ */
+ if (test_and_set_bit(0, (void *) &dev->tbusy) != 0)
+ {
+ printk(KERN_ERR "%s: Transmitter access conflict.\n",
+ dev->name);
+ }
+ else
+ {
+ short length;
+ unsigned char *buf;
+
+ /*
+ * If some higher layer thinks we've missed an tx-done interrupt
+ * we are passed NULL. Caution: dev_tint() handles the cli()/sti()
+ * itself.
+ */
+
+ length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+ buf = skb->data;
+
+ if (priv->txOffset + length + 0x12 > 0x800)
+ printk(KERN_ERR "TX RING overflow \n");
+
+ if (arlan_hw_tx(dev, buf, length) == -1)
+ goto bad_end;
+
+ dev->trans_start = jiffies;
+ }
+ dev_kfree_skb(skb);
+
+ arlan_process_interrupt(dev);
+ priv->tx_chain_active = 0;
+ ARLAN_DEBUG_EXIT("arlan_tx");
+ return 0;
+
+bad_end:
+ arlan_process_interrupt(dev);
+ priv->tx_chain_active = 0;
+ ARLAN_DEBUG_EXIT("arlan_tx");
+ return 1;
+}
+
+
+extern inline int DoNotReTransmitCrap(struct device *dev)
+{
+ struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+ if (TXLAST(dev).length < priv->Conf->ReTransmitPacketMaxSize)
+ return 1;
+ return 0;
+
+}
+
+extern inline int DoNotWaitReTransmitCrap(struct device *dev)
+{
+ struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+ if (TXLAST(dev).length < priv->Conf->waitReTransmitPacketMaxSize)
+ return 1;
+ return 0;
+}
+
+extern inline void arlan_queue_retransmit(struct device *dev)
+{
+ struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+ ARLAN_DEBUG_ENTRY("arlan_queue_retransmit");
+
+ if (DoNotWaitReTransmitCrap(dev))
+ {
+ arlan_drop_tx(dev);
+ } else
+ priv->ReTransmitRequested++;
+
+ ARLAN_DEBUG_EXIT("arlan_queue_retransmit");
+};
+
+extern inline void RetryOrFail(struct device *dev)
+{
+ struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+ ARLAN_DEBUG_ENTRY("RetryOrFail");
+
+ if (priv->retransmissions > priv->Conf->retries ||
+ DoNotReTransmitCrap(dev))
+ {
+ arlan_drop_tx(dev);
+ }
+ else if (priv->bad <= priv->Conf->fastReTransCount)
+ {
+ arlan_retransmit_now(dev);
+ }
+ else arlan_queue_retransmit(dev);
+
+ ARLAN_DEBUG_EXIT("RetryOrFail");
+}
+
+
+static void arlan_tx_done_interrupt(struct device *dev, int status)
+{
+ struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+ ARLAN_DEBUG_ENTRY("arlan_tx_done_interrupt");
+
+ priv->tx_last_cleared = jiffies;
+ priv->tx_command_given = 0;
+ priv->nof_tx_ack++;
+ switch (status)
+ {
+ case 1:
+ {
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+ printk("arlan intr: transmit OK\n");
+ priv->stats.tx_packets++;
+ priv->bad = 0;
+ priv->reset = 0;
+ priv->retransmissions = 0;
+ if (priv->Conf->tx_delay_ms)
+ {
+ priv->tx_done_delayed = jiffies + (priv->Conf->tx_delay_ms * HZ) / 1000 + 1;;
+ }
+ else
+ {
+ TXLAST(dev).offset = 0;
+ if (priv->txLast)
+ priv->txLast = 0;
+ else if (TXTAIL(dev).offset)
+ priv->txLast = 1;
+ if (TXLAST(dev).offset)
+ {
+ arlan_retransmit_now(dev);
+ dev->trans_start = jiffies;
+ }
+ if (!TXHEAD(dev).offset || !TXTAIL(dev).offset)
+ {
+ priv->txOffset = 0;
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+ }
+ }
+ }
+ break;
+
+ case 2:
+ {
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+ printk("arlan intr: transmit timed out\n");
+ priv->bad += 1;
+ //arlan_queue_retransmit(dev);
+ RetryOrFail(dev);
+ }
+ break;
+
+ case 3:
+ {
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+ printk("arlan intr: transmit max retries\n");
+ priv->bad += 1;
+ priv->reset = 0;
+ //arlan_queue_retransmit(dev);
+ RetryOrFail(dev);
+ }
+ break;
+
+ case 4:
+ {
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+ printk("arlan intr: transmit aborted\n");
+ priv->bad += 1;
+ arlan_queue_retransmit(dev);
+ //RetryOrFail(dev);
+ }
+ break;
+
+ case 5:
+ {
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+ printk("arlan intr: transmit not registered\n");
+ priv->bad += 1;
+ //debug=101;
+ arlan_queue_retransmit(dev);
+ }
+ break;
+
+ case 6:
+ {
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+ printk("arlan intr: transmit destination full\n");
+ priv->bad += 1;
+ priv->reset = 0;
+ //arlan_drop_tx(dev);
+ arlan_queue_retransmit(dev);
+ }
+ break;
+
+ case 7:
+ {
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+ printk("arlan intr: transmit unknown ack\n");
+ priv->bad += 1;
+ priv->reset = 0;
+ arlan_queue_retransmit(dev);
+ }
+ break;
+
+ case 8:
+ {
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+ printk("arlan intr: transmit dest mail box full\n");
+ priv->bad += 1;
+ priv->reset = 0;
+ //arlan_drop_tx(dev);
+ arlan_queue_retransmit(dev);
+ }
+ break;
+
+ case 9:
+ {
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+ printk("arlan intr: transmit root dest not reg.\n");
+ priv->bad += 1;
+ priv->reset = 1;
+ //arlan_drop_tx(dev);
+ arlan_queue_retransmit(dev);
+ }
+ break;
+
+ default:
+ {
+ printk(KERN_ERR "arlan intr: transmit status unknown\n");
+ priv->bad += 1;
+ priv->reset = 1;
+ arlan_drop_tx(dev);
+ }
+ }
+
+ ARLAN_DEBUG_EXIT("arlan_tx_done_interrupt");
+}
+
+
+static void arlan_rx_interrupt(struct device *dev, u_char rxStatus, u_short rxOffset, u_short pkt_len)
+{
+ char *skbtmp;
+ int i = 0;
+
+ struct arlan_private *priv = (struct arlan_private *) dev->priv;
+ volatile struct arlan_shmem *arlan = priv->card;
+ struct arlan_conf_stru *conf = priv->Conf;
+
+
+ ARLAN_DEBUG_ENTRY("arlan_rx_interrupt");
+ // by spec, not WRITESHMB(arlan->rxStatus,0x00);
+ // prohibited here arlan_command(dev, ARLAN_COMMAND_RX);
+
+ if (pkt_len < 10 || pkt_len > 2048)
+ {
+ printk(KERN_WARNING "%s: got too short or long packet, len %d \n", dev->name, pkt_len);
+ return;
+ }
+ if (rxOffset + pkt_len > 0x2000)
+ {
+ printk("%s: got too long packet, len %d offset %x\n", dev->name, pkt_len, rxOffset);
+ return;
+ }
+ priv->in_bytes += pkt_len;
+ priv->in_bytes10 += pkt_len;
+ if (conf->measure_rate < 1)
+ conf->measure_rate = 1;
+ if (jiffies - priv->in_time > conf->measure_rate * HZ)
+ {
+ conf->in_speed = priv->in_bytes / conf->measure_rate;
+ priv->in_bytes = 0;
+ priv->in_time = jiffies;
+ }
+ if (jiffies - priv->in_time10 > conf->measure_rate * HZ * 10)
+ {
+ conf->in_speed10 = priv->in_bytes10 / (10 * conf->measure_rate);
+ priv->in_bytes10 = 0;
+ priv->in_time10 = jiffies;
+ }
+ DEBUGSHM(1, "arlan rcv pkt rxStatus= %d ", arlan->rxStatus, u_char);
+ switch (rxStatus)
+ {
+ case 1:
+ case 2:
+ case 3:
+ {
+ /* Malloc up new buffer. */
+ struct sk_buff *skb;
+
+ DEBUGSHM(50, "arlan recv pkt offs=%d\n", arlan->rxOffset, u_short);
+ DEBUGSHM(1, "arlan rxFrmType = %d \n", arlan->rxFrmType, u_char);
+ DEBUGSHM(1, KERN_INFO "arlan rx scrambled = %d \n", arlan->scrambled, u_char);
+
+ /* here we do multicast filtering to avoid slow 8-bit memcopy */
+#ifdef ARLAN_MULTICAST
+ if (!(dev->flags & IFF_ALLMULTI) &&
+ !(dev->flags & IFF_PROMISC) &&
+ dev->mc_list)
+ {
+ char hw_dst_addr[6];
+ struct dev_mc_list *dmi = dev->mc_list;
+ int i;
+
+ memcpy_fromio(hw_dst_addr, arlan->ultimateDestAddress, 6);
+ if (hw_dst_addr[0] == 0x01)
+ {
+ if (mdebug)
+ if (hw_dst_addr[1] == 0x00)
+ printk(KERN_ERR "%s mcast 0x0100 \n", dev->name);
+ else if (hw_dst_addr[1] == 0x40)
+ printk(KERN_ERR "%s m/bcast 0x0140 \n", dev->name);
+ while (dmi)
+ { if (dmi->dmi_addrlen == 6)
+ {
+ if (arlan_debug & ARLAN_DEBUG_HEADER_DUMP)
+ printk(KERN_ERR "%s mcl %2x:%2x:%2x:%2x:%2x:%2x \n", dev->name,
+ dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2],
+ dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]);
+ for (i = 0; i < 6; i++)
+ if (dmi->dmi_addr[i] != hw_dst_addr[i])
+ break;
+ if (i == 6)
+ break;
+ }
+ else
+ printk(KERN_ERR "%s: invalid multicast address length given.\n", dev->name);
+ dmi = dmi->next;
+ }
+ /* we reach here if multicast filtering is on and packet
+ * is multicast and not for receive */
+ goto end_of_interupt;
+ }
+ }
+#endif // ARLAN_MULTICAST
+ /* multicast filtering ends here */
+ pkt_len += ARLAN_FAKE_HDR_LEN;
+
+ skb = dev_alloc_skb(pkt_len + 4);
+ if (skb == NULL)
+ {
+ printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", dev->name);
+ priv->stats.rx_dropped++;
+ break;
+ }
+ skb_reserve(skb, 2);
+ skb->dev = dev;
+ skbtmp = skb_put(skb, pkt_len);
+
+ memcpy_fromio(skbtmp + ARLAN_FAKE_HDR_LEN, ((char *) arlan) + rxOffset, pkt_len - ARLAN_FAKE_HDR_LEN);
+ memcpy_fromio(skbtmp, arlan->ultimateDestAddress, 6);
+ memcpy_fromio(skbtmp + 6, arlan->rxSrc, 6);
+ WRITESHMB(arlan->rxStatus, 0x00);
+ arlan_command(dev, ARLAN_COMMAND_RX);
+
+ IFDEBUG(ARLAN_DEBUG_HEADER_DUMP)
+ {
+ char immedDestAddress[6];
+ char immedSrcAddress[6];
+ memcpy_fromio(immedDestAddress, arlan->immedDestAddress, 6);
+ memcpy_fromio(immedSrcAddress, arlan->immedSrcAddress, 6);
+
+ printk(KERN_WARNING "%s t %2x:%2x:%2x:%2x:%2x:%2x f %2x:%2x:%2x:%2x:%2x:%2x imd %2x:%2x:%2x:%2x:%2x:%2x ims %2x:%2x:%2x:%2x:%2x:%2x\n", dev->name,
+ (unsigned char) skbtmp[0], (unsigned char) skbtmp[1], (unsigned char) skbtmp[2], (unsigned char) skbtmp[3],
+ (unsigned char) skbtmp[4], (unsigned char) skbtmp[5], (unsigned char) skbtmp[6], (unsigned char) skbtmp[7],
+ (unsigned char) skbtmp[8], (unsigned char) skbtmp[9], (unsigned char) skbtmp[10], (unsigned char) skbtmp[11],
+ immedDestAddress[0], immedDestAddress[1], immedDestAddress[2],
+ immedDestAddress[3], immedDestAddress[4], immedDestAddress[5],
+ immedSrcAddress[0], immedSrcAddress[1], immedSrcAddress[2],
+ immedSrcAddress[3], immedSrcAddress[4], immedSrcAddress[5]);
+ }
+ skb->protocol = eth_type_trans(skb, dev);
+ IFDEBUG(ARLAN_DEBUG_HEADER_DUMP)
+ if (skb->protocol != 0x608 && skb->protocol != 0x8)
+ {
+ for (i = 0; i <= 22; i++)
+ printk("%02x:", (u_char) skbtmp[i + 12]);
+ printk(KERN_ERR "\n");
+ printk(KERN_WARNING "arlan kernel pkt type trans %x \n", skb->protocol);
+ }
+ netif_rx(skb);
+ priv->stats.rx_packets++;
+ }
+ break;
+
+ default:
+ printk(KERN_ERR "arlan intr: recieved unknown status\n");
+ priv->stats.rx_crc_errors++;
+ break;
+ }
+ ARLAN_DEBUG_EXIT("arlan_rx_interrupt");
+}
+
+static void arlan_process_interrupt(struct device *dev)
+{
+ struct arlan_private *priv = (struct arlan_private *) dev->priv;
+ volatile struct arlan_shmem *arlan = priv->card;
+ u_char rxStatus = READSHMB(arlan->rxStatus);
+ u_char txStatus = READSHMB(arlan->txStatus);
+ u_short rxOffset = READSHMS(arlan->rxOffset);
+ u_short pkt_len = READSHMS(arlan->rxLength);
+ int interrupt_count = 0;
+
+ ARLAN_DEBUG_ENTRY("arlan_process_interrupt");
+
+ if (test_and_set_bit(0, (void *) &priv->interrupt_processing_active))
+ {
+ if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS)
+ printk(KERN_ERR "interrupt chain reentering \n");
+ goto end_int_process;
+ }
+ while ((rxStatus || txStatus || priv->interrupt_ack_requested)
+ && (interrupt_count < 5))
+ {
+ if (rxStatus)
+ priv->last_rx_int_ack_time = arlan_time();
+
+ arlan_command(dev, ARLAN_COMMAND_INT_ACK);
+ arlan_command(dev, ARLAN_COMMAND_INT_ENABLE);
+
+ IFDEBUG(ARLAN_DEBUG_INTERRUPT)
+ printk(KERN_ERR "%s: got IRQ rx %x tx %x comm %x rxOff %x rxLen %x \n",
+ dev->name, rxStatus, txStatus, READSHMB(arlan->commandByte),
+ rxOffset, pkt_len);
+
+ if (rxStatus == 0 && txStatus == 0)
+ {
+ priv->last_command_was_rx = 0;
+ if (priv->irq_test_done)
+ {
+ if (!registrationBad(dev))
+ IFDEBUG(ARLAN_DEBUG_INTERRUPT) printk(KERN_ERR "%s unknown interrupt(nop? regLost ?) reason tx %d rx %d ",
+ dev->name, txStatus, rxStatus);
+ } else {
+ IFDEBUG(ARLAN_DEBUG_INTERRUPT)
+ printk(KERN_INFO "%s irq $%d test OK \n", dev->name, dev->irq);
+
+ }
+ priv->interrupt_ack_requested = 0;
+ goto ends;
+ }
+ if (txStatus != 0)
+ {
+ WRITESHMB(arlan->txStatus, 0x00);
+ arlan_tx_done_interrupt(dev, txStatus);
+ goto ends;
+ }
+ if (rxStatus == 1 || rxStatus == 2)
+ { /* a packet waiting */
+ arlan_rx_interrupt(dev, rxStatus, rxOffset, pkt_len);
+ goto ends;
+ }
+ if (rxStatus > 2 && rxStatus < 0xff)
+ {
+ priv->last_command_was_rx = 0;
+ WRITESHMB(arlan->rxStatus, 0x00);
+ printk(KERN_ERR "%s unknown rxStatus reason tx %d rx %d ",
+ dev->name, txStatus, rxStatus);
+ goto ends;
+ }
+ if (rxStatus == 0xff)
+ {
+ priv->last_command_was_rx = 0;
+ WRITESHMB(arlan->rxStatus, 0x00);
+ arlan_command(dev, ARLAN_COMMAND_RX);
+ if (registrationBad(dev))
+ dev->start = 0;
+ if (!registrationBad(dev))
+ {
+ priv->registrationLastSeen = jiffies;
+ if (!dev->tbusy && !priv->under_reset && !priv->under_config)
+ {
+ mark_bh(NET_BH);
+ dev->start = 1;
+ }
+ }
+ goto ends;
+ }
+ends:
+
+ arlan_command_process(dev);
+
+ rxStatus = READSHMB(arlan->rxStatus);
+ txStatus = READSHMB(arlan->txStatus);
+ rxOffset = READSHMS(arlan->rxOffset);
+ pkt_len = READSHMS(arlan->rxLength);
+
+
+ priv->irq_test_done = 1;
+
+ interrupt_count++;
+ }
+ priv->interrupt_processing_active = 0;
+
+end_int_process:
+ arlan_command_process(dev);
+
+ ARLAN_DEBUG_EXIT("arlan_process_interrupt");
+ return;
+}
+
+static void arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct device *dev = dev_id;
+ struct arlan_private *priv = (struct arlan_private *) dev->priv;
+ volatile struct arlan_shmem *arlan = priv->card;
+ u_char rxStatus = READSHMB(arlan->rxStatus);
+ u_char txStatus = READSHMB(arlan->txStatus);
+
+ ARLAN_DEBUG_ENTRY("arlan_interrupt");
+
+
+ if (!rxStatus && !txStatus)
+ priv->interrupt_ack_requested++;
+ dev->interrupt++;
+
+ arlan_process_interrupt(dev);
+
+ priv->irq_test_done = 1;
+ dev->interrupt--;
+
+ ARLAN_DEBUG_EXIT("arlan_interrupt");
+ return;
+
+}
+
+
+static int arlan_close(struct device *dev)
+{
+ struct arlan_private *priv = (struct arlan_private *) dev->priv;
+
+ if (!dev)
+ {
+ printk(KERN_CRIT "arlan: No Device\n");
+ return 0;
+ }
+ priv = (struct arlan_private *) dev->priv;
+ if (!priv)
+ {
+ printk(KERN_CRIT "arlan: No Device priv \n");
+ return 0;
+ }
+ ARLAN_DEBUG_ENTRY("arlan_close");
+
+ IFDEBUG(ARLAN_DEBUG_STARTUP)
+ printk(KERN_NOTICE "%s: Closing device\n", dev->name);
+
+ priv->open_time = 0;
+ dev->tbusy = 1;
+ dev->start = 0;
+ del_timer(&priv->timer);
+ free_irq(dev->irq, dev);
+
+ MOD_DEC_USE_COUNT;
+
+ ARLAN_DEBUG_EXIT("arlan_close");
+ return 0;
+}
+
+
+static long alignLong(volatile u_char * ptr)
+{
+ long ret;
+ memcpy_fromio(&ret, (void *) ptr, 4);
+ return ret;
+}
+
+
+/*
+ * Get the current statistics.
+ * This may be called with the card open or closed.
+ */
+
+static struct enet_statistics *arlan_statistics(struct device *dev)
+{
+ struct arlan_private *priv = (struct arlan_private *) dev->priv;
+ volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+
+
+ ARLAN_DEBUG_ENTRY("arlan_statistics");
+
+ /* Update the statistics from the device registers. */
+
+ READSHM(priv->stats.collisions, arlan->numReTransmissions, u_int);
+ READSHM(priv->stats.rx_crc_errors, arlan->numCRCErrors, u_int);
+ READSHM(priv->stats.rx_dropped, arlan->numFramesDiscarded, u_int);
+ READSHM(priv->stats.rx_fifo_errors, arlan->numRXBufferOverflows, u_int);
+ READSHM(priv->stats.rx_frame_errors, arlan->numReceiveFramesLost, u_int);
+ READSHM(priv->stats.rx_over_errors, arlan->numRXOverruns, u_int);
+ READSHM(priv->stats.rx_packets, arlan->numDatagramsReceived, u_int);
+ READSHM(priv->stats.tx_aborted_errors, arlan->numAbortErrors, u_int);
+ READSHM(priv->stats.tx_carrier_errors, arlan->numStatusTimeouts, u_int);
+ READSHM(priv->stats.tx_dropped, arlan->numDatagramsDiscarded, u_int);
+ READSHM(priv->stats.tx_fifo_errors, arlan->numTXUnderruns, u_int);
+ READSHM(priv->stats.tx_packets, arlan->numDatagramsTransmitted, u_int);
+ READSHM(priv->stats.tx_window_errors, arlan->numHoldOffs, u_int);
+
+ ARLAN_DEBUG_EXIT("arlan_statistics");
+
+ return &priv->stats;
+}
+
+
+static void arlan_set_multicast(struct device *dev)
+{
+ volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+ struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
+ int board_conf_needed = 0;
+
+
+ ARLAN_DEBUG_ENTRY("arlan_set_multicast");
+
+ if (dev->flags & IFF_PROMISC)
+ {
+ unsigned char recMode;
+ READSHM(recMode, arlan->receiveMode, u_char);
+ conf->receiveMode = (ARLAN_RCV_PROMISC | ARLAN_RCV_CONTROL);
+ if (conf->receiveMode != recMode)
+ board_conf_needed = 1;
+ }
+ else
+ {
+ /* turn off promiscuous mode */
+ unsigned char recMode;
+ READSHM(recMode, arlan->receiveMode, u_char);
+ conf->receiveMode = ARLAN_RCV_CLEAN | ARLAN_RCV_CONTROL;
+ if (conf->receiveMode != recMode)
+ board_conf_needed = 1;
+ }
+ if (board_conf_needed)
+ arlan_command(dev, ARLAN_COMMAND_CONF);
+
+ ARLAN_DEBUG_EXIT("arlan_set_multicast");
+}
+
+
+__initfunctio(int arlan_probe(struct device *dev))
+{
+ printk("Arlan driver %s\n", arlan_version);
+
+ if (arlan_probe_everywhere(dev))
+ return ENODEV;
+
+ arlans_found++;
+
+ if (arlans_found == 1)
+ siteName = kmalloc(100, GFP_KERNEL);
+ return 0;
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+ int i = 0;
+
+ ARLAN_DEBUG_ENTRY("init_module");
+
+ if (channelSet != channelSetUNKNOWN || channelNumber != channelNumberUNKNOWN || systemId != systemIdUNKNOWN)
+ {
+ printk(KERN_WARNING "arlan: wrong module params for multiple devices\n ");
+ return -1;
+ }
+ numDevices = arlan_find_devices();
+ if (numDevices == 0)
+ {
+ printk(KERN_ERR "arlan: no devices found \n");
+ return -1;
+ }
+
+ siteName = kmalloc(100, GFP_KERNEL);
+ if(siteName==NULL)
+ {
+ printk(KERN_ERR "arlan: No memory for site name.\n");
+ return -1;
+ }
+ for (i = 0; i < numDevices && i < MAX_ARLANS; i++)
+ {
+ if (!arlan_allocate_device(i, NULL))
+ return -1;
+ if (arlan_device[i] == NULL)
+ {
+ printk(KERN_CRIT "arlan: Not Enough memory \n");
+ return -1;
+ }
+ if (probe)
+ arlan_probe_everywhere(arlan_device[i]);
+ }
+ printk(KERN_INFO "Arlan driver %s\n", arlan_version);
+ ARLAN_DEBUG_EXIT("init_module");
+ return 0;
+}
+
+
+void cleanup_module(void)
+{
+ int i = 0;
+
+ ARLAN_DEBUG_ENTRY("cleanup_module");
+
+ IFDEBUG(ARLAN_DEBUG_SHUTDOWN)
+ printk(KERN_INFO "arlan: unloading module\n");
+ for (i = 0; i < MAX_ARLANS; i++)
+ {
+ if (arlan_device[i])
+ {
+ unregister_netdev(arlan_device[i]);
+ if (arlan_device[i]->priv)
+ {
+ if (((struct arlan_private *) arlan_device[i]->priv)->conf)
+ kfree(((struct arlan_private *) arlan_device[i]->priv)->conf);
+ kfree(arlan_device[i]);
+ }
+ arlan_device[i] = NULL;
+ }
+ }
+ ARLAN_DEBUG_EXIT("cleanup_module");
+}
+
+
+#endif
diff --git a/drivers/net/arlan.h b/drivers/net/arlan.h
new file mode 100644
index 000000000..7074335ea
--- /dev/null
+++ b/drivers/net/arlan.h
@@ -0,0 +1,574 @@
+/*
+ * Copyright (C) 1997 Cullen Jennings
+ * Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500
+ * Gnu Public License applies
+ */
+#include <linux/version.h>
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/if_ether.h> /* For the statistics structure. */
+#include <linux/if_arp.h> /* For ARPHRD_ETHER */
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+
+#include <linux/init.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+
+#define DEBUG 1
+
+#define ARLAN_PROC_INTERFACE
+#define MAX_ARLANS 4 /* not more than 4 ! */
+#define ARLAN_PROC_SHM_DUMP /* shows all card registers, makes driver way larger */
+
+#define ARLAN_MAX_MULTICAST_ADDRS 16
+#define ARLAN_RCV_CLEAN 0
+#define ARLAN_RCV_PROMISC 1
+#define ARLAN_RCV_CONTROL 2
+
+
+#ifdef CONFIG_PROC_FS
+extern int init_arlan_proc(void);
+#endif
+
+extern struct device *arlan_device[MAX_ARLANS];
+static int arlan_debug;
+static char * siteName;
+static int arlan_entry_debug;
+static int arlan_exit_debug;
+static int arlan_entry_and_exit_debug;
+static int testMemory;
+static const char* arlan_version;
+
+#define SIDUNKNOWN -1
+#define radioNodeIdUNKNOWN -1
+#define encryptionKeyUNKNOWN '\0';
+#define irqUNKNOWN 0
+#define memUNKNOWN 0
+#define debugUNKNOWN 0
+#define probeUNKNOWN 1
+#define numDevicesUNKNOWN 1
+#define testMemoryUNKNOWN 1
+#define spreadingCodeUNKNOWN 0
+#define channelNumberUNKNOWN 0
+#define channelSetUNKNOWN 0
+#define systemIdUNKNOWN -1
+#define registrationModeUNKNOWN -1
+#define siteNameUNKNOWN "LinuxSite"
+
+
+
+#define IFDEBUG( L ) if ( (L) & arlan_debug )
+#define ARLAN_FAKE_HDR_LEN 12
+
+#ifdef DEBUG
+ #define ARLAN_ENTRY_EXIT_DEBUGING 1
+ #define ARLAN_DEBUG(a,b) printk(KERN_DEBUG a, b)
+#else
+ #define ARLAN_DEBUG(a,b)
+#endif
+
+struct arlan_shmem
+{
+ /* Header Signature */
+ volatile char textRegion[48];
+ volatile u_char resetFlag;
+ volatile u_char diagnosticInfo;
+ volatile u_short diagnosticOffset;
+ volatile u_char _1[12];
+ volatile u_char lanCardNodeId[6];
+ volatile u_char broadcastAddress[6];
+ volatile u_char hardwareType;
+ volatile u_char majorHardwareVersion;
+ volatile u_char minorHardwareVersion;
+ volatile u_char radioModule;// shows EEPROM, can be overridden at 0x111
+ volatile u_char defaultChannelSet; // shows EEProm, can be overriiden at 0x10A
+ volatile u_char _2[47];
+
+ /* Control/Status Block - 0x0080 */
+ volatile u_char interruptInProgress; /* not used by lancpu */
+ volatile u_char cntrlRegImage; /* not used by lancpu */
+ volatile u_char _3[13];
+ volatile u_char dumpByte;
+ volatile u_char commandByte; /* non-zero = active */
+ volatile u_char commandParameter[15];
+
+ /* Receive Status - 0x00a0 */
+ volatile u_char rxStatus; /* 1- data, 2-control, 0xff - registr change */
+ volatile u_char rxFrmType;
+ volatile u_short rxOffset;
+ volatile u_short rxLength;
+ volatile u_char rxSrc[6];
+ volatile u_char rxBroadcastFlag;
+ volatile u_char rxQuality;
+ volatile u_char scrambled;
+ volatile u_char _4[1];
+
+ /* Transmit Status - 0x00b0 */
+ volatile u_char txStatus;
+ volatile u_char txAckQuality;
+ volatile u_char numRetries;
+ volatile u_char _5[14];
+ volatile u_char registeredRouter[6];
+ volatile u_char backboneRouter[6];
+ volatile u_char registrationStatus;
+ volatile u_char configuredStatusFlag;
+ volatile u_char _6[1];
+ volatile u_char ultimateDestAddress[6];
+ volatile u_char immedDestAddress[6];
+ volatile u_char immedSrcAddress[6];
+ volatile u_short rxSequenceNumber;
+ volatile u_char assignedLocaltalkAddress;
+ volatile u_char _7[27];
+
+ /* System Parameter Block */
+
+ /* - Driver Parameters (Novell Specific) */
+
+ volatile u_short txTimeout;
+ volatile u_short transportTime;
+ volatile u_char _8[4];
+
+ /* - Configuration Parameters */
+ volatile u_char irqLevel;
+ volatile u_char spreadingCode;
+ volatile u_char channelSet;
+ volatile u_char channelNumber;
+ volatile u_short radioNodeId;
+ volatile u_char _9[2];
+ volatile u_char scramblingDisable;
+ volatile u_char radioType;
+ volatile u_short routerId;
+ volatile u_char _10[9];
+ volatile u_char txAttenuation;
+ volatile u_char systemId[4];
+ volatile u_short globalChecksum;
+ volatile u_char _11[4];
+ volatile u_short maxDatagramSize;
+ volatile u_short maxFrameSize;
+ volatile u_char maxRetries;
+ volatile u_char receiveMode;
+ volatile u_char priority;
+ volatile u_char rootOrRepeater;
+ volatile u_char specifiedRouter[6];
+ volatile u_short fastPollPeriod;
+ volatile u_char pollDecay;
+ volatile u_char fastPollDelay[2];
+ volatile u_char arlThreshold;
+ volatile u_char arlDecay;
+ volatile u_char _12[1];
+ volatile u_short specRouterTimeout;
+ volatile u_char _13[5];
+
+ /* Scrambled Area */
+ volatile u_char SID[4];
+ volatile u_char encryptionKey[12];
+ volatile u_char _14[2];
+ volatile u_char waitTime[2];
+ volatile u_char lParameter[2];
+ volatile u_char _15[3];
+ volatile u_short headerSize;
+ volatile u_short sectionChecksum;
+
+ volatile u_char registrationMode;
+ volatile u_char registrationFill;
+ volatile u_short pollPeriod;
+ volatile u_short refreshPeriod;
+ volatile u_char name[16];
+ volatile u_char NID[6];
+ volatile u_char localTalkAddress;
+ volatile u_char codeFormat;
+ volatile u_char numChannels;
+ volatile u_char channel1;
+ volatile u_char channel2;
+ volatile u_char channel3;
+ volatile u_char channel4;
+ volatile u_char SSCode[59];
+
+ volatile u_char _16[0xC0];
+ volatile u_short auxCmd;
+ volatile u_char dumpPtr[4];
+ volatile u_char dumpVal;
+ volatile u_char _17[0x6A];
+ volatile u_char wireTest;
+ volatile u_char _18[14];
+
+ /* Statistics Block - 0x0300 */
+ volatile u_char hostcpuLock;
+ volatile u_char lancpuLock;
+ volatile u_char resetTime[18];
+
+ volatile u_char numDatagramsTransmitted[4];
+ volatile u_char numReTransmissions[4];
+ volatile u_char numFramesDiscarded[4];
+ volatile u_char numDatagramsReceived[4];
+ volatile u_char numDuplicateReceivedFrames[4];
+ volatile u_char numDatagramsDiscarded[4];
+
+ volatile u_short maxNumReTransmitDatagram;
+ volatile u_short maxNumReTransmitFrames;
+ volatile u_short maxNumConsecutiveDuplicateFrames;
+ /* misaligned here so we have to go to characters */
+
+ volatile u_char numBytesTransmitted[4];
+ volatile u_char numBytesReceived[4];
+ volatile u_char numCRCErrors[4];
+ volatile u_char numLengthErrors[4];
+ volatile u_char numAbortErrors[4];
+ volatile u_char numTXUnderruns[4];
+ volatile u_char numRXOverruns[4];
+ volatile u_char numHoldOffs[4];
+ volatile u_char numFramesTransmitted[4];
+ volatile u_char numFramesReceived[4];
+ volatile u_char numReceiveFramesLost[4];
+ volatile u_char numRXBufferOverflows[4];
+ volatile u_char numFramesDiscardedAddrMismatch[4];
+ volatile u_char numFramesDiscardedSIDMismatch[4];
+ volatile u_char numPollsTransmistted[4];
+ volatile u_char numPollAcknowledges[4];
+ volatile u_char numStatusTimeouts[4];
+ volatile u_char numNACKReceived[4];
+
+ volatile u_char _19[0x86];
+
+ volatile u_char txBuffer[0x800];
+ volatile u_char rxBuffer[0x800];
+
+ volatile u_char _20[0x800];
+ volatile u_char _21[0x3fb];
+ volatile u_char configStatus;
+ volatile u_char _22;
+ volatile u_char progIOCtrl;
+ volatile u_char shareMBase;
+ volatile u_char controlRegister;
+};
+
+struct arlan_conf_stru {
+ int spreadingCode;
+ int channelSet;
+ int channelNumber;
+ int scramblingDisable;
+ int txAttenuation;
+ int systemId;
+ int maxDatagramSize;
+ int maxFrameSize;
+ int maxRetries;
+ int receiveMode;
+ int priority;
+ int rootOrRepeater;
+ int SID;
+ int radioNodeId;
+ int registrationMode;
+ int registrationFill;
+ int localTalkAddress;
+ int codeFormat;
+ int numChannels;
+ int channel1;
+ int channel2;
+ int channel3;
+ int channel4;
+ int txClear;
+ int txRetries;
+ int txRouting;
+ int txScrambled;
+ int rxParameter;
+ int txTimeoutMs;
+ int txAckTimeoutMs;
+ int waitCardTimeout;
+ int waitTime;
+ int lParameter;
+ int _15;
+ int headerSize;
+ int async;
+ int retries;
+ int tx_delay_ms;
+ int waitReTransmitPacketMaxSize;
+ int ReTransmitPacketMaxSize;
+ int fastReTransCount;
+ int driverRetransmissions;
+ int registrationInterrupts;
+ int hardwareType;
+ int radioType;
+ int writeRadioType;
+ int writeEEPROM;
+ char siteName[17];
+ int measure_rate;
+ int in_speed;
+ int out_speed;
+ int in_speed10;
+ int out_speed10;
+ int in_speed_max;
+ int out_speed_max;
+ int pre_Command_Wait;
+ int rx_tweak1;
+ int rx_tweak2;
+ int tx_queue_len;
+};
+
+struct arlan_conf_stru arlan_conf[MAX_ARLANS];
+
+struct TxParam
+{
+ volatile short offset;
+ volatile short length;
+ volatile u_char dest[6];
+ volatile unsigned char clear;
+ volatile unsigned char retries;
+ volatile unsigned char routing;
+ volatile unsigned char scrambled;
+};
+
+struct TxRingPoint {
+ struct TxParam txParam;
+
+
+};
+
+#define TX_RING_SIZE 2
+/* Information that need to be kept for each board. */
+struct arlan_private {
+ struct enet_statistics stats;
+ long open_time; /* Useless example local info. */
+ struct arlan_shmem * card;
+ struct arlan_shmem * conf;
+ struct TxParam txParam;
+ int multicastLength;
+ char multicastList[ARLAN_MAX_MULTICAST_ADDRS][6];
+ int promiscModeEnabled;
+ struct arlan_conf_stru * Conf;
+ int bad;
+ int reset;
+ long long lastReset;
+ struct timer_list timer;
+ struct timer_list tx_delay_timer;
+ struct timer_list tx_retry_timer;
+ struct timer_list rx_check_timer;
+ struct semaphore card_lock;
+ atomic_t card_users;
+ atomic_t delay_on;
+ atomic_t retr_on;
+ int registrationLostCount;
+ int reRegisterExp;
+ int nof_tx;
+ int nof_tx_ack;
+ int last_nof_tx;
+ int last_nof_tx_ack;
+ int irq_test_done;
+ int last_command_was_rx;
+ struct TxParam txRing[TX_RING_SIZE];
+ char reTransmitBuff[0x800];
+ volatile int txLast;
+ volatile int txNew;
+ volatile int txOffset;
+ volatile char ReTransmitRequested;
+ volatile long long tx_done_delayed;
+ volatile long long registrationLastSeen;
+ volatile char under_command;
+ volatile char under_toggle;
+ volatile long long tx_last_sent;
+ volatile long long tx_last_cleared;
+ volatile u_char under_tx;
+ volatile int retransmissions;
+ volatile int tx_chain_active;
+ volatile int timer_chain_active;
+ volatile int interrupt_ack_requested;
+ volatile int command_lock;
+ volatile int rx_command_needed;
+ volatile int tx_command_needed;
+ volatile int waiting_command_mask;
+ volatile int card_polling_interval;
+ volatile int last_command_buff_free_time;
+ volatile int numResets;
+ volatile int under_reset;
+ volatile int under_config;
+ volatile int rx_command_given;
+ volatile int tx_command_given;
+ volatile int interrupt_processing_active;
+ volatile long long last_tx_time;
+ volatile long long last_rx_time;
+ volatile long long last_rx_int_ack_time;
+ int in_bytes;
+ int out_bytes;
+ int in_time;
+ int out_time;
+ int in_time10;
+ int out_time10;
+ int in_bytes10;
+ int out_bytes10;
+};
+
+
+
+#define ARLAN_CLEAR 0x00
+#define ARLAN_RESET 0x01
+#define ARLAN_CHANNEL_ATTENTION 0x02
+#define ARLAN_INTERRUPT_ENABLE 0x04
+#define ARLAN_CLEAR_INTERRUPT 0x08
+#define ARLAN_POWER 0x40
+#define ARLAN_ACCESS 0x80
+
+#define ARLAN_COM_CONF 0x01
+#define ARLAN_COM_RX_ENABLE 0x03
+#define ARLAN_COM_RX_ABORT 0x04
+#define ARLAN_COM_TX_ENABLE 0x05
+#define ARLAN_COM_TX_ABORT 0x06
+#define ARLAN_COM_NOP 0x07
+#define ARLAN_COM_STANDBY 0x08
+#define ARLAN_COM_ACTIVATE 0x09
+#define ARLAN_COM_GOTO_SLOW_POLL 0x0a
+#define ARLAN_COM_INT 0x80
+
+
+#define TXLAST(dev) (((struct arlan_private *)dev->priv)->txRing[((struct arlan_private *)dev->priv)->txLast])
+#define TXHEAD(dev) (((struct arlan_private *)dev->priv)->txRing[0])
+#define TXTAIL(dev) (((struct arlan_private *)dev->priv)->txRing[1])
+
+#define TXBuffStart(dev) \
+ ((int)(((struct arlan_private *)dev->priv)->card)->txBuffer) - ((int)(((struct arlan_private *)dev->priv)->card) )
+#define TXBuffEnd(dev) \
+ ((int)(((struct arlan_private *)dev->priv)->card)->rxBuffer) - ((int)(((struct arlan_private *)dev->priv)->card)
+
+#define READSHM(to,from,atype) {\
+ atype tmp;\
+ memcpy_fromio(&(tmp),&(from),sizeof(atype));\
+ to = tmp;\
+ }
+
+#define READSHMEM(from,atype)\
+ atype from; \
+ READSHM(from, arlan->from, atype);
+
+#define WRITESHM(to,from,atype) \
+ { atype tmpSHM = from;\
+ memcpy_toio(&(to),&tmpSHM,sizeof(atype));\
+ }
+
+#define DEBUGSHM(levelSHM,stringSHM,stuff,atype) \
+ { atype tmpSHM; \
+ memcpy_fromio(&tmpSHM,&(stuff),sizeof(atype));\
+ IFDEBUG(levelSHM) printk(stringSHM,tmpSHM);\
+ }
+
+#define WRITESHMB(to, val) \
+ writeb(val,&(to))
+#define READSHMB(to) \
+ readb(&(to))
+#define WRITESHMS(to, val) \
+ writew(val,&(to))
+#define READSHMS(to) \
+ readw(&(to))
+#define WRITESHMI(to, val) \
+ writel(val,&(to))
+#define READSHMI(to) \
+ readl(&(to))
+
+
+
+
+
+#define registrationBad(dev)\
+ ( ( READSHMB(((struct arlan_private *)dev->priv)->card->registrationMode) > 0) && \
+ ( READSHMB(((struct arlan_private *)dev->priv)->card->registrationStatus) == 0) )
+
+
+#define readControlRegister(dev)\
+ READSHMB(((struct arlan_private *)dev->priv)->card->cntrlRegImage)
+
+#define writeControlRegister(dev, v){\
+ WRITESHMB(((struct arlan_private *)dev->priv)->card->cntrlRegImage ,((v) &0xF) );\
+ WRITESHMB(((struct arlan_private *)dev->priv)->card->controlRegister ,(v) );}
+
+
+#define arlan_interrupt_lancpu(dev) {\
+ int cr; \
+ \
+ priv->under_toggle++; \
+ cr = readControlRegister(dev);\
+ if (cr & ARLAN_CHANNEL_ATTENTION){ \
+ writeControlRegister(dev, (cr & ~ARLAN_CHANNEL_ATTENTION));\
+ }else \
+ writeControlRegister(dev, (cr | ARLAN_CHANNEL_ATTENTION));\
+ priv->under_toggle=0; \
+}
+
+#define clearChannelAttention(dev){ \
+ writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_CHANNEL_ATTENTION);}
+#define setHardwareReset(dev) {\
+ writeControlRegister(dev,readControlRegister(dev) | ARLAN_RESET);}
+#define clearHardwareReset(dev) {\
+ writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_RESET);}
+#define setInterruptEnable(dev){\
+ writeControlRegister(dev,readControlRegister(dev) | ARLAN_INTERRUPT_ENABLE) ;}
+#define clearInterruptEnable(dev){\
+ writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_INTERRUPT_ENABLE) ;}
+#define setClearInterrupt(dev){\
+ writeControlRegister(dev,readControlRegister(dev) | ARLAN_CLEAR_INTERRUPT) ;}
+#define clearClearInterrupt(dev){\
+ writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_CLEAR_INTERRUPT);}
+#define setPowerOff(dev){\
+ writeControlRegister(dev,readControlRegister(dev) | (ARLAN_POWER && ARLAN_ACCESS));\
+ writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_ACCESS);}
+#define setPowerOn(dev){\
+ writeControlRegister(dev,readControlRegister(dev) & ~(ARLAN_POWER)); }
+#define arlan_lock_card_access(dev){\
+ writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_ACCESS);}
+#define arlan_unlock_card_access(dev){\
+ writeControlRegister(dev,readControlRegister(dev) | ARLAN_ACCESS ); }
+
+
+
+
+#define ARLAN_COMMAND_RX 0x00001
+#define ARLAN_COMMAND_NOOP 0x00002
+#define ARLAN_COMMAND_NOOPINT 0x00004
+#define ARLAN_COMMAND_TX 0x00008
+#define ARLAN_COMMAND_CONF 0x00010
+#define ARLAN_COMMAND_RESET 0x00020
+#define ARLAN_COMMAND_TX_ABORT 0x00040
+#define ARLAN_COMMAND_RX_ABORT 0x00080
+#define ARLAN_COMMAND_POWERDOWN 0x00100
+#define ARLAN_COMMAND_POWERUP 0x00200
+#define ARLAN_COMMAND_SLOW_POLL 0x00400
+#define ARLAN_COMMAND_ACTIVATE 0x00800
+#define ARLAN_COMMAND_INT_ACK 0x01000
+#define ARLAN_COMMAND_INT_ENABLE 0x02000
+#define ARLAN_COMMAND_WAIT_NOW 0x04000
+#define ARLAN_COMMAND_LONG_WAIT_NOW 0x08000
+#define ARLAN_COMMAND_STANDBY 0x10000
+#define ARLAN_COMMAND_INT_RACK 0x20000
+#define ARLAN_COMMAND_INT_RENABLE 0x40000
+#define ARLAN_COMMAND_CONF_WAIT 0x80000
+#define ARLAN_COMMAND_CLEAN_AND_CONF (ARLAN_COMMAND_TX_ABORT\
+ | ARLAN_COMMAND_RX_ABORT\
+ | ARLAN_COMMAND_CONF)
+#define ARLAN_COMMAND_CLEAN_AND_RESET (ARLAN_COMMAND_TX_ABORT\
+ | ARLAN_COMMAND_RX_ABORT\
+ | ARLAN_COMMAND_RESET)
+
+
+
+#define ARLAN_DEBUG_CHAIN_LOCKS 0x00001
+#define ARLAN_DEBUG_RESET 0x00002
+#define ARLAN_DEBUG_TIMING 0x00004
+#define ARLAN_DEBUG_CARD_STATE 0x00008
+#define ARLAN_DEBUG_TX_CHAIN 0x00010
+#define ARLAN_DEBUG_MULTICAST 0x00020
+#define ARLAN_DEBUG_HEADER_DUMP 0x00040
+#define ARLAN_DEBUG_INTERRUPT 0x00080
+#define ARLAN_DEBUG_STARTUP 0x00100
+#define ARLAN_DEBUG_SHUTDOWN 0x00200
+ \ No newline at end of file
diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c
index f17950109..8fb48eeb4 100644
--- a/drivers/net/atari_bionet.c
+++ b/drivers/net/atari_bionet.c
@@ -324,8 +324,8 @@ end:
/* Check for a network adaptor of this type, and return '0' if one exists.
*/
-__initfunc(int
-bionet_probe(struct device *dev)) {
+int __init
+bionet_probe(struct device *dev){
unsigned char station_addr[6];
static unsigned version_printed = 0;
static int no_more_found = 0; /* avoid "Probing for..." printed 4 times */
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c
index 269b7de15..83cd0f665 100644
--- a/drivers/net/atari_pamsnet.c
+++ b/drivers/net/atari_pamsnet.c
@@ -561,8 +561,8 @@ bad:
/* Check for a network adaptor of this type, and return '0' if one exists.
*/
-__initfunc(extern int
-pamsnet_probe (dev))
+extern int __init
+pamsnet_probe (dev)
struct device *dev;
{
int i;
diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
index c79fd581e..de439cb27 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/atarilance.c
@@ -370,9 +370,9 @@ void *slow_memcpy( void *dst, const void *src, size_t len )
}
-__initfunc(int atarilance_probe( struct device *dev ))
-
-{ int i;
+int __init atarilance_probe( struct device *dev )
+{
+ int i;
static int found = 0;
if (!MACH_IS_ATARI || found)
@@ -393,9 +393,9 @@ __initfunc(int atarilance_probe( struct device *dev ))
/* Derived from hwreg_present() in atari/config.c: */
-__initfunc(static int addr_accessible( volatile void *regp, int wordflag, int writeflag ))
-
-{ int ret;
+static int __init addr_accessible( volatile void *regp, int wordflag, int writeflag )
+{
+ int ret;
long flags;
long *vbr, save_berr;
@@ -443,10 +443,10 @@ __initfunc(static int addr_accessible( volatile void *regp, int wordflag, int wr
}
-__initfunc(static unsigned long lance_probe1( struct device *dev,
- struct lance_addr *init_rec ))
-
-{ volatile unsigned short *memaddr =
+static unsigned long __init lance_probe1( struct device *dev,
+ struct lance_addr *init_rec )
+{
+ volatile unsigned short *memaddr =
(volatile unsigned short *)init_rec->memaddr;
volatile unsigned short *ioaddr =
(volatile unsigned short *)init_rec->ioaddr;
diff --git a/drivers/net/atp.c b/drivers/net/atp.c
index 658c894b9..4cfed8d92 100644
--- a/drivers/net/atp.c
+++ b/drivers/net/atp.c
@@ -150,8 +150,8 @@ static void set_multicast_list(struct device *dev);
If dev->base_addr == 2, allocate space for the device and return success
(detachable devices only).
*/
-__initfunc(int
-atp_init(struct device *dev))
+int __init
+atp_init(struct device *dev)
{
int *port, ports[] = {0x378, 0x278, 0x3bc, 0};
int base_addr = dev->base_addr;
@@ -173,7 +173,7 @@ atp_init(struct device *dev))
return ENODEV;
}
-__initfunc(static int atp_probe1(struct device *dev, short ioaddr))
+static int __init atp_probe1(struct device *dev, short ioaddr)
{
int saved_ctrl_reg, status;
@@ -259,7 +259,7 @@ __initfunc(static int atp_probe1(struct device *dev, short ioaddr))
}
/* Read the station address PROM, usually a word-wide EEPROM. */
-__initfunc(static void get_node_ID(struct device *dev))
+static void __init get_node_ID(struct device *dev)
{
short ioaddr = dev->base_addr;
int sa_offset = 0;
@@ -291,7 +291,7 @@ __initfunc(static void get_node_ID(struct device *dev))
* DO : _________X_______X
*/
-__initfunc(static unsigned short eeprom_op(short ioaddr, unsigned int cmd))
+static unsigned short __init eeprom_op(short ioaddr, unsigned int cmd)
{
unsigned eedata_out = 0;
int num_bits = EE_CMD_SIZE;
diff --git a/drivers/net/com20020.c b/drivers/net/com20020.c
index 093a5acf0..afadea838 100644
--- a/drivers/net/com20020.c
+++ b/drivers/net/com20020.c
@@ -96,7 +96,7 @@ MODULE_PARM(timeout,"i");
MODULE_PARM(backplane,"i");
MODULE_PARM(clock,"i");
#else
-__initfunc(void com20020_setup (char *str, int *ints));
+void __init com20020_setup (char *str, int *ints);
extern struct device arcnet_devs[];
extern char arcnet_dev_names[][10];
extern int arcnet_num_devs;
@@ -224,7 +224,7 @@ static const char *version =
* it's where we were told it was, and even autoirq
*/
-__initfunc(int arc20020_probe(struct device *dev))
+int __init arc20020_probe(struct device *dev)
{
int ioaddr=dev->base_addr,status,delayval;
unsigned long airqmask;
@@ -327,7 +327,7 @@ __initfunc(int arc20020_probe(struct device *dev))
/* Set up the struct device associated with this card. Called after
* probing succeeds.
*/
-__initfunc(int arc20020_found(struct device *dev,int ioaddr,int airq))
+int __init arc20020_found(struct device *dev,int ioaddr,int airq)
{
struct arcnet_local *lp;
@@ -1035,7 +1035,7 @@ void cleanup_module(void)
#else
-__initfunc(void com20020_setup (char *str, int *ints))
+void __init com20020_setup (char *str, int *ints)
{
struct device *dev;
diff --git a/drivers/net/com90io.c b/drivers/net/com90io.c
index 309654460..2e9ea0660 100644
--- a/drivers/net/com90io.c
+++ b/drivers/net/com90io.c
@@ -87,7 +87,7 @@ MODULE_PARM(io, "i");
MODULE_PARM(irq, "i");
MODULE_PARM(device, "s");
#else
-__initfunc(void com90io_setup (char *str, int *ints));
+void __init com90io_setup (char *str, int *ints);
extern struct device arcnet_devs[];
extern char arcnet_dev_names[][10];
extern int arcnet_num_devs;
@@ -193,7 +193,7 @@ static const char *version =
* it's where we were told it was, and even autoirq
*/
-__initfunc(int arc90io_probe(struct device *dev))
+int __init arc90io_probe(struct device *dev)
{
int ioaddr=dev->base_addr,status,delayval;
unsigned long airqmask;
@@ -287,7 +287,7 @@ __initfunc(int arc90io_probe(struct device *dev))
/* Set up the struct device associated with this card. Called after
* probing succeeds.
*/
-__initfunc(int arc90io_found(struct device *dev,int ioaddr,int airq))
+int __init arc90io_found(struct device *dev,int ioaddr,int airq)
{
struct arcnet_local *lp;
@@ -914,7 +914,7 @@ void cleanup_module(void)
#else
-__initfunc(void com90io_setup (char *str, int *ints))
+void __init com90io_setup (char *str, int *ints)
{
struct device *dev;
diff --git a/drivers/net/com90xx.c b/drivers/net/com90xx.c
index 3ca5a5ef8..be4514fab 100644
--- a/drivers/net/com90xx.c
+++ b/drivers/net/com90xx.c
@@ -117,7 +117,7 @@ MODULE_PARM(irq, "i");
MODULE_PARM(shmem, "i");
MODULE_PARM(device, "s");
#else
-__initfunc(void com90xx_setup(char *str, int *ints));
+void __init com90xx_setup(char *str, int *ints);
char __initdata com90xx_explicit = 0;
extern struct device arcnet_devs[];
@@ -179,7 +179,7 @@ static u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] __initdata = {
0
};
-__initfunc(int arc90xx_probe(struct device *dev))
+int __init arc90xx_probe(struct device *dev)
{
static int init_once = 0;
static int numports = sizeof(ports) / sizeof(ports[0]), numshmems = sizeof(shmems) / sizeof(shmems[0]);
@@ -399,7 +399,7 @@ __initfunc(int arc90xx_probe(struct device *dev))
*/
airqmask = probe_irq_on();
AINTMASK(NORXflag);
- udelay(1);
+ mdelay(1);
AINTMASK(0);
airq = probe_irq_off(airqmask);
@@ -493,7 +493,7 @@ __initfunc(int arc90xx_probe(struct device *dev))
/* Set up the struct device associated with this card. Called after
* probing succeeds.
*/
-__initfunc(static int arc90xx_found(struct device *dev, int ioaddr, int airq, u_long shmem, int more))
+static int __init arc90xx_found(struct device *dev, int ioaddr, int airq, u_long shmem, int more)
{
struct arcnet_local *lp;
u_long first_mirror, last_mirror;
@@ -1121,7 +1121,7 @@ void cleanup_module(void)
#else
-__initfunc(void com90xx_setup(char *str, int *ints))
+void __init com90xx_setup(char *str, int *ints)
{
struct device *dev;
diff --git a/drivers/net/cops.c b/drivers/net/cops.c
index e920debeb..0d3469204 100644
--- a/drivers/net/cops.c
+++ b/drivers/net/cops.c
@@ -218,7 +218,7 @@ static struct enet_statistics *cops_get_stats (struct device *dev);
* If dev->base_addr in [1..0x1ff], always return failure.
* otherwise go with what we pass in.
*/
-__initfunc(int cops_probe(struct device *dev))
+int __init cops_probe(struct device *dev)
{
int i;
int base_addr = dev ? dev->base_addr : 0;
@@ -252,7 +252,7 @@ __initfunc(int cops_probe(struct device *dev))
* probes on the ISA bus. A good device probes avoids doing writes, and
* verifies that the correct device exists and functions.
*/
-__initfunc(static int cops_probe1(struct device *dev, int ioaddr))
+static int __init cops_probe1(struct device *dev, int ioaddr)
{
struct cops_local *lp;
static unsigned version_printed = 0;
@@ -348,7 +348,7 @@ __initfunc(static int cops_probe1(struct device *dev, int ioaddr))
return 0;
}
-__initfunc(static int cops_irq (int ioaddr, int board))
+static int __init cops_irq (int ioaddr, int board)
{ /*
* This does not use the IRQ to determine where the IRQ is. We just
* assume that when we get a correct status response that it's the IRQ.
diff --git a/drivers/net/cosa.c b/drivers/net/cosa.c
index 8db7657ee..fdfa991b9 100644
--- a/drivers/net/cosa.c
+++ b/drivers/net/cosa.c
@@ -362,7 +362,7 @@ static void debug_status_out(struct cosa_data *cosa, int status);
#ifdef MODULE
int init_module(void)
#else
-__initfunc(static int cosa_init(void))
+static int __init cosa_init(void)
#endif
{
int i;
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index b4e4a911b..3867c58d3 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -145,8 +145,8 @@ static int set_mac_address(struct device *dev, void *addr);
struct netdev_entry netcard_drv =
{"netcard", cs89x0_probe1, NETCARD_IO_EXTENT, netcard_portlist};
#else
-__initfunc(int
-cs89x0_probe(struct device *dev))
+int __init
+cs89x0_probe(struct device *dev)
{
int i;
int base_addr = dev ? dev->base_addr : 0;
@@ -195,8 +195,8 @@ writeword(struct device *dev, int portno, int value)
outw(value, dev->base_addr + portno);
}
-__initfunc(static int
-wait_eeprom_ready(struct device *dev))
+static int __init
+wait_eeprom_ready(struct device *dev)
{
int timeout = jiffies;
/* check to see if the EEPROM is ready, a timeout is used -
@@ -208,8 +208,8 @@ wait_eeprom_ready(struct device *dev))
return 0;
}
-__initfunc(static int
-get_eeprom_data(struct device *dev, int off, int len, int *buffer))
+static int __init
+get_eeprom_data(struct device *dev, int off, int len, int *buffer)
{
int i;
@@ -226,8 +226,8 @@ get_eeprom_data(struct device *dev, int off, int len, int *buffer))
return 0;
}
-__initfunc(static int
-get_eeprom_cksum(int off, int len, int *buffer))
+static int __init
+get_eeprom_cksum(int off, int len, int *buffer)
{
int i, cksum;
@@ -244,7 +244,7 @@ get_eeprom_cksum(int off, int len, int *buffer))
probes on the ISA bus. A good device probes avoids doing writes, and
verifies that the correct device exists and functions. */
-__initfunc(static int cs89x0_probe1(struct device *dev, int ioaddr))
+static int __init cs89x0_probe1(struct device *dev, int ioaddr)
{
struct net_local *lp;
static unsigned version_printed = 0;
@@ -390,10 +390,8 @@ __initfunc(static int cs89x0_probe1(struct device *dev, int ioaddr))
return 0;
}
-
-
-__initfunc(void
-reset_chip(struct device *dev))
+void __init
+reset_chip(struct device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr = dev->base_addr;
diff --git a/drivers/net/de4x5.c b/drivers/net/de4x5.c
index f0edae261..ccd35038e 100644
--- a/drivers/net/de4x5.c
+++ b/drivers/net/de4x5.c
@@ -1106,8 +1106,8 @@ static int (*dc_infoblock[])(struct device *dev, u_char, u_char *) = {
** Autoprobing in modules is allowed here. See the top of the file for
** more info.
*/
-__initfunc(int
-de4x5_probe(struct device *dev))
+int __init
+de4x5_probe(struct device *dev)
{
u_long iobase = dev->base_addr;
@@ -1121,8 +1121,8 @@ de4x5_probe(struct device *dev))
return (dev->priv ? 0 : -ENODEV);
}
-__initfunc(static int
-de4x5_hw_init(struct device *dev, u_long iobase))
+static int __init
+de4x5_hw_init(struct device *dev, u_long iobase)
{
struct bus_type *lp = &bus;
int i, status=0;
@@ -2054,8 +2054,8 @@ SetMulticastFilter(struct device *dev)
** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
** the motherboard. Upto 15 EISA devices are supported.
*/
-__initfunc(static void
-eisa_probe(struct device *dev, u_long ioaddr))
+static void __init
+eisa_probe(struct device *dev, u_long ioaddr)
{
int i, maxSlots, status, device;
u_char irq;
@@ -2136,8 +2136,8 @@ eisa_probe(struct device *dev, u_long ioaddr))
*/
#define PCI_LAST_DEV 32
-__initfunc(static void
-pci_probe(struct device *dev, u_long ioaddr))
+static void __init
+pci_probe(struct device *dev, u_long ioaddr)
{
u_char pb, pbus, dev_num, dnum, timer;
u_short vendor, index, status;
@@ -2248,8 +2248,8 @@ pci_probe(struct device *dev, u_long ioaddr))
** DECchips, we can find the base SROM irrespective of the BIOS scan direction.
** For single port cards this is a time waster...
*/
-__initfunc(static void
-srom_search(struct pci_dev *dev))
+static void __init
+srom_search(struct pci_dev *dev)
{
u_char pb;
u_short vendor, status;
@@ -2307,8 +2307,8 @@ srom_search(struct pci_dev *dev))
return;
}
-__initfunc(static void
-link_modules(struct device *dev, struct device *tmp))
+static void __init
+link_modules(struct device *dev, struct device *tmp)
{
struct device *p=dev;
@@ -5559,17 +5559,15 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
switch(ioc->cmd) {
case DE4X5_GET_HWADDR: /* Get the hardware address */
ioc->len = ETH_ALEN;
- if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;
for (i=0; i<ETH_ALEN; i++) {
tmp.addr[i] = dev->dev_addr[i];
}
- copy_to_user(ioc->data, tmp.addr, ioc->len);
+ if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
break;
case DE4X5_SET_HWADDR: /* Set the hardware address */
if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (verify_area(VERIFY_READ, ioc->data, ETH_ALEN)) return -EFAULT;
- copy_from_user(tmp.addr, ioc->data, ETH_ALEN);
+ if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) return -EFAULT;
for (i=0; i<ETH_ALEN; i++) {
dev->dev_addr[i] = tmp.addr[i];
}
@@ -5612,9 +5610,8 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
case DE4X5_GET_STATS: /* Get the driver statistics */
ioc->len = sizeof(lp->pktStats);
- if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;
spin_lock_irqsave(&lp->lock, flags);
- copy_to_user(ioc->data, &lp->pktStats, ioc->len);
+ if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) return -EFAULT;
spin_unlock_irqrestore(&lp->lock, flags);
break;
@@ -5627,14 +5624,12 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
case DE4X5_GET_OMR: /* Get the OMR Register contents */
tmp.addr[0] = inl(DE4X5_OMR);
- if (verify_area(VERIFY_WRITE, ioc->data, 1)) return -EFAULT;
- copy_to_user(ioc->data, tmp.addr, 1);
+ if (copy_to_user(ioc->data, tmp.addr, 1)) return -EFAULT;
break;
case DE4X5_SET_OMR: /* Set the OMR Register contents */
if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (verify_area(VERIFY_READ, ioc->data, 1)) return -EFAULT;
- copy_from_user(tmp.addr, ioc->data, 1);
+ if (copy_from_user(tmp.addr, ioc->data, 1)) return -EFAULT;
outl(tmp.addr[0], DE4X5_OMR);
break;
@@ -5649,8 +5644,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
tmp.lval[6] = inl(DE4X5_STRR); j+=4;
tmp.lval[7] = inl(DE4X5_SIGR); j+=4;
ioc->len = j;
- if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;
- copy_to_user(ioc->data, tmp.addr, ioc->len);
+ if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
break;
#define DE4X5_DUMP 0x0f /* Dump the DE4X5 Status */
@@ -5739,8 +5733,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
tmp.addr[j++] = dev->tbusy;
ioc->len = j;
- if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;
- copy_to_user(ioc->data, tmp.addr, ioc->len);
+ if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
break;
*/
@@ -5863,8 +5856,8 @@ count_adapters(void)
** If at end of eth device list and can't use current entry, malloc
** one up. If memory could not be allocated, print an error message.
*/
-__initfunc(static struct device *
-insert_device(struct device *dev, u_long iobase, int (*init)(struct device *)))
+static struct device * __init
+insert_device(struct device *dev, u_long iobase, int (*init)(struct device *))
{
struct device *new;
diff --git a/drivers/net/de600.c b/drivers/net/de600.c
index 03a3205ed..5e8050300 100644
--- a/drivers/net/de600.c
+++ b/drivers/net/de600.c
@@ -627,8 +627,8 @@ de600_rx_intr(struct device *dev)
*/
}
-__initfunc(int
-de600_probe(struct device *dev))
+int __init
+de600_probe(struct device *dev)
{
int i;
static struct net_device_stats de600_netstats;
diff --git a/drivers/net/de620.c b/drivers/net/de620.c
index 28a318637..8ae2803a3 100644
--- a/drivers/net/de620.c
+++ b/drivers/net/de620.c
@@ -820,8 +820,8 @@ adapter_init(struct device *dev)
*
* Check if there is a DE-620 connected
*/
-__initfunc(int
-de620_probe(struct device *dev))
+int __init
+de620_probe(struct device *dev)
{
static struct net_device_stats de620_netstats;
int i;
@@ -913,8 +913,8 @@ de620_probe(struct device *dev))
*/
#define sendit(dev,data) de620_set_register(dev, W_EIP, data | EIPRegister);
-__initfunc(static unsigned short
-ReadAWord(struct device *dev, int from))
+static unsigned short __init
+ReadAWord(struct device *dev, int from)
{
unsigned short data;
int nbits;
@@ -956,8 +956,8 @@ ReadAWord(struct device *dev, int from))
return data;
}
-__initfunc(static int
-read_eeprom(struct device *dev))
+static int __init
+read_eeprom(struct device *dev)
{
unsigned short wrd;
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index 3a3dd6af8..84915977e 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -446,11 +446,8 @@ static inline void dfx_port_read_long(
* the device structure.
*/
-__initfunc(int dfx_probe(
- struct device *dev
- ))
-
- {
+int __init dfx_probe(struct device *dev)
+{
int i; /* used in for loops */
int version_disp; /* was version info string already displayed? */
int port_len; /* length of port address range (in bytes) */
@@ -641,12 +638,8 @@ __initfunc(int dfx_probe(
* None
*/
-__initfunc(struct device *dfx_alloc_device(
- struct device *dev,
- u16 iobase
- ))
-
- {
+struct device __init *dfx_alloc_device( struct device *dev, u16 iobase)
+{
struct device *tmp_dev; /* pointer to a device structure */
DBG_printk("In dfx_alloc_device...\n");
@@ -736,11 +729,8 @@ __initfunc(struct device *dfx_alloc_device(
* enabled yet.
*/
-__initfunc(void dfx_bus_init(
- struct device *dev
- ))
-
- {
+void __init dfx_bus_init(struct device *dev)
+{
DFX_board_t *bp = (DFX_board_t *)dev->priv;
u8 val; /* used for I/O read/writes */
@@ -871,11 +861,8 @@ __initfunc(void dfx_bus_init(
* None
*/
-__initfunc(void dfx_bus_config_check(
- DFX_board_t *bp
- ))
-
- {
+void __init dfx_bus_config_check(DFX_board_t *bp)
+{
int status; /* return code from adapter port control call */
u32 slot_id; /* EISA-bus hardware id (DEC3001, DEC3002,...) */
u32 host_data; /* LW data returned from port control call */
@@ -975,11 +962,8 @@ __initfunc(void dfx_bus_config_check(
* returning from this routine.
*/
-__initfunc(int dfx_driver_init(
- struct device *dev
- ))
-
- {
+int __init dfx_driver_init(struct device *dev)
+{
DFX_board_t *bp = (DFX_board_t *)dev->priv;
int alloc_size; /* total buffer size needed */
char *top_v, *curr_v; /* virtual addrs into memory block */
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index 68250ade1..1be3c5dda 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -476,10 +476,8 @@ static char *adapter_name = '\0'; /* If no PROM when loadable module
outw(CSR0, DEPCA_ADDR);\
outw(STOP, DEPCA_DATA)
-
-
-__initfunc(int
-depca_probe(struct device *dev))
+int __init
+depca_probe(struct device *dev)
{
int tmp = num_depcas, status = -ENODEV;
u_long iobase = dev->base_addr;
@@ -512,8 +510,8 @@ depca_probe(struct device *dev))
return status;
}
-__initfunc(static int
-depca_hw_init(struct device *dev, u_long ioaddr, int mca_slot))
+static int __init
+depca_hw_init(struct device *dev, u_long ioaddr, int mca_slot)
{
struct depca_private *lp;
int i, j, offset, netRAM, mem_len, status=0;
@@ -1250,8 +1248,8 @@ static void SetMulticastFilter(struct device *dev)
/*
** Microchannel bus I/O device probe
*/
-__initfunc(static void
-mca_probe(struct device *dev, u_long ioaddr))
+static void __init
+mca_probe(struct device *dev, u_long ioaddr)
{
unsigned char pos[2];
unsigned char where;
@@ -1399,8 +1397,8 @@ responding.\n", dev->name, iobase);
/*
** ISA bus I/O device probe
*/
-__initfunc(static void
-isa_probe(struct device *dev, u_long ioaddr))
+static void __init
+isa_probe(struct device *dev, u_long ioaddr)
{
int i = num_depcas, maxSlots;
s32 ports[] = DEPCA_IO_PORTS;
@@ -1438,8 +1436,8 @@ isa_probe(struct device *dev, u_long ioaddr))
** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
** the motherboard. Upto 15 EISA devices are supported.
*/
-__initfunc(static void
-eisa_probe(struct device *dev, u_long ioaddr))
+static void __init
+eisa_probe(struct device *dev, u_long ioaddr)
{
int i, maxSlots;
u_long iobase;
@@ -1485,8 +1483,8 @@ eisa_probe(struct device *dev, u_long ioaddr))
** are not available then insert a new device structure at the end of
** the current list.
*/
-__initfunc(static struct device *
-alloc_device(struct device *dev, u_long iobase))
+static struct device * __init
+alloc_device(struct device *dev, u_long iobase)
{
struct device *adev = NULL;
int fixed = 0, new_dev = 0;
@@ -1530,8 +1528,8 @@ alloc_device(struct device *dev, u_long iobase))
** If at end of eth device list and can't use current entry, malloc
** one up. If memory could not be allocated, print an error message.
*/
-__initfunc(static struct device *
-insert_device(struct device *dev, u_long iobase, int (*init)(struct device *)))
+static struct device * __init
+insert_device(struct device *dev, u_long iobase, int (*init)(struct device *))
{
struct device *new;
@@ -1556,8 +1554,8 @@ insert_device(struct device *dev, u_long iobase, int (*init)(struct device *)))
return dev;
}
-__initfunc(static int
-depca_dev_index(char *s))
+static int __init
+depca_dev_index(char *s)
{
int i=0, j=0;
@@ -1576,8 +1574,8 @@ depca_dev_index(char *s))
** and Boot (readb) ROM. This will also give us a clue to the network RAM
** base address.
*/
-__initfunc(static void
-DepcaSignature(char *name, u_long paddr))
+static void __init
+DepcaSignature(char *name, u_long paddr)
{
u_int i,j,k;
const char *signatures[] = DEPCA_SIGNATURE;
@@ -1629,8 +1627,8 @@ DepcaSignature(char *name, u_long paddr))
** PROM address counter is correctly positioned at the start of the
** ethernet address for later read out.
*/
-__initfunc(static int
-DevicePresent(u_long ioaddr))
+static int __init
+DevicePresent(u_long ioaddr)
{
union {
struct {
@@ -1682,8 +1680,8 @@ DevicePresent(u_long ioaddr))
** reason: access the upper half of the PROM with x=0; access the lower half
** with x=1.
*/
-__initfunc(static int
-get_hw_addr(struct device *dev))
+static int __init
+get_hw_addr(struct device *dev)
{
u_long ioaddr = dev->base_addr;
int i, k, tmp, status = 0;
@@ -1771,8 +1769,8 @@ static int load_packet(struct device *dev, struct sk_buff *skb)
/*
** Look for a particular board name in the EISA configuration space
*/
-__initfunc(static int
-EISA_signature(char *name, s32 eisa_id))
+static int __init
+EISA_signature(char *name, s32 eisa_id)
{
u_int i;
const char *signatures[] = DEPCA_SIGNATURE;
diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c
index 2d4e08482..8588a8b4a 100644
--- a/drivers/net/dgrs.c
+++ b/drivers/net/dgrs.c
@@ -991,8 +991,8 @@ ack_intr:
/*
* Download the board firmware
*/
-__initfunc(static int
-dgrs_download(struct device *dev0))
+static int __init
+dgrs_download(struct device *dev0)
{
DGRS_PRIV *priv0 = (DGRS_PRIV *) dev0->priv;
int is;
@@ -1150,8 +1150,8 @@ dgrs_download(struct device *dev0))
/*
* Probe (init) a board
*/
-__initfunc(int
-dgrs_probe1(struct device *dev))
+int __init
+dgrs_probe1(struct device *dev)
{
DGRS_PRIV *priv = (DGRS_PRIV *) dev->priv;
int i;
@@ -1224,8 +1224,8 @@ dgrs_probe1(struct device *dev))
return (0);
}
-__initfunc(int
-dgrs_initclone(struct device *dev))
+int __init
+dgrs_initclone(struct device *dev)
{
DGRS_PRIV *priv = (DGRS_PRIV *) dev->priv;
int i;
@@ -1239,7 +1239,7 @@ dgrs_initclone(struct device *dev))
return (0);
}
-__initfunc(static int
+static int __init
dgrs_found_device(
struct device *dev,
int io,
@@ -1247,7 +1247,7 @@ dgrs_found_device(
int irq,
ulong plxreg,
ulong plxdma
-))
+)
{
DGRS_PRIV *priv;
@@ -1360,8 +1360,8 @@ dgrs_found_device(
*/
static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 };
-__initfunc(static int
-dgrs_scan(struct device *dev))
+static int __init
+dgrs_scan(struct device *dev)
{
int cards_found = 0;
uint io;
@@ -1614,8 +1614,8 @@ cleanup_module(void)
#else
-__initfunc(int
-dgrs_probe(struct device *dev))
+int __init
+dgrs_probe(struct device *dev)
{
int cards_found;
diff --git a/drivers/net/dlci.c b/drivers/net/dlci.c
index 6343463d0..9d177a0b7 100644
--- a/drivers/net/dlci.c
+++ b/drivers/net/dlci.c
@@ -601,7 +601,7 @@ int dlci_init(struct device *dev)
return(0);
}
-__initfunc(int dlci_setup(void))
+int __init dlci_setup(void)
{
int i;
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 8d4ea3b05..c27d4628c 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -80,7 +80,7 @@ static int dummy_accept_fastpath(struct device *dev, struct dst_entry *dst)
}
#endif
-__initfunc(int dummy_init(struct device *dev))
+int __init dummy_init(struct device *dev)
{
/* Initialize the device structure. */
dev->hard_start_xmit = dummy_xmit;
@@ -127,7 +127,7 @@ static struct net_device_stats *dummy_get_stats(struct device *dev)
#ifdef MODULE
-__initfunc(static int dummy_probe(struct device *dev))
+static int __init dummy_probe(struct device *dev)
{
dummy_init(dev);
return 0;
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index 529158e81..571ff901b 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -117,7 +117,7 @@ static int e21_close(struct device *dev);
station address).
*/
-__initfunc(int e2100_probe(struct device *dev))
+int __init e2100_probe(struct device *dev)
{
int *port;
int base_addr = dev->base_addr;
@@ -137,7 +137,7 @@ __initfunc(int e2100_probe(struct device *dev))
return ENODEV;
}
-__initfunc(int e21_probe1(struct device *dev, int ioaddr))
+int __init e21_probe1(struct device *dev, int ioaddr)
{
int i, status;
unsigned char *station_addr = dev->dev_addr;
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 56858bc45..69d383a45 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -41,7 +41,7 @@ static int rx_copybreak = 200;
static int max_interrupt_work = 200;
/* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */
-static int multicast_filter_limit = 64;
+static int multicast_filter_limit = 3;
#include <linux/module.h>
@@ -343,7 +343,8 @@ struct speedo_private {
const char *product_name;
struct device *next_module;
spinlock_t lock;
- struct TxFD tx_ring[TX_RING_SIZE]; /* Commands (usually CmdTxPacket). */
+ struct TxFD tx_ring[TX_RING_SIZE] /* Commands (usually CmdTxPacket). */
+ __attribute__ ((aligned (L1_CACHE_BYTES)));;
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
struct sk_buff* tx_skbuff[TX_RING_SIZE];
struct descriptor *last_cmd; /* Last command sent. */
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 51af63aa4..f8088862e 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -325,7 +325,7 @@ static inline unsigned short int SHADOW(short int addr)
* checks for presence of EtherExpress card
*/
-__initfunc(int express_probe(struct device *dev))
+int __init express_probe(struct device *dev)
{
unsigned short *port;
static unsigned short ports[] = { 0x300,0x310,0x270,0x320,0x340,0 };
@@ -961,7 +961,7 @@ static void eexp_hw_tx_pio(struct device *dev, unsigned short *buf,
* than one card in a machine.
*/
-__initfunc(static int eexp_hw_probe(struct device *dev, unsigned short ioaddr))
+static int __init eexp_hw_probe(struct device *dev, unsigned short ioaddr)
{
unsigned short hw_addr[3];
unsigned char buswidth;
@@ -1084,8 +1084,8 @@ __initfunc(static int eexp_hw_probe(struct device *dev, unsigned short ioaddr))
* Read a word from the EtherExpress on-board serial EEPROM.
* The EEPROM contains 64 words of 16 bits.
*/
-__initfunc(static unsigned short eexp_hw_readeeprom(unsigned short ioaddr,
- unsigned char location))
+static unsigned short __init eexp_hw_readeeprom(unsigned short ioaddr,
+ unsigned char location)
{
unsigned short cmd = 0x180|(location&0x7f);
unsigned short rval = 0,wval = EC_CS|i586_RST;
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index 165d4fefe..d677dbf1b 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -209,7 +209,7 @@ static void eql_timer(unsigned long param); /* */
---------------------------------------------------------
*/
-__initfunc(int eql_init(struct device *dev))
+int __init eql_init(struct device *dev)
{
static unsigned version_printed = 0;
/* static unsigned num_masters = 0; */
@@ -411,16 +411,15 @@ static int eql_enslave(struct device *dev, slaving_request_t *srqp)
slaving_request_t srq;
int err;
- err = verify_area(VERIFY_READ, (void *)srqp, sizeof (slaving_request_t));
+ err = copy_from_user(&srq, srqp, sizeof (slaving_request_t));
if (err)
{
#ifdef EQL_DEBUG
if (eql_debug >= 20)
- printk ("EQL enslave: error detected by verify_area\n");
+ printk ("EQL enslave: error detected by copy_from_user\n");
#endif
return err;
}
- copy_from_user (&srq, srqp, sizeof (slaving_request_t));
#ifdef EQL_DEBUG
if (eql_debug >= 20)
@@ -473,11 +472,10 @@ static int eql_emancipate(struct device *dev, slaving_request_t *srqp)
slaving_request_t srq;
int err;
- err = verify_area(VERIFY_READ, (void *)srqp, sizeof (slaving_request_t));
+ err = copy_from_user(&srq, srqp, sizeof (slaving_request_t));
if (err)
return err;
- copy_from_user (&srq, srqp, sizeof (slaving_request_t));
#ifdef EQL_DEBUG
if (eql_debug >= 20)
printk ("%s: emancipate `%s`\n", dev->name, srq.slave_name);
@@ -504,11 +502,10 @@ static int eql_g_slave_cfg(struct device *dev, slave_config_t *scp)
slave_config_t sc;
int err;
- err = verify_area(VERIFY_READ, (void *)scp, sizeof (slave_config_t));
+ err = copy_from_user (&sc, scp, sizeof (slave_config_t));
if (err)
return err;
- copy_from_user (&sc, scp, sizeof (slave_config_t));
#ifdef EQL_DEBUG
if (eql_debug >= 20)
printk ("%s: get config for slave `%s'\n", dev->name, sc.slave_name);
@@ -541,7 +538,7 @@ static int eql_s_slave_cfg(struct device *dev, slave_config_t *scp)
slave_config_t sc;
int err;
- err = verify_area(VERIFY_READ, (void *)scp, sizeof (slave_config_t));
+ err = copy_from_user (&sc, scp, sizeof (slave_config_t));
if (err)
return err;
@@ -550,7 +547,6 @@ static int eql_s_slave_cfg(struct device *dev, slave_config_t *scp)
printk ("%s: set config for slave `%s'\n", dev->name, sc.slave_name);
#endif
- copy_from_user (&sc, scp, sizeof (slave_config_t));
eql = (equalizer_t *) dev->priv;
slave_dev = dev_get (sc.slave_name);
@@ -583,13 +579,12 @@ static int eql_g_master_cfg(struct device *dev, master_config_t *mcp)
if ( eql_is_master (dev) )
{
int err;
- err = verify_area(VERIFY_WRITE, (void *)mcp, sizeof (master_config_t));
- if (err)
- return err;
eql = (equalizer_t *) dev->priv;
mc.max_slaves = eql->max_slaves;
mc.min_slaves = eql->min_slaves;
- copy_to_user (mcp, &mc, sizeof (master_config_t));
+ err = copy_to_user (mcp, &mc, sizeof (master_config_t));
+ if (err)
+ return err;
return 0;
}
return -EINVAL;
@@ -602,14 +597,13 @@ static int eql_s_master_cfg(struct device *dev, master_config_t *mcp)
master_config_t mc;
int err;
- err = verify_area(VERIFY_READ, (void *)mcp, sizeof (master_config_t));
+ err = copy_from_user (&mc, mcp, sizeof (master_config_t));
if (err)
return err;
#if EQL_DEBUG
if (eql_debug >= 20)
printk ("%s: set master config\n", dev->name);
#endif
- copy_from_user (&mc, mcp, sizeof (master_config_t));
if ( eql_is_master (dev) )
{
eql = (equalizer_t *) dev->priv;
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index f57e76cda..71d0631e7 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -124,7 +124,7 @@ static unsigned char hi_irq_map[] __initdata = {11, 12, 0, 14, 0, 0, 0, 15};
* PROM for a match against the Racal-Interlan assigned value.
*/
-__initfunc(int es_probe(struct device *dev))
+int __init es_probe(struct device *dev)
{
unsigned short ioaddr = dev->base_addr;
@@ -151,7 +151,7 @@ __initfunc(int es_probe(struct device *dev))
return ENODEV;
}
-__initfunc(int es_probe1(struct device *dev, int ioaddr))
+int __init es_probe1(struct device *dev, int ioaddr)
{
int i;
unsigned long eisa_id;
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index 391f6194a..8958374d4 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -450,7 +450,7 @@ static char *cardname = "ICL EtherTeam 16i/32";
#else /* Not HAVE_DEVLIST */
-__initfunc(int eth16i_probe(struct device *dev))
+int __init eth16i_probe(struct device *dev)
{
int i;
int ioaddr;
@@ -484,7 +484,7 @@ __initfunc(int eth16i_probe(struct device *dev))
}
#endif /* Not HAVE_DEVLIST */
-__initfunc(static int eth16i_probe1(struct device *dev, int ioaddr))
+static int __init eth16i_probe1(struct device *dev, int ioaddr)
{
static unsigned version_printed = 0;
boot = 1; /* To inform initilization that we are in boot probe */
@@ -886,7 +886,7 @@ static int eth16i_check_signature(int ioaddr)
creg[0] &= 0x0F; /* Mask collision cnr */
creg[2] &= 0x7F; /* Mask DCLEN bit */
-#ifdef 0
+#if 0
/*
This was removed because the card was sometimes left to state
from which it couldn't be find anymore. If there is need
diff --git a/drivers/net/ethertap.c b/drivers/net/ethertap.c
index cc478fb2e..d0cc26e51 100644
--- a/drivers/net/ethertap.c
+++ b/drivers/net/ethertap.c
@@ -65,7 +65,7 @@ struct net_local
* hardware it would have to check what was present.
*/
-__initfunc(int ethertap_probe(struct device *dev))
+int __init ethertap_probe(struct device *dev)
{
memcpy(dev->dev_addr, "\xFE\xFD\x00\x00\x00\x00", 6);
if (dev->mem_start & 0xf)
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index 5618f1fcd..5f3b8d744 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -342,11 +342,8 @@ static int num_ewrk3s = 0, num_eth = 0;
outb(EEPROM_INIT, EWRK3_IOPR);\
mdelay(1);\
}
-
-
-
-__initfunc(int ewrk3_probe(struct device *dev))
+int __init ewrk3_probe(struct device *dev)
{
int tmp = num_ewrk3s, status = -ENODEV;
u_long iobase = dev->base_addr;
@@ -378,8 +375,8 @@ __initfunc(int ewrk3_probe(struct device *dev))
return status;
}
-__initfunc(static int
- ewrk3_hw_init(struct device *dev, u_long iobase))
+static int __init
+ewrk3_hw_init(struct device *dev, u_long iobase)
{
struct ewrk3_private *lp;
int i, status = 0;
@@ -1285,7 +1282,7 @@ static void SetMulticastFilter(struct device *dev)
/*
** ISA bus I/O device probe
*/
-__initfunc(static void isa_probe(struct device *dev, u_long ioaddr))
+static void __init isa_probe(struct device *dev, u_long ioaddr)
{
int i = num_ewrk3s, maxSlots;
u_long iobase;
@@ -1325,7 +1322,7 @@ __initfunc(static void isa_probe(struct device *dev, u_long ioaddr))
** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
** the motherboard.
*/
-__initfunc(static void eisa_probe(struct device *dev, u_long ioaddr))
+static void __init eisa_probe(struct device *dev, u_long ioaddr)
{
int i, maxSlots;
u_long iobase;
@@ -1372,8 +1369,8 @@ __initfunc(static void eisa_probe(struct device *dev, u_long ioaddr))
** are not available then insert a new device structure at the end of
** the current list.
*/
-__initfunc(static struct device *
- alloc_device(struct device *dev, u_long iobase))
+static struct device * __init
+alloc_device(struct device *dev, u_long iobase)
{
struct device *adev = NULL;
int fixed = 0, new_dev = 0;
@@ -1417,8 +1414,8 @@ __initfunc(static struct device *
** If at end of eth device list and can't use current entry, malloc
** one up. If memory could not be allocated, print an error message.
*/
-__initfunc(static struct device *
- insert_device(struct device *dev, u_long iobase, int (*init) (struct device *)))
+static __init struct device *
+insert_device(struct device *dev, u_long iobase, int (*init) (struct device *))
{
struct device *new;
@@ -1443,8 +1440,8 @@ __initfunc(static struct device *
return dev;
}
-__initfunc(static int
- ewrk3_dev_index(char *s))
+static int __init
+ewrk3_dev_index(char *s)
{
int i = 0, j = 0;
@@ -1499,7 +1496,7 @@ static int Write_EEPROM(short data, u_long iobase, u_char eaddr)
/*
** Look for a particular board name in the on-board EEPROM.
*/
-__initfunc(static void EthwrkSignature(char *name, char *eeprom_image))
+static void __init EthwrkSignature(char *name, char *eeprom_image)
{
u_long i, j, k;
char *signatures[] = EWRK3_SIGNATURE;
@@ -1536,7 +1533,7 @@ __initfunc(static void EthwrkSignature(char *name, char *eeprom_image))
** ethernet address for later read out.
*/
-__initfunc(static int DevicePresent(u_long iobase))
+static int __init DevicePresent(u_long iobase)
{
union {
struct {
@@ -1573,7 +1570,7 @@ __initfunc(static int DevicePresent(u_long iobase))
return status;
}
-__initfunc(static u_char get_hw_addr(struct device *dev, u_char * eeprom_image, char chipType))
+static u_char __init get_hw_addr(struct device *dev, u_char * eeprom_image, char chipType)
{
int i, j, k;
u_short chksum;
@@ -1624,7 +1621,7 @@ __initfunc(static u_char get_hw_addr(struct device *dev, u_char * eeprom_image,
/*
** Look for a particular board name in the EISA configuration space
*/
-__initfunc(static int EISA_signature(char *name, s32 eisa_id))
+static int __init EISA_signature(char *name, s32 eisa_id)
{
u_long i;
char *signatures[] = EWRK3_SIGNATURE;
@@ -1679,18 +1676,20 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
tmp.addr[i] = dev->dev_addr[i];
}
ioc->len = ETH_ALEN;
- if (!(status = verify_area(VERIFY_WRITE, (void *) ioc->data, ioc->len))) {
- copy_to_user(ioc->data, tmp.addr, ioc->len);
+ if (copy_to_user(ioc->data, tmp.addr, ioc->len)) {
+ status = -EFAULT;
+ break;
}
- break;
case EWRK3_SET_HWADDR: /* Set the hardware address */
if (capable(CAP_NET_ADMIN)) {
- if (!(status = verify_area(VERIFY_READ, (void *) ioc->data, ETH_ALEN))) {
csr = inb(EWRK3_CSR);
csr |= (CSR_TXD | CSR_RXD);
outb(csr, EWRK3_CSR); /* Disable the TX and RX */
- copy_from_user(tmp.addr, ioc->data, ETH_ALEN);
+ if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) {
+ status = -EFAULT;
+ break;
+ }
for (i = 0; i < ETH_ALEN; i++) {
dev->dev_addr[i] = tmp.addr[i];
outb(tmp.addr[i], EWRK3_PAR0 + i);
@@ -1698,7 +1697,6 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
csr &= ~(CSR_TXD | CSR_RXD); /* Enable the TX and RX */
outb(csr, EWRK3_CSR);
- }
} else {
status = -EPERM;
}
@@ -1730,7 +1728,6 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case EWRK3_GET_MCA: /* Get the multicast address table */
- if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
while (test_and_set_bit(0, (void *) &lp->lock) != 0); /* Wait for lock to free */
if (lp->shmem_length == IO_ONLY) {
outb(0, EWRK3_IOPR);
@@ -1743,17 +1740,21 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
memcpy_fromio(tmp.addr, (char *) (lp->shmem_base + PAGE0_HTE), (HASH_TABLE_LEN >> 3));
}
ioc->len = (HASH_TABLE_LEN >> 3);
- copy_to_user(ioc->data, tmp.addr, ioc->len);
- }
+ if (copy_to_user(ioc->data, tmp.addr, ioc->len)) {
+ status = -EFAULT;
+ break;
+ }
+
lp->lock = 0; /* Unlock the page register */
break;
case EWRK3_SET_MCA: /* Set a multicast address */
if (capable(CAP_NET_ADMIN)) {
- if (!(status = verify_area(VERIFY_READ, ioc->data, ETH_ALEN * ioc->len))) {
- copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
- set_multicast_list(dev);
+ if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) {
+ status = -EFAULT;
+ break;
}
+ set_multicast_list(dev);
} else {
status = -EPERM;
}
@@ -1781,9 +1782,8 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
case EWRK3_GET_STATS: /* Get the driver statistics */
cli();
ioc->len = sizeof(lp->pktStats);
- if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
- copy_to_user(ioc->data, &lp->pktStats, ioc->len);
- }
+ if (copy_to_user(ioc->data, &lp->pktStats, ioc->len))
+ status = -EFAULT;
sti();
break;
@@ -1800,16 +1800,16 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
case EWRK3_GET_CSR: /* Get the CSR Register contents */
tmp.addr[0] = inb(EWRK3_CSR);
ioc->len = 1;
- if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
- copy_to_user(ioc->data, tmp.addr, ioc->len);
- }
+ if (copy_to_user(ioc->data, tmp.addr, ioc->len))
+ status = -EFAULT;
break;
case EWRK3_SET_CSR: /* Set the CSR Register contents */
if (capable(CAP_NET_ADMIN)) {
- if (!(status = verify_area(VERIFY_READ, ioc->data, 1))) {
- copy_from_user(tmp.addr, ioc->data, 1);
- outb(tmp.addr[0], EWRK3_CSR);
+ if (copy_from_user(tmp.addr, ioc->data, 1)) {
+ status = -EFAULT;
+ break;
}
+ outb(tmp.addr[0], EWRK3_CSR);
} else {
status = -EPERM;
}
@@ -1826,9 +1826,8 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
tmp.addr[i++] = inb(EWRK3_PAR0 + j);
}
ioc->len = EEPROM_MAX + 1 + ETH_ALEN;
- if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
- copy_to_user(ioc->data, tmp.addr, ioc->len);
- }
+ if (copy_to_user(ioc->data, tmp.addr, ioc->len))
+ status = -EFAULT;
} else {
status = -EPERM;
}
@@ -1836,11 +1835,12 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case EWRK3_SET_EEPROM: /* Set the EEPROM contents */
if (capable(CAP_NET_ADMIN)) {
- if (!(status = verify_area(VERIFY_READ, ioc->data, EEPROM_MAX))) {
- copy_from_user(tmp.addr, ioc->data, EEPROM_MAX);
- for (i = 0; i < (EEPROM_MAX >> 1); i++) {
- Write_EEPROM(tmp.val[i], iobase, i);
- }
+ if (copy_from_user(tmp.addr, ioc->data, EEPROM_MAX)) {
+ status = -EFAULT;
+ break;
+ }
+ for (i = 0; i < (EEPROM_MAX >> 1); i++) {
+ Write_EEPROM(tmp.val[i], iobase, i);
}
} else {
status = -EPERM;
@@ -1850,9 +1850,8 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
case EWRK3_GET_CMR: /* Get the CMR Register contents */
tmp.addr[0] = inb(EWRK3_CMR);
ioc->len = 1;
- if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
- copy_to_user(ioc->data, tmp.addr, ioc->len);
- }
+ if (copy_to_user(ioc->data, tmp.addr, ioc->len))
+ status = -EFAULT;
break;
case EWRK3_SET_TX_CUT_THRU: /* Set TX cut through mode */
if (suser()) {
diff --git a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c
index 749e1f123..0c51aa90b 100644
--- a/drivers/net/fmv18x.c
+++ b/drivers/net/fmv18x.c
@@ -132,8 +132,8 @@ static void set_multicast_list(struct device *dev);
struct netdev_entry fmv18x_drv =
{"fmv18x", fmv18x_probe1, FMV18X_IO_EXTENT, fmv18x_probe_list};
#else
-__initfunc(int
-fmv18x_probe(struct device *dev))
+int __init
+fmv18x_probe(struct device *dev)
{
int i;
int base_addr = dev ? dev->base_addr : 0;
@@ -163,7 +163,7 @@ fmv18x_probe(struct device *dev))
that can be done is checking a few bits and then diving right into MAC
address check. */
-__initfunc(int fmv18x_probe1(struct device *dev, short ioaddr))
+int __init fmv18x_probe1(struct device *dev, short ioaddr)
{
char irqmap[4] = {3, 7, 10, 15};
char irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 99bd59e9a..9dda3006e 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -726,7 +726,7 @@ static int sp_open_dev(struct device *dev)
#ifdef MODULE
static int sixpack_init_ctrl_dev(void)
#else /* !MODULE */
-__initfunc(int sixpack_init_ctrl_dev(struct device *dummy))
+int __init sixpack_init_ctrl_dev(struct device *dummy)
#endif /* !MODULE */
{
int status;
diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c
index bbc29e4c1..afaed1432 100644
--- a/drivers/net/hamradio/baycom_par.c
+++ b/drivers/net/hamradio/baycom_par.c
@@ -533,7 +533,7 @@ static int baycom_ioctl(struct device *dev, struct ifreq *ifr,
/* --------------------------------------------------------------------- */
-__initfunc(int baycom_par_init(void))
+int __init baycom_par_init(void)
{
int i, j, found = 0;
char set_hw = 1;
@@ -593,7 +593,7 @@ MODULE_DESCRIPTION("Baycom par96 and picpar amateur radio modem driver");
#endif
-__initfunc(int init_module(void))
+int __init init_module(void)
{
int i;
@@ -633,7 +633,7 @@ void cleanup_module(void)
* mode: par96,picpar
*/
-__initfunc(void baycom_par_setup(char *str, int *ints))
+void __init baycom_par_setup(char *str, int *ints)
{
int i;
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index 6129b4b44..216855a4c 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -605,7 +605,7 @@ static int baycom_ioctl(struct device *dev, struct ifreq *ifr,
/* --------------------------------------------------------------------- */
-__initfunc(int baycom_ser_fdx_init(void))
+int __init baycom_ser_fdx_init(void)
{
int i, j, found = 0;
char set_hw = 1;
@@ -673,7 +673,7 @@ MODULE_DESCRIPTION("Baycom ser12 full duplex amateur radio modem driver");
#endif
-__initfunc(int init_module(void))
+int __init init_module(void)
{
int i;
@@ -716,7 +716,7 @@ void cleanup_module(void)
* * indicates sofware DCD
*/
-__initfunc(void baycom_ser_fdx_setup(char *str, int *ints))
+void __init baycom_ser_fdx_setup(char *str, int *ints)
{
int i;
diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
index 088f9318e..20681a134 100644
--- a/drivers/net/hamradio/baycom_ser_hdx.c
+++ b/drivers/net/hamradio/baycom_ser_hdx.c
@@ -643,7 +643,7 @@ static int baycom_ioctl(struct device *dev, struct ifreq *ifr,
/* --------------------------------------------------------------------- */
-__initfunc(int baycom_ser_hdx_init(void))
+int __init baycom_ser_hdx_init(void)
{
int i, j, found = 0;
char set_hw = 1;
@@ -707,7 +707,7 @@ MODULE_DESCRIPTION("Baycom ser12 half duplex amateur radio modem driver");
#endif
-__initfunc(int init_module(void))
+int __init init_module(void)
{
int i;
@@ -749,7 +749,7 @@ void cleanup_module(void)
* * indicates sofware DCD
*/
-__initfunc(void baycom_ser_hdx_setup(char *str, int *ints))
+void __init baycom_ser_hdx_setup(char *str, int *ints)
{
int i;
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 4a9c60a7d..18a7bce23 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -621,7 +621,7 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
* Initialize driver. To be called from af_ax25 if not compiled as a
* module
*/
-__initfunc(int bpq_init(void))
+int __init bpq_init(void)
{
struct device *dev;
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index ac474d0b9..2d3935117 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -336,7 +336,7 @@ void cleanup_module(void)
#else
-__initfunc(void dmascc_setup(char *str, int *ints))
+void __init dmascc_setup(char *str, int *ints)
{
int i;
@@ -350,7 +350,7 @@ __initfunc(void dmascc_setup(char *str, int *ints))
/* Initialization functions */
-__initfunc(int dmascc_init(void))
+int __init dmascc_init(void)
{
int h, i, j, n;
int base[MAX_NUM_DEVS], tcmd[MAX_NUM_DEVS], t0[MAX_NUM_DEVS],
@@ -453,8 +453,7 @@ __initfunc(int dmascc_init(void))
return -EIO;
}
-
-__initfunc(int setup_adapter(int io, int h, int n))
+int __init setup_adapter(int io, int h, int n)
{
int i, irq, chip;
struct scc_info *info;
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index b2358447d..9558b9763 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -43,7 +43,6 @@
#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/net.h>
#include <linux/in.h>
@@ -936,7 +935,7 @@ MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder");
/* --------------------------------------------------------------------- */
-__initfunc(int init_module(void))
+int __init init_module(void)
{
printk(KERN_INFO "hdlcdrv: (C) 1996 Thomas Sailer HB9JNX/AE4WA\n");
printk(KERN_INFO "hdlcdrv: version 0.6 compiled " __TIME__ " " __DATE__ "\n");
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index ab1ecab6a..796b019e4 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -937,7 +937,7 @@ static int ax_open_dev(struct device *dev)
}
/* Initialize AX25 control device -- register AX25 line discipline */
-__initfunc(int mkiss_init_ctrl_dev(void))
+int __init mkiss_init_ctrl_dev(void)
{
int status;
@@ -1154,7 +1154,7 @@ static void mkiss_set_termios(struct tty_struct *tty, struct termios *old_termio
/* * Init MKISS driver * */
/* ******************************************************************** */
-__initfunc(static int mkiss_init(void))
+static int __init mkiss_init(void)
{
memset(&mkiss_driver, 0, sizeof(struct tty_driver));
diff --git a/drivers/net/hamradio/pi2.c b/drivers/net/hamradio/pi2.c
index 8de325175..f036c5eb8 100644
--- a/drivers/net/hamradio/pi2.c
+++ b/drivers/net/hamradio/pi2.c
@@ -927,7 +927,7 @@ static void b_exint(struct pi_local *lp)
/* Probe for a PI card. */
/* This routine also initializes the timer chip */
-__initfunc(static int hw_probe(int ioaddr))
+static int __init hw_probe(int ioaddr)
{
int time = 1000; /* Number of milliseconds for test */
unsigned long start_time, end_time;
@@ -1182,7 +1182,7 @@ static void chipset_init(struct device *dev)
}
-__initfunc(int pi_init(void))
+int __init pi_init(void)
{
int *port;
int ioaddr = 0;
diff --git a/drivers/net/hamradio/pt.c b/drivers/net/hamradio/pt.c
index 86ed83d3b..4a7604e96 100644
--- a/drivers/net/hamradio/pt.c
+++ b/drivers/net/hamradio/pt.c
@@ -474,8 +474,7 @@ static void chipset_init(struct device *dev)
} /* chipset_init() */
-
-__initfunc(int pt_init(void))
+int __init pt_init(void)
{
int *port;
int ioaddr = 0;
@@ -537,7 +536,7 @@ __initfunc(int pt_init(void))
/*
* Probe for PT card. Also initialises the timers
*/
-__initfunc(static int hw_probe(int ioaddr))
+static int __init hw_probe(int ioaddr)
{
int time = 1000; /* Number of milliseconds to test */
int a = 1;
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 48ef86a9b..0f803139a 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -2193,7 +2193,7 @@ struct proc_dir_entry scc_proc_dir_entry =
/* * Init SCC driver * */
/* ******************************************************************** */
-__initfunc(int scc_init (void))
+int __init scc_init (void)
{
int chip, chan, k, result;
char devname[10];
diff --git a/drivers/net/hamradio/soundmodem/sm.c b/drivers/net/hamradio/soundmodem/sm.c
index 15b5239fd..193ffeae2 100644
--- a/drivers/net/hamradio/soundmodem/sm.c
+++ b/drivers/net/hamradio/soundmodem/sm.c
@@ -640,9 +640,9 @@ static int sm_ioctl(struct device *dev, struct ifreq *ifr,
/* --------------------------------------------------------------------- */
#ifdef MODULE
-__initfunc(static int sm_init(void))
+static int __init sm_init(void)
#else /* MODULE */
-__initfunc(int sm_init(void))
+int __init sm_init(void)
#endif /* MODULE */
{
int i, j, found = 0;
@@ -724,7 +724,7 @@ MODULE_DESCRIPTION("Soundcard amateur radio modem driver");
#endif
-__initfunc(int init_module(void))
+int __init init_module(void)
{
if (mode) {
if (iobase == -1)
@@ -778,7 +778,7 @@ void cleanup_module(void)
* modem: afsk1200, fsk9600
*/
-__initfunc(void sm_setup(char *str, int *ints))
+void __init sm_setup(char *str, int *ints)
{
int i;
diff --git a/drivers/net/hamradio/soundmodem/sm.h b/drivers/net/hamradio/soundmodem/sm.h
index 66e8f936c..68799e20e 100644
--- a/drivers/net/hamradio/soundmodem/sm.h
+++ b/drivers/net/hamradio/soundmodem/sm.h
@@ -296,8 +296,6 @@ extern inline unsigned int lcm(unsigned int x, unsigned int y)
#ifdef __i386__
-#include <asm/processor.h>
-
#define HAS_RDTSC (current_cpu_data.x86_capability & X86_FEATURE_TSC)
/*
diff --git a/drivers/net/hostess_sv11.c b/drivers/net/hostess_sv11.c
index fe20840a4..d4f0dec2d 100644
--- a/drivers/net/hostess_sv11.c
+++ b/drivers/net/hostess_sv11.c
@@ -389,7 +389,8 @@ static void sv11_shutdown(struct sv11_device *dev)
free_irq(dev->sync.irq, dev);
if(dma)
{
- free_dma(dev->sync.chanA.rxdma);
+ if(dma==1)
+ free_dma(dev->sync.chanA.rxdma);
free_dma(dev->sync.chanA.txdma);
}
release_region(dev->sync.chanA.ctrlio-1, 8);
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index bcb76242a..b58ba73fc 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -123,7 +123,7 @@ struct netdev_entry hpplus_drv =
{"hpplus", hpp_probe1, HP_IO_EXTENT, hpplus_portlist};
#else
-__initfunc(int hp_plus_probe(struct device *dev))
+int __init hp_plus_probe(struct device *dev)
{
int i;
int base_addr = dev ? dev->base_addr : 0;
@@ -146,7 +146,7 @@ __initfunc(int hp_plus_probe(struct device *dev))
#endif
/* Do the interesting part of the probe at a single address. */
-__initfunc(int hpp_probe1(struct device *dev, int ioaddr))
+int __init hpp_probe1(struct device *dev, int ioaddr)
{
int i;
unsigned char checksum = 0;
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index 8963b5562..c031cd87f 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -84,7 +84,7 @@ struct netdev_entry netcard_drv =
{"hp", hp_probe1, HP_IO_EXTENT, hppclan_portlist};
#else
-__initfunc(int hp_probe(struct device *dev))
+int __init hp_probe(struct device *dev)
{
int i;
int base_addr = dev ? dev->base_addr : 0;
@@ -106,7 +106,7 @@ __initfunc(int hp_probe(struct device *dev))
}
#endif
-__initfunc(int hp_probe1(struct device *dev, int ioaddr))
+int __init hp_probe1(struct device *dev, int ioaddr)
{
int i, board_id, wordmode;
const char *name;
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index 5ac9da0a3..8535a4955 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -106,6 +106,7 @@
#include <linux/types.h>
#include <linux/config.h> /* for CONFIG_PCI */
#include <linux/delay.h>
+#include <linux/init.h>
#if LINUX_VERSION_CODE >= 0x020100
#define LINUX_2_1
@@ -347,7 +348,7 @@ static void wait( void )
* since this could cause problems when the card is not installed.
*/
-__initfunc(int hp100_probe( struct device *dev ))
+int __init hp100_probe( struct device *dev )
{
int base_addr = dev ? dev -> base_addr : 0;
int ioaddr = 0;
@@ -524,9 +525,9 @@ __initfunc(int hp100_probe( struct device *dev ))
#ifdef LINUX_2_1
-__initfunc(static int hp100_probe1( struct device *dev, int ioaddr, u_char bus, struct pci_dev *pci_dev ))
+static int __init hp100_probe1( struct device *dev, int ioaddr, u_char bus, struct pci_dev *pci_dev )
#else
-__initfunc(static int hp100_probe1( struct device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn ))
+static int __init hp100_probe1( struct device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn )
#endif
{
int i;
diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c
index fb7f61729..b8249f1f9 100644
--- a/drivers/net/hplance.c
+++ b/drivers/net/hplance.c
@@ -67,7 +67,7 @@ static struct hplance_private *root_hplance_dev = NULL;
#endif
/* Find all the HP Lance boards and initialise them... */
-__initfunc(int hplance_probe(struct device *dev))
+int __init hplance_probe(struct device *dev)
{
int cards = 0, called = 0;
@@ -98,7 +98,7 @@ __initfunc(int hplance_probe(struct device *dev))
}
/* Initialise a single lance board at the given select code */
-__initfunc (static int hplance_init(struct device *dev, int scode))
+static int __init hplance_init(struct device *dev, int scode)
{
/* const char *name = dio_scodetoname(scode); */
static const char name[] = "HP LANCE";
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c
index 00549b6b9..5ced788bb 100644
--- a/drivers/net/hydra.c
+++ b/drivers/net/hydra.c
@@ -157,7 +157,7 @@ static void memcpyw(u16 *dest, u16 *src, int len)
#endif
-__initfunc(int hydra_probe(struct device *dev))
+int __init hydra_probe(struct device *dev)
{
struct hydra_private *priv;
u32 board;
diff --git a/drivers/net/ibmtr.c b/drivers/net/ibmtr.c
index 29356bbbf..947f8c75c 100644
--- a/drivers/net/ibmtr.c
+++ b/drivers/net/ibmtr.c
@@ -138,11 +138,9 @@ static char mcchannelid[] = {
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
-#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/in.h>
#include <linux/ioport.h>
-#include <linux/errno.h>
#include <linux/string.h>
#include <linux/skbuff.h>
#include <linux/interrupt.h>
@@ -173,7 +171,7 @@ const char *channel_def[] __initdata = {
"ISA", "MCA", "ISA P&P"
};
-__initfunc(char *adapter_def(char type))
+char __init *adapter_def(char type)
{
switch (type)
{
@@ -223,7 +221,7 @@ static unsigned int ibmtr_portlist[] __initdata = {
static __u32 ibmtr_mem_base = 0xd0000;
-__initfunc(static void PrtChanID(char *pcid, short stride) )
+static void __init PrtChanID(char *pcid, short stride)
{
short i, j;
for (i=0, j=0; i<24; i++, j+=stride)
@@ -231,7 +229,7 @@ __initfunc(static void PrtChanID(char *pcid, short stride) )
printk("\n");
}
-__initfunc(static void HWPrtChanID (__u32 pcid, short stride))
+static void __init HWPrtChanID (__u32 pcid, short stride)
{
short i, j;
for (i=0, j=0; i<24; i++, j+=stride)
@@ -252,7 +250,7 @@ __initfunc(static void HWPrtChanID (__u32 pcid, short stride))
* which references it.
*/
-__initfunc(int ibmtr_probe(struct device *dev))
+int __init ibmtr_probe(struct device *dev)
{
int i;
int base_addr = dev ? dev->base_addr : 0;
@@ -295,7 +293,7 @@ __initfunc(int ibmtr_probe(struct device *dev))
return -ENODEV;
}
-__initfunc(static int ibmtr_probe1(struct device *dev, int PIOaddr))
+static int __init ibmtr_probe1(struct device *dev, int PIOaddr)
{
unsigned char segment=0, intr=0, irq=0, i=0, j=0, cardpresent=NOTOK,temp=0;
__u32 t_mmio=0;
@@ -750,7 +748,7 @@ __initfunc(static int ibmtr_probe1(struct device *dev, int PIOaddr))
/* query the adapter for the size of shared RAM */
-__initfunc(static unsigned char get_sram_size(struct tok_info *adapt_info))
+static unsigned char __init get_sram_size(struct tok_info *adapt_info)
{
unsigned char avail_sram_code;
@@ -769,7 +767,7 @@ __initfunc(static unsigned char get_sram_size(struct tok_info *adapt_info))
return 1<<((readb(adapt_info->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD)>>2)+4);
}
-__initfunc(static int trdev_init(struct device *dev))
+static int __init trdev_init(struct device *dev)
{
struct tok_info *ti=(struct tok_info *)dev->priv;
diff --git a/drivers/net/irda/actisys.c b/drivers/net/irda/actisys.c
index 8e86770a1..46634c42e 100644
--- a/drivers/net/irda/actisys.c
+++ b/drivers/net/irda/actisys.c
@@ -61,7 +61,7 @@ static struct dongle dongle_plus = {
actisys_init_qos,
};
-__initfunc(int actisys_init(void))
+int __init actisys_init(void)
{
int ret;
diff --git a/drivers/net/irda/esi.c b/drivers/net/irda/esi.c
index b1f47b775..930abe63e 100644
--- a/drivers/net/irda/esi.c
+++ b/drivers/net/irda/esi.c
@@ -52,7 +52,7 @@ static struct dongle dongle = {
esi_qos_init,
};
-__initfunc(int esi_init(void))
+int __init esi_init(void)
{
return irda_device_register_dongle(&dongle);
}
diff --git a/drivers/net/irda/girbil.c b/drivers/net/irda/girbil.c
index 938315bc5..a3d28dedb 100644
--- a/drivers/net/irda/girbil.c
+++ b/drivers/net/irda/girbil.c
@@ -76,7 +76,7 @@ static struct dongle dongle = {
girbil_init_qos,
};
-__initfunc(int girbil_init(void))
+int __init girbil_init(void)
{
return irda_device_register_dongle(&dongle);
}
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index e813fe8a4..096027b8f 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -86,7 +86,7 @@ static int irport_is_receiving(struct irda_device *idev);
static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts);
static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len);
-__initfunc(int irport_init(void))
+int __init irport_init(void)
{
int i;
diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c
index 751d98ec7..e9e0bb6d5 100644
--- a/drivers/net/irda/irtty.c
+++ b/drivers/net/irda/irtty.c
@@ -64,7 +64,7 @@ static void irtty_receive_buf(struct tty_struct *, const unsigned char *,
char *, int);
char *driver_name = "irtty";
-__initfunc(int irtty_init(void))
+int __init irtty_init(void)
{
int status;
diff --git a/drivers/net/irda/litelink.c b/drivers/net/irda/litelink.c
index 84df367da..4758914dd 100644
--- a/drivers/net/irda/litelink.c
+++ b/drivers/net/irda/litelink.c
@@ -60,7 +60,7 @@ static struct dongle dongle = {
litelink_init_qos,
};
-__initfunc(int litelink_init(void))
+int __init litelink_init(void)
{
return irda_device_register_dongle(&dongle);
}
diff --git a/drivers/net/irda/pc87108.c b/drivers/net/irda/pc87108.c
index 9433ec6b5..32220bf43 100644
--- a/drivers/net/irda/pc87108.c
+++ b/drivers/net/irda/pc87108.c
@@ -127,7 +127,7 @@ static int pc87108_net_close(struct device *dev);
* Initialize chip. Just try to find out how many chips we are dealing with
* and where they are
*/
-__initfunc(int pc87108_init(void))
+int __init pc87108_init(void)
{
int i;
diff --git a/drivers/net/irda/smc-ircc.c b/drivers/net/irda/smc-ircc.c
index 4daa5f7e2..d1e7de8d5 100644
--- a/drivers/net/irda/smc-ircc.c
+++ b/drivers/net/irda/smc-ircc.c
@@ -33,8 +33,6 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/malloc.h>
-#include <linux/delay.h>
-#include <linux/init.h>
#include <linux/init.h>
#include <asm/io.h>
@@ -102,7 +100,7 @@ static inline void serial_out(int port, int offset, int value)
* Initialize chip. Just try to find out how many chips we are dealing with
* and where they are
*/
-__initfunc(int ircc_init(void))
+int __init ircc_init(void)
{
int i;
diff --git a/drivers/net/irda/tekram.c b/drivers/net/irda/tekram.c
index 123e2bd28..c47cf68d7 100644
--- a/drivers/net/irda/tekram.c
+++ b/drivers/net/irda/tekram.c
@@ -56,7 +56,7 @@ static struct dongle dongle = {
tekram_init_qos,
};
-__initfunc(int tekram_init(void))
+int __init tekram_init(void)
{
return irda_device_register_dongle(&dongle);
}
diff --git a/drivers/net/irda/toshoboe.c b/drivers/net/irda/toshoboe.c
index c7ef984ea..0986211f1 100644
--- a/drivers/net/irda/toshoboe.c
+++ b/drivers/net/irda/toshoboe.c
@@ -568,11 +568,11 @@ toshoboe_net_open (struct device *dev)
self->rxs = inb_p (OBOE_RCVT);
self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET;
-#ifdef 0
+#if 0
self->rxs = 0;
self->txs = 0;
#endif
-#ifdef 0
+#if 0
self->rxs = RX_SLOTS - 1;
self->txs = 0;
#endif
@@ -838,7 +838,7 @@ toshoboe_open (struct pci_dev *pci_dev)
return (0);
}
-__initfunc (int toshoboe_init (void))
+int __init toshoboe_init (void)
{
struct pci_dev *pci_dev = NULL;
int found = 0;
diff --git a/drivers/net/irda/uircc.c b/drivers/net/irda/uircc.c
index d9e1e107f..d5eba5fe2 100644
--- a/drivers/net/irda/uircc.c
+++ b/drivers/net/irda/uircc.c
@@ -36,8 +36,6 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/malloc.h>
-#include <linux/delay.h>
-#include <linux/init.h>
#include <linux/init.h>
#include <asm/io.h>
@@ -90,7 +88,7 @@ static int uircc_net_close(struct device *dev);
* Initialize chip. Just try to find out how many chips we are dealing with
* and where they are
*/
-__initfunc(int uircc_init(void))
+int __init uircc_init(void)
{
int i;
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 029d6de51..292b97a3a 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -105,7 +105,7 @@ static int w83977af_net_close(struct device *dev);
* Initialize chip. Just try to find out how many chips we are dealing with
* and where they are
*/
-__initfunc(int w83977af_init(void))
+int __init w83977af_init(void)
{
int i;
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 659983655..9054744fc 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -420,7 +420,7 @@ int lance_probe(struct device *dev)
return -ENODEV;
}
-__initfunc(int lance_probe1(struct device *dev, int ioaddr, int irq, int options))
+int __init lance_probe1(struct device *dev, int ioaddr, int irq, int options)
{
struct lance_private *lp;
short dma_channels; /* Mark spuriously-busy DMA channels */
@@ -499,6 +499,8 @@ __initfunc(int lance_probe1(struct device *dev, int ioaddr, int irq, int options
lp = (struct lance_private *)(((unsigned long)kmalloc(sizeof(*lp)+7,
GFP_DMA | GFP_KERNEL)+7) & ~7);
+ if(lp==NULL)
+ return -ENODEV;
if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp);
memset(lp, 0, sizeof(*lp));
dev->priv = lp;
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index 1fa60e04d..b61d45e67 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -100,7 +100,7 @@ static unsigned int shmem_mapB[] __initdata = {0xff, 0xfe, 0x0e, 0xfff, 0xffe, 0
* PROM for a match against the value assigned to Mylex.
*/
-__initfunc(int lne390_probe(struct device *dev))
+int __init lne390_probe(struct device *dev)
{
unsigned short ioaddr = dev->base_addr;
@@ -127,7 +127,7 @@ __initfunc(int lne390_probe(struct device *dev))
return ENODEV;
}
-__initfunc(int lne390_probe1(struct device *dev, int ioaddr))
+int __init lne390_probe1(struct device *dev, int ioaddr)
{
int i, revision;
unsigned long eisa_id;
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index b2aa9b27b..2f4089577 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -114,7 +114,7 @@ static int loopback_open(struct device *dev)
}
/* Initialize the rest of the LOOPBACK device. */
-__initfunc(int loopback_init(struct device *dev))
+int __init loopback_init(struct device *dev)
{
dev->mtu = LOOPBACK_MTU;
dev->tbusy = 0;
diff --git a/drivers/net/ltpc.c b/drivers/net/ltpc.c
index 1ffe0f368..6c3740585 100644
--- a/drivers/net/ltpc.c
+++ b/drivers/net/ltpc.c
@@ -1018,7 +1018,7 @@ static struct net_device_stats *ltpc_get_stats(struct device *dev)
/* initialization stuff */
-__initfunc(int ltpc_probe_dma(int base))
+int __init ltpc_probe_dma(int base)
{
int dma = 0;
int timeout;
@@ -1088,7 +1088,7 @@ __initfunc(int ltpc_probe_dma(int base))
return dma;
}
-__initfunc(int ltpc_probe(struct device *dev))
+int __init ltpc_probe(struct device *dev)
{
int err;
int x=0,y=0;
@@ -1250,7 +1250,7 @@ __initfunc(int ltpc_probe(struct device *dev))
}
/* handles "ltpc=io,irq,dma" kernel command lines */
-__initfunc(void ltpc_setup(char *str, int *ints))
+void __init ltpc_setup(char *str, int *ints)
{
if (ints[0] == 0) {
if (str && !strncmp(str, "auto", 4)) {
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 6772139ac..58c11d17b 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -1074,7 +1074,7 @@ static inline int myri_ether_init(struct device *dev, struct linux_sbus_device *
return 0;
}
-__initfunc(int myri_sbus_probe(struct device *dev))
+int __init myri_sbus_probe(struct device *dev)
{
struct linux_sbus *bus;
struct linux_sbus_device *sdev = 0;
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 9bbf753c5..36a841c08 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -177,7 +177,7 @@ struct netdev_entry netcard_drv =
* the card.
*/
-__initfunc(int ne_probe(struct device *dev))
+int __init ne_probe(struct device *dev)
{
int base_addr = dev ? dev->base_addr : 0;
@@ -209,7 +209,7 @@ __initfunc(int ne_probe(struct device *dev))
#endif
#ifdef CONFIG_PCI
-__initfunc(static int ne_probe_pci(struct device *dev))
+static int __init ne_probe_pci(struct device *dev)
{
int i;
@@ -243,7 +243,7 @@ __initfunc(static int ne_probe_pci(struct device *dev))
}
#endif /* CONFIG_PCI */
-__initfunc(static int ne_probe1(struct device *dev, int ioaddr))
+static int __init ne_probe1(struct device *dev, int ioaddr)
{
int i;
unsigned char SA_prom[32];
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
index 3fabee261..6decb8100 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ne2.c
@@ -146,7 +146,7 @@ static void ne_block_output(struct device *dev, const int count,
* Note that at boot, this probe only picks up one card at a time.
*/
-__initfunc (int ne2_probe(struct device *dev))
+int __init ne2_probe(struct device *dev)
{
static int current_mca_slot = -1;
int i;
@@ -198,8 +198,7 @@ static int ne2_procinfo(char *buf, int slot, struct device *dev)
return len;
}
-
-__initfunc (static int ne2_probe1(struct device *dev, int slot))
+static int __init ne2_probe1(struct device *dev, int slot)
{
int i, base_addr, irq;
unsigned char POS;
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index 1b48abd36..cd809d562 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -24,11 +24,8 @@
/* Our copyright info must remain in the binary. */
static const char *version =
-"ne2k-pci.c:v0.99L 2/7/98 D. Becker/P. Gortmaker http://cesdis.gsfc.nasa.gov/linux/drivers/ne2k-pci.html\n";
+"ne2k-pci.c:vpre-1.00e 5/27/99 D. Becker/P. Gortmaker http://cesdis.gsfc.nasa.gov/linux/drivers/ne2k-pci.html\n";
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -44,6 +41,13 @@ static const char *version =
#include <linux/etherdevice.h>
#include "8390.h"
+#if defined(__powerpc__)
+#define inl_le(addr) le32_to_cpu(inl(addr))
+#define inw_le(addr) le16_to_cpu(inw(addr))
+#define insl insl_ns
+#define outsl outsl_ns
+#endif
+
/* Set statically or when loading the driver module. */
static int debug = 1;
@@ -58,19 +62,34 @@ static int debug = 1;
/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
/* #define PACKETBUF_MEMSIZE 0x40 */
+#define ne2k_flags reg0 /* Rename an existing field to store flags! */
+
+/* Only the low 8 bits are usable for non-init-time flags! */
+enum {
+ HOLTEK_FDX=1, /* Full duplex -> set 0x80 at offset 0x20. */
+ ONLY_16BIT_IO=2, ONLY_32BIT_IO=4, /* Chip can do only 16/32-bit xfers. */
+ STOP_PG_0x60=0x100,
+};
+
+/* This will eventually be converted to the standard PCI probe table. */
+
static struct {
unsigned short vendor, dev_id;
char *name;
+ int flags;
}
pci_clone_list[] __initdata = {
- {0x10ec, 0x8029, "RealTek RTL-8029"},
- {0x1050, 0x0940, "Winbond 89C940"},
- {0x11f6, 0x1401, "Compex RL2000"},
- {0x8e2e, 0x3000, "KTI ET32P2"},
- {0x4a14, 0x5000, "NetVin NV5000SC"},
- {0x1106, 0x0926, "Via 82C926"},
- {0x10bd, 0x0e34, "SureCom NE34"},
- {0x1050, 0x5a5a, "Winbond"},
+ {0x10ec, 0x8029, "RealTek RTL-8029", 0},
+ {0x1050, 0x0940, "Winbond 89C940", 0},
+ {0x11f6, 0x1401, "Compex RL2000", 0},
+ {0x8e2e, 0x3000, "KTI ET32P2", 0},
+ {0x4a14, 0x5000, "NetVin NV5000SC", 0},
+ {0x1106, 0x0926, "Via 86C926", ONLY_16BIT_IO},
+ {0x10bd, 0x0e34, "SureCom NE34", 0},
+ {0x1050, 0x5a5a, "Winbond", 0},
+ {0x12c3, 0x0058, "Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX},
+ {0x12c3, 0x5598, "Holtek HT80229",
+ ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 },
{0,}
};
@@ -86,7 +105,8 @@ pci_clone_list[] __initdata = {
#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
int ne2k_pci_probe(struct device *dev);
-static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq);
+static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq,
+ int chip_idx);
static int ne2k_pci_open(struct device *dev);
static int ne2k_pci_close(struct device *dev);
@@ -115,17 +135,13 @@ static struct ne2k_pci_card *ne2k_card_list = NULL;
int
init_module(void)
{
- int retval;
-
/* We must emit version information. */
if (debug)
printk(KERN_INFO "%s", version);
- retval = ne2k_pci_probe(0);
-
- if (retval) {
- printk(KERN_NOTICE "ne2k-pci.c: no (useable) cards found, driver NOT installed.\n");
- return retval;
+ if (ne2k_pci_probe(0)) {
+ printk(KERN_NOTICE "ne2k-pci.c: No useable cards found, driver NOT installed.\n");
+ return -ENODEV;
}
lock_8390_module();
return 0;
@@ -170,7 +186,7 @@ struct netdev_entry netcard_drv =
{"ne2k_pci", ne2k_pci_probe1, NE_IO_EXTENT, 0};
#endif
-__initfunc (int ne2k_pci_probe(struct device *dev))
+int __init ne2k_pci_probe(struct device *dev)
{
struct pci_dev *pdev = NULL;
int cards_found = 0;
@@ -225,7 +241,7 @@ __initfunc (int ne2k_pci_probe(struct device *dev))
printk("ne2k-pci.c: PCI NE2000 clone '%s' at I/O %#x, IRQ %d.\n",
pci_clone_list[i].name, pci_ioaddr, pci_irq_line);
- dev = ne2k_pci_probe1(dev, pci_ioaddr, pci_irq_line);
+ dev = ne2k_pci_probe1(dev, pci_ioaddr, pci_irq_line, i);
if (dev == 0) {
/* Should not happen. */
printk(KERN_ERR "ne2k-pci: Probe of PCI card at %#x failed.\n",
@@ -247,11 +263,10 @@ __initfunc (int ne2k_pci_probe(struct device *dev))
return cards_found ? 0 : -ENODEV;
}
-__initfunc (static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq))
+static struct device __init *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq, int chip_idx)
{
int i;
unsigned char SA_prom[32];
- const char *name = NULL;
int start_page, stop_page;
int reg0 = inb(ioaddr);
@@ -273,6 +288,8 @@ __initfunc (static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr
}
}
+ dev = init_etherdev(dev, 0);
+
/* Reset card. Who knows what dain-bramaged state it was left in. */
{
unsigned long reset_start_time = jiffies;
@@ -321,59 +338,47 @@ __initfunc (static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr
}
-#ifdef notdef
- /* Some broken PCI cards don't respect the byte-wide
- request in program_seq above, and hence don't have doubled up values.
- */
- for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
- SA_prom[i] = inb(ioaddr + NE_DATAPORT);
- SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
- if (SA_prom[i] != SA_prom[i+1])
- sa_prom_doubled = 0;
- }
-
- if (sa_prom_doubled)
- for (i = 0; i < 16; i++)
- SA_prom[i] = SA_prom[i+i];
-#else
- for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++)
- SA_prom[i] = inb(ioaddr + NE_DATAPORT);
+ /* Note: all PCI cards have at least 16 bit access, so we don't have
+ to check for 8 bit cards. Most cards permit 32 bit access. */
-#endif
+ if (pci_clone_list[chip_idx].flags & ONLY_32BIT_IO) {
+ for (i = 0; i < 4 ; i++)
+ ((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT));
+ } else
+ for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++)
+ SA_prom[i] = inb(ioaddr + NE_DATAPORT);
/* We always set the 8390 registers for word mode. */
outb(0x49, ioaddr + EN0_DCFG);
start_page = NESM_START_PG;
- stop_page = NESM_STOP_PG;
-
- /* Set up the rest of the parameters. */
- name = "PCI NE2000";
- dev = init_etherdev(dev, 0);
+ stop_page =
+ pci_clone_list[chip_idx].flags&STOP_PG_0x60 ? 0x60 : NESM_STOP_PG;
+ /* Set up the rest of the parameters. */
dev->irq = irq;
dev->base_addr = ioaddr;
/* Allocate dev->priv and fill in 8390 specific dev fields. */
if (ethdev_init(dev)) {
printk ("%s: unable to get memory for dev->priv.\n", dev->name);
- kfree(dev);
return 0;
}
request_region(ioaddr, NE_IO_EXTENT, dev->name);
printk("%s: %s found at %#x, IRQ %d, ",
- dev->name, name, ioaddr, dev->irq);
+ dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq);
for(i = 0; i < 6; i++) {
printk("%2.2X%s", SA_prom[i], i == 5 ? ".\n": ":");
dev->dev_addr[i] = SA_prom[i];
}
- ei_status.name = name;
+ ei_status.name = pci_clone_list[chip_idx].name;
ei_status.tx_start_page = start_page;
ei_status.stop_page = stop_page;
ei_status.word16 = 1;
+ ei_status.ne2k_flags = pci_clone_list[chip_idx].flags;
ei_status.rx_start_page = start_page + TX_PAGES;
#ifdef PACKETBUF_MEMSIZE
@@ -447,9 +452,9 @@ ne2k_pci_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_pa
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr "
- "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
+ "[DMAstat:%d][irqlock:%d][intr:%d].\n",
dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
+ (int)dev->interrupt);
return;
}
@@ -461,11 +466,12 @@ ne2k_pci_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_pa
outb(ring_page, nic_base + EN0_RSARHI);
outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-#if defined(USE_LONGIO)
- *(u32*)hdr = inl(NE_BASE + NE_DATAPORT);
-#else
- insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
-#endif
+ if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+ insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+ } else {
+ *(u32*)hdr = le32_to_cpu(inl(NE_BASE + NE_DATAPORT));
+ le16_to_cpus(&hdr->count);
+ }
outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
ei_status.dmaing &= ~0x01;
@@ -485,12 +491,14 @@ ne2k_pci_block_input(struct device *dev, int count, struct sk_buff *skb, int rin
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
printk("%s: DMAing conflict in ne2k_pci_block_input "
- "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
+ "[DMAstat:%d][irqlock:%d][intr:%d].\n",
dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
+ (int)dev->interrupt);
return;
}
ei_status.dmaing |= 0x01;
+ if (ei_status.ne2k_flags & ONLY_32BIT_IO)
+ count = (count + 3) & 0xFFFC;
outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
outb(count & 0xff, nic_base + EN0_RCNTLO);
outb(count >> 8, nic_base + EN0_RCNTHI);
@@ -498,21 +506,21 @@ ne2k_pci_block_input(struct device *dev, int count, struct sk_buff *skb, int rin
outb(ring_offset >> 8, nic_base + EN0_RSARHI);
outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-#if defined(USE_LONGIO)
- insl(NE_BASE + NE_DATAPORT, buf, count>>2);
- if (count & 3) {
- buf += count & ~3;
- if (count & 2)
- *((u16*)buf)++ = inw(NE_BASE + NE_DATAPORT);
- if (count & 1)
- *buf = inb(NE_BASE + NE_DATAPORT);
- }
-#else
- insw(NE_BASE + NE_DATAPORT,buf,count>>1);
- if (count & 0x01) {
- buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+ if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+ insw(NE_BASE + NE_DATAPORT,buf,count>>1);
+ if (count & 0x01) {
+ buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+ }
+ } else {
+ insl(NE_BASE + NE_DATAPORT, buf, count>>2);
+ if (count & 3) {
+ buf += count & ~3;
+ if (count & 2)
+ *((u16*)buf)++ = le16_to_cpu(inw(NE_BASE + NE_DATAPORT));
+ if (count & 1)
+ *buf = inb(NE_BASE + NE_DATAPORT);
+ }
}
-#endif
outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
ei_status.dmaing &= ~0x01;
@@ -527,15 +535,18 @@ ne2k_pci_block_output(struct device *dev, int count,
/* On little-endian it's always safe to round the count up for
word writes. */
- if (count & 0x01)
- count++;
+ if (ei_status.ne2k_flags & ONLY_32BIT_IO)
+ count = (count + 3) & 0xFFFC;
+ else
+ if (count & 0x01)
+ count++;
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
printk("%s: DMAing conflict in ne2k_pci_block_output."
- "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
+ "[DMAstat:%d][irqlock:%d][intr:%d]\n",
dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
+ (int)dev->interrupt);
return;
}
ei_status.dmaing |= 0x01;
@@ -561,16 +572,16 @@ ne2k_pci_block_output(struct device *dev, int count,
outb(0x00, nic_base + EN0_RSARLO);
outb(start_page, nic_base + EN0_RSARHI);
outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
-#if defined(USE_LONGIO)
- outsl(NE_BASE + NE_DATAPORT, buf, count>>2);
- if (count & 3) {
- buf += count & ~3;
- if (count & 2)
- outw(*((u16*)buf)++, NE_BASE + NE_DATAPORT);
+ if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+ outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
+ } else {
+ outsl(NE_BASE + NE_DATAPORT, buf, count>>2);
+ if (count & 3) {
+ buf += count & ~3;
+ if (count & 2)
+ outw(cpu_to_le16(*((u16*)buf)++), NE_BASE + NE_DATAPORT);
+ }
}
-#else
- outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
-#endif
dma_start = jiffies;
diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c
index eb3098095..51d11cb0c 100644
--- a/drivers/net/ne3210.c
+++ b/drivers/net/ne3210.c
@@ -95,7 +95,7 @@ static unsigned int shmem_map[] __initdata = {0xff0, 0xfe0, 0xfff0, 0xd8, 0xffe0
* PROM for a match against the value assigned to Novell.
*/
-__initfunc(int ne3210_probe(struct device *dev))
+int __init ne3210_probe(struct device *dev)
{
unsigned short ioaddr = dev->base_addr;
@@ -122,7 +122,7 @@ __initfunc(int ne3210_probe(struct device *dev))
return ENODEV;
}
-__initfunc(int ne3210_probe1(struct device *dev, int ioaddr))
+int __init ne3210_probe1(struct device *dev, int ioaddr)
{
int i;
unsigned long eisa_id;
diff --git a/drivers/net/olympic.c b/drivers/net/olympic.c
new file mode 100644
index 000000000..07ae7b91c
--- /dev/null
+++ b/drivers/net/olympic.c
@@ -0,0 +1,1663 @@
+/*
+ * olympic.c (c) 1999 Peter De Schrijver All Rights Reserved
+ * 1999 Mike Phillips (phillim@amtrak.com)
+ *
+ * Linux driver for IBM PCI tokenring cards based on the Pit/Pit-Phy/Olympic
+ * chipset.
+ *
+ * Base Driver Skeleton:
+ * Written 1993-94 by Donald Becker.
+ *
+ * Copyright 1993 United States Government as represented by the
+ * Director, National Security Agency.
+ *
+ * Thanks to Erik De Cock, Adrian Bridgett and Frank Fiene for their
+ * assistance and perserverance with the testing of this driver.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ *
+ * 4/27/99 - Alpha Release 0.1.0
+ * First release to the public
+ *
+ * 6/8/99 - Official Release 0.2.0
+ * Merged into the kernel code
+ *
+ * To Do:
+ *
+ * Sanitize for smp
+ *
+ * If Problems do Occur
+ * Most problems can be rectified by either closing and opening the interface
+ * (ifconfig down and up) or rmmod and insmod'ing the driver (a bit difficult
+ * if compiled into the kernel).
+ */
+
+/* Change OLYMPIC_DEBUG to 1 to get verbose, and I mean really verbose, messages */
+
+#define OLYMPIC_DEBUG 0
+
+/* Change OLYMPIC_NETWORK_MONITOR to receive mac frames through the arb channel.
+ * Will also create a /proc/net/olympic_tr entry if proc_fs is compiled into the
+ * kernel.
+ * Intended to be used to create a ring-error reporting network module
+ * i.e. it will give you the source address of beaconers on the ring
+ */
+
+#define OLYMPIC_NETWORK_MONITOR 0
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+#include <linux/ptrace.h>
+#include <linux/skbuff.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <net/checksum.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include "olympic.h"
+
+/* I've got to put some intelligence into the version number so that Peter and I know
+ * which version of the code somebody has got.
+ * Version Number = a.b.c.d where a.b.c is the level of code and d is the latest author.
+ * So 0.0.1.pds = Peter, 0.0.1.mlp = Mike
+ *
+ * Official releases will only have an a.b.c version number format.
+ */
+
+static char *version =
+"Olympic.c v0.2.0 6/8/99 - Peter De Schrijver & Mike Phillips" ;
+
+static char *open_maj_error[] = {"No error", "Lobe Media Test", "Physical Insertion",
+ "Address Verification", "Neighbor Notification (Ring Poll)",
+ "Request Parameters","FDX Registration Request",
+ "FDX Duplicate Address Check", "Station registration Query Wait",
+ "Unknown stage"};
+
+static char *open_min_error[] = {"No error", "Function Failure", "Signal Lost", "Wire Fault",
+ "Ring Speed Mismatch", "Timeout","Ring Failure","Ring Beaconing",
+ "Duplicate Node Address","Request Parameters","Remove Received",
+ "Reserved", "Reserved", "No Monitor Detected for RPL",
+ "Monitor Contention failer for RPL", "FDX Protocol Error"};
+
+/* Module paramters */
+
+/* Ring Speed 0,4,16,100
+ * 0 = Autosense
+ * 4,16 = Selected speed only, no autosense
+ * This allows the card to be the first on the ring
+ * and become the active monitor.
+ * 100 = Nothing at present, 100mbps is autodetected
+ * if FDX is turned on. May be implemented in the future to
+ * fail if 100mpbs is not detected.
+ *
+ * WARNING: Some hubs will allow you to insert
+ * at the wrong speed
+ */
+
+static int ringspeed[OLYMPIC_MAX_ADAPTERS] = {0,} ;
+
+MODULE_PARM(ringspeed, "1-" __MODULE_STRING(OLYMPIC_MAX_ADAPTERS) "i");
+
+/* Packet buffer size */
+
+static int pkt_buf_sz[OLYMPIC_MAX_ADAPTERS] = {0,} ;
+
+MODULE_PARM(pkt_buf_sz, "1-" __MODULE_STRING(OLYMPIC_MAX_ADAPTERS) "i") ;
+
+/* Message Level */
+
+static int message_level[OLYMPIC_MAX_ADAPTERS] = {0,} ;
+
+MODULE_PARM(message_level, "1-" __MODULE_STRING(OLYMPIC_MAX_ADAPTERS) "i") ;
+
+static int olympic_scan(struct device *dev);
+static int olympic_init(struct device *dev);
+static int olympic_open(struct device *dev);
+static int olympic_xmit(struct sk_buff *skb, struct device *dev);
+static int olympic_close(struct device *dev);
+static void olympic_set_rx_mode(struct device *dev);
+static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static struct net_device_stats * olympic_get_stats(struct device *dev);
+static int olympic_set_mac_address(struct device *dev, void *addr) ;
+static void olympic_arb_cmd(struct device *dev);
+static int olympic_change_mtu(struct device *dev, int mtu);
+static void olympic_srb_bh(struct device *dev) ;
+static void olympic_asb_bh(struct device *dev) ;
+#if OLYMPIC_NETWORK_MONITOR
+#ifdef CONFIG_PROC_FS
+static int sprintf_info(char *buffer, struct device *dev) ;
+#endif
+#endif
+
+__initfunc(int olympic_probe(struct device *dev))
+{
+ int cards_found;
+
+ cards_found=olympic_scan(dev);
+ return cards_found ? 0 : -ENODEV;
+}
+
+__initfunc(static int olympic_scan(struct device *dev))
+{
+ struct pci_dev *pci_device = NULL ;
+ struct olympic_private *olympic_priv;
+ int card_no = 0 ;
+ if (pci_present()) {
+
+ while((pci_device=pci_find_device(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_TR_WAKE, pci_device))) {
+
+ pci_set_master(pci_device);
+
+ /* Check to see if io has been allocated, if so, we've already done this card,
+ so continue on the card discovery loop */
+
+ if (check_region(pci_device->base_address[0] & (~3), OLYMPIC_IO_SPACE)) {
+ card_no++ ;
+ continue ;
+ }
+
+ olympic_priv=kmalloc(sizeof (struct olympic_private), GFP_KERNEL);
+ memset(olympic_priv, 0, sizeof(struct olympic_private));
+ init_waitqueue_head(&olympic_priv->srb_wait);
+ init_waitqueue_head(&olympic_priv->trb_wait);
+#ifndef MODULE
+ dev=init_trdev(dev, 0);
+#endif
+ dev->priv=(void *)olympic_priv;
+#if OLYMPIC_DEBUG
+ printk("pci_device: %p, dev:%p, dev->priv: %p\n", pci_device, dev, dev->priv);
+#endif
+ dev->irq=pci_device->irq;
+ dev->base_addr=pci_device->base_address[0] & (~3);
+ dev->init=&olympic_init;
+ olympic_priv->olympic_mmio=ioremap(pci_device->base_address[1],256);
+ olympic_priv->olympic_lap=ioremap(pci_device->base_address[2],2048);
+
+ if ((pkt_buf_sz[card_no] < 100) || (pkt_buf_sz[card_no] > 18000) )
+ olympic_priv->pkt_buf_sz = PKT_BUF_SZ ;
+ else
+ olympic_priv->pkt_buf_sz = pkt_buf_sz[card_no] ;
+
+ olympic_priv->olympic_ring_speed = ringspeed[card_no] ;
+ olympic_priv->olympic_message_level = message_level[card_no] ;
+ olympic_priv->olympic_multicast_set = 0 ;
+
+ if(olympic_init(dev)==-1) {
+ unregister_netdevice(dev);
+ kfree(dev->priv);
+ return 0;
+ }
+
+ dev->open=&olympic_open;
+ dev->hard_start_xmit=&olympic_xmit;
+ dev->change_mtu=&olympic_change_mtu;
+
+ dev->stop=&olympic_close;
+ dev->do_ioctl=NULL;
+ dev->set_multicast_list=&olympic_set_rx_mode;
+ dev->get_stats=&olympic_get_stats ;
+ dev->set_mac_address=&olympic_set_mac_address ;
+ return 1;
+ }
+ }
+ return 0 ;
+}
+
+
+__initfunc(static int olympic_init(struct device *dev))
+{
+ struct olympic_private *olympic_priv;
+ __u8 *olympic_mmio, *init_srb,*adapter_addr;
+ unsigned long t;
+ unsigned int uaa_addr;
+
+ olympic_priv=(struct olympic_private *)dev->priv;
+ olympic_mmio=olympic_priv->olympic_mmio;
+
+ printk("%s \n", version);
+ printk("%s: IBM PCI tokenring card. I/O at %hx, MMIO at %p, LAP at %p, using irq %d\n",dev->name, (unsigned int) dev->base_addr,olympic_priv->olympic_mmio, olympic_priv->olympic_lap, dev->irq);
+
+ request_region(dev->base_addr, OLYMPIC_IO_SPACE, "olympic");
+ writel(readl(olympic_mmio+BCTL) | BCTL_SOFTRESET,olympic_mmio+BCTL);
+ t=jiffies;
+ while((readl(olympic_priv->olympic_mmio+BCTL)) & BCTL_SOFTRESET) {
+ schedule();
+ if(jiffies-t > 40*HZ) {
+ printk(KERN_ERR "IBM PCI tokenring card not responding.\n");
+ release_region(dev->base_addr, OLYMPIC_IO_SPACE) ;
+ return -1;
+ }
+ }
+
+#if OLYMPIC_DEBUG
+ printk("BCTL: %x\n",readl(olympic_mmio+BCTL));
+ printk("GPR: %x\n",readw(olympic_mmio+GPR));
+ printk("SISRMASK: %x\n",readl(olympic_mmio+SISR_MASK));
+#endif
+ /* Aaaahhh, You have got to be real careful setting GPR, the card
+ holds the previous values from flash memory, including autosense
+ and ring speed */
+
+ writel(readl(olympic_mmio+BCTL)|BCTL_MIMREB,olympic_mmio+BCTL);
+
+ if (olympic_priv->olympic_ring_speed == 0) { /* Autosense */
+ writel(readl(olympic_mmio+GPR)|GPR_AUTOSENSE,olympic_mmio+GPR);
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Ringspeed autosense mode on\n",dev->name);
+ } else if (olympic_priv->olympic_ring_speed == 16) {
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Trying to open at 16 Mbps as requested\n", dev->name);
+ writel(GPR_16MBPS, olympic_mmio+GPR);
+ } else if (olympic_priv->olympic_ring_speed == 4) {
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Trying to open at 4 Mbps as requested\n", dev->name) ;
+ writel(0, olympic_mmio+GPR);
+ }
+
+ writel(readl(olympic_mmio+GPR)|GPR_NEPTUNE_BF,olympic_mmio+GPR);
+
+#if OLYMPIC_DEBUG
+ printk("GPR = %x\n",readw(olympic_mmio + GPR) ) ;
+#endif
+ /* start solo init */
+ writel((1<<15),olympic_mmio+SISR_MASK_SUM);
+
+ t=jiffies;
+ while(!((readl(olympic_mmio+SISR_RR)) & SISR_SRB_REPLY)) {
+ schedule();
+ if(jiffies-t > 40*HZ) {
+ printk(KERN_ERR "IBM PCI tokenring card not responding.\n");
+ release_region(dev->base_addr, OLYMPIC_IO_SPACE);
+ return -1;
+ }
+ }
+
+ writel(readl(olympic_mmio+LAPWWO),olympic_mmio+LAPA);
+
+#if OLYMPIC_DEBUG
+ printk("LAPWWO: %x, LAPA: %x\n",readl(olympic_mmio+LAPWWO), readl(olympic_mmio+LAPA));
+#endif
+
+ init_srb=olympic_priv->olympic_lap + ((readl(olympic_mmio+LAPWWO)) & (~0xf800));
+
+#if OLYMPIC_DEBUG
+{
+ int i;
+ printk("init_srb(%p): ",init_srb);
+ for(i=0;i<20;i++)
+ printk("%x ",readb(init_srb+i));
+ printk("\n");
+}
+#endif
+ if(readw(init_srb+6)) {
+ printk(KERN_INFO "tokenring card intialization failed. errorcode : %x\n",readw(init_srb+6));
+ release_region(dev->base_addr, OLYMPIC_IO_SPACE);
+ return -1;
+ }
+
+ uaa_addr=ntohs(readw(init_srb+8));
+
+#if OLYMPIC_DEBUG
+ printk("UAA resides at %x\n",uaa_addr);
+#endif
+
+ writel(uaa_addr,olympic_mmio+LAPA);
+ adapter_addr=olympic_priv->olympic_lap + (uaa_addr & (~0xf800));
+
+#if OLYMPIC_DEBUG
+ printk("adapter address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ readb(adapter_addr), readb(adapter_addr+1),readb(adapter_addr+2),
+ readb(adapter_addr+3),readb(adapter_addr+4),readb(adapter_addr+5));
+#endif
+
+ memcpy_fromio(&dev->dev_addr[0], adapter_addr,6);
+
+ olympic_priv->olympic_addr_table_addr = ntohs(readw(init_srb + 12)) ;
+ olympic_priv->olympic_parms_addr = ntohs(readw(init_srb + 14)) ;
+
+ return 0;
+
+}
+
+static int olympic_open(struct device *dev)
+{
+ struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+ __u8 *olympic_mmio=olympic_priv->olympic_mmio,*init_srb;
+ unsigned long flags;
+ char open_error[255] ;
+ int i, open_finished = 1 ;
+
+#if OLYMPIC_NETWORK_MONITOR
+ __u8 *oat ;
+ __u8 *opt ;
+#endif
+
+ if(request_irq(dev->irq, &olympic_interrupt, SA_SHIRQ , "olympic", dev)) {
+ return -EAGAIN;
+ }
+
+#if OLYMPIC_DEBUG
+ printk("BMCTL: %x\n",readl(olympic_mmio+BMCTL_SUM));
+ printk("pending ints: %x\n",readl(olympic_mmio+SISR_RR));
+#endif
+
+ writel(SISR_MI,olympic_mmio+SISR_MASK_SUM);
+
+ writel(SISR_MI | SISR_SRB_REPLY, olympic_mmio+SISR_MASK); /* more ints later, doesn't stop arb cmd interrupt */
+
+ writel(LISR_LIE,olympic_mmio+LISR); /* more ints later */
+
+ /* adapter is closed, so SRB is pointed to by LAPWWO */
+
+ writel(readl(olympic_mmio+LAPWWO),olympic_mmio+LAPA);
+ init_srb=olympic_priv->olympic_lap + ((readl(olympic_mmio+LAPWWO)) & (~0xf800));
+
+#if OLYMPIC_DEBUG
+ printk("LAPWWO: %x, LAPA: %x\n",readl(olympic_mmio+LAPWWO), readl(olympic_mmio+LAPA));
+ printk("SISR Mask = %04x\n", readl(olympic_mmio+SISR_MASK));
+ printk("Before the open command \n");
+#endif
+ do {
+ int i;
+
+ save_flags(flags);
+ cli();
+ for(i=0;i<SRB_COMMAND_SIZE;i+=4)
+ writel(0,init_srb+i);
+ if(SRB_COMMAND_SIZE & 2)
+ writew(0,init_srb+(SRB_COMMAND_SIZE & ~3));
+ if(SRB_COMMAND_SIZE & 1)
+ writeb(0,init_srb+(SRB_COMMAND_SIZE & ~1));
+
+ writeb(SRB_OPEN_ADAPTER,init_srb) ; /* open */
+ writeb(OLYMPIC_CLEAR_RET_CODE,init_srb+2);
+
+ /* If Network Monitor, instruct card to copy MAC frames through the ARB */
+
+#if OLYMPIC_NETWORK_MONITOR
+ writew(ntohs(OPEN_ADAPTER_ENABLE_FDX | OPEN_ADAPTER_PASS_ADC_MAC | OPEN_ADAPTER_PASS_ATT_MAC | OPEN_ADAPTER_PASS_BEACON),init_srb+8);
+#else
+ writew(OPEN_ADAPTER_ENABLE_FDX,init_srb+8);
+#endif
+
+ if (olympic_priv->olympic_laa[0]) {
+ writeb(olympic_priv->olympic_laa[0],init_srb+12);
+ writeb(olympic_priv->olympic_laa[1],init_srb+13);
+ writeb(olympic_priv->olympic_laa[2],init_srb+14);
+ writeb(olympic_priv->olympic_laa[3],init_srb+15);
+ writeb(olympic_priv->olympic_laa[4],init_srb+16);
+ writeb(olympic_priv->olympic_laa[5],init_srb+17);
+ memcpy(dev->dev_addr,olympic_priv->olympic_laa,dev->addr_len) ;
+ }
+ writeb(1,init_srb+30);
+
+ olympic_priv->srb_queued=1;
+
+ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+ while(olympic_priv->srb_queued) {
+ interruptible_sleep_on_timeout(&olympic_priv->srb_wait, 60*HZ);
+ if(signal_pending(current)) {
+ printk(KERN_WARNING "%s: SRB timed out.\n",
+ dev->name);
+ printk(KERN_WARNING "SISR=%x MISR=%x\n",
+ readl(olympic_mmio+SISR),
+ readl(olympic_mmio+LISR));
+ olympic_priv->srb_queued=0;
+ break;
+ }
+ }
+ restore_flags(flags);
+#if OLYMPIC_DEBUG
+ printk("init_srb(%p): ",init_srb);
+ for(i=0;i<20;i++)
+ printk("%x ",readb(init_srb+i));
+ printk("\n");
+#endif
+
+ /* If we get the same return response as we set, the interrupt wasn't raised and the open
+ * timed out.
+ */
+
+ if(readb(init_srb+2)== OLYMPIC_CLEAR_RET_CODE) {
+ printk(KERN_WARNING "%s: Adapter Open time out or error.\n", dev->name) ;
+ return -EIO ;
+ }
+
+ if(readb(init_srb+2)!=0) {
+ if (readb(init_srb+2) == 0x07) {
+ if (!olympic_priv->olympic_ring_speed && open_finished) { /* Autosense , first time around */
+ printk(KERN_WARNING "%s: Retrying at different ring speed \n", dev->name);
+ open_finished = 0 ;
+ } else {
+
+ strcpy(open_error, open_maj_error[(readb(init_srb+7) & 0xf0) >> 4]) ;
+ strcat(open_error," - ") ;
+ strcat(open_error, open_min_error[(readb(init_srb+7) & 0x0f)]) ;
+
+ if (!olympic_priv->olympic_ring_speed && ((readb(init_srb+7) & 0x0f) == 0x0d)) {
+ printk(KERN_WARNING "%s: Tried to autosense ring speed with no monitors present\n",dev->name);
+ printk(KERN_WARNING "%s: Please try again with a specified ring speed \n",dev->name);
+ free_irq(dev->irq, dev);
+ return -EIO ;
+ }
+
+ printk(KERN_WARNING "%s: %s\n",dev->name,open_error);
+ free_irq(dev->irq,dev) ;
+ return -EIO ;
+
+ } /* if autosense && open_finished */
+ } else {
+ printk(KERN_WARNING "%s: Bad OPEN response: %x\n", dev->name,init_srb[2]);
+ free_irq(dev->irq, dev);
+ return -EIO;
+ }
+ } else
+ open_finished = 1 ;
+ } while (!(open_finished)) ; /* Will only loop if ring speed mismatch re-open attempted && autosense is on */
+
+ if (readb(init_srb+18) & (1<<3))
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Opened in FDX Mode\n",dev->name);
+
+ if (readb(init_srb+18) & (1<<1))
+ olympic_priv->olympic_ring_speed = 100 ;
+ else if (readb(init_srb+18) & 1)
+ olympic_priv->olympic_ring_speed = 16 ;
+ else
+ olympic_priv->olympic_ring_speed = 4 ;
+
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Opened in %d Mbps mode\n",dev->name, olympic_priv->olympic_ring_speed);
+
+ olympic_priv->asb=ntohs(readw(init_srb+8));
+ olympic_priv->srb=ntohs(readw(init_srb+10));
+ olympic_priv->arb=ntohs(readw(init_srb+12));
+ olympic_priv->trb=ntohs(readw(init_srb+16));
+
+ olympic_priv->olympic_receive_options = 0x01 ;
+ olympic_priv->olympic_copy_all_options = 0 ;
+
+ /* setup rx ring */
+
+ writel((3<<16),olympic_mmio+BMCTL_RWM); /* Ensure end of frame generated interrupts */
+
+ writel(BMCTL_RX_DIS|3,olympic_mmio+BMCTL_RWM); /* Yes, this the enables RX channel */
+
+ for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {
+
+ struct sk_buff *skb;
+
+ skb=dev_alloc_skb(olympic_priv->pkt_buf_sz);
+ if(skb == NULL)
+ break;
+
+ skb->dev = dev;
+
+ olympic_priv->olympic_rx_ring[i].buffer=virt_to_bus(skb->data);
+ olympic_priv->olympic_rx_ring[i].res_length = olympic_priv->pkt_buf_sz ;
+ olympic_priv->rx_ring_skb[i]=skb;
+ }
+
+ if (i==0) {
+ printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers. Adapter disabled\n",dev->name);
+ free_irq(dev->irq, dev);
+ return -EIO;
+ }
+
+ writel(virt_to_bus(&olympic_priv->olympic_rx_ring[0]),olympic_mmio+RXDESCQ);
+ writel(virt_to_bus(&olympic_priv->olympic_rx_ring[0]),olympic_mmio+RXCDA);
+ writew(i,olympic_mmio+RXDESCQCNT);
+
+ writel(virt_to_bus(&olympic_priv->olympic_rx_status_ring[0]),olympic_mmio+RXSTATQ);
+ writel(virt_to_bus(&olympic_priv->olympic_rx_status_ring[0]),olympic_mmio+RXCSA);
+
+ olympic_priv->rx_ring_last_received=OLYMPIC_RX_RING_SIZE-1; /* last processed rx status */
+ olympic_priv->rx_status_last_received = OLYMPIC_RX_RING_SIZE-1;
+
+ writew(i,olympic_mmio+RXSTATQCNT);
+
+#if OLYMPIC_DEBUG
+ printk("# of rx buffers: %d, RXENQ: %x\n",i, readw(olympic_mmio+RXENQ));
+ printk("RXCSA: %x, rx_status_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCSA)),&olympic_priv->olympic_rx_status_ring[0]);
+ printk(" stat_ring[1]: %p, stat_ring[2]: %p, stat_ring[3]: %p\n", &(olympic_priv->olympic_rx_status_ring[1]), &(olympic_priv->olympic_rx_status_ring[2]), &(olympic_priv->olympic_rx_status_ring[3]) );
+ printk(" stat_ring[4]: %p, stat_ring[5]: %p, stat_ring[6]: %p\n", &(olympic_priv->olympic_rx_status_ring[4]), &(olympic_priv->olympic_rx_status_ring[5]), &(olympic_priv->olympic_rx_status_ring[6]) );
+ printk(" stat_ring[7]: %p\n", &(olympic_priv->olympic_rx_status_ring[7]) );
+
+ printk("RXCDA: %x, rx_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCDA)),&olympic_priv->olympic_rx_ring[0]);
+#endif
+
+ writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) | i,olympic_mmio+RXENQ);
+
+#if OLYMPIC_DEBUG
+ printk("# of rx buffers: %d, RXENQ: %x\n",i, readw(olympic_mmio+RXENQ));
+ printk("RXCSA: %x, rx_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCSA)),&olympic_priv->olympic_rx_status_ring[0]);
+ printk("RXCDA: %x, rx_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCDA)),&olympic_priv->olympic_rx_ring[0]);
+#endif
+
+ writel(SISR_RX_STATUS | SISR_RX_NOBUF,olympic_mmio+SISR_MASK_SUM);
+
+ /* setup tx ring */
+
+ writel(BMCTL_TX1_DIS,olympic_mmio+BMCTL_RWM); /* Yes, this enables TX channel 1 */
+ for(i=0;i<OLYMPIC_TX_RING_SIZE;i++)
+ olympic_priv->olympic_tx_ring[i].buffer=0xdeadbeef;
+
+ olympic_priv->free_tx_ring_entries=OLYMPIC_TX_RING_SIZE;
+ writel(virt_to_bus(&olympic_priv->olympic_tx_ring[0]),olympic_mmio+TXDESCQ_1);
+ writel(virt_to_bus(&olympic_priv->olympic_tx_ring[0]),olympic_mmio+TXCDA_1);
+ writew(OLYMPIC_TX_RING_SIZE,olympic_mmio+TXDESCQCNT_1);
+
+ writel(virt_to_bus(&olympic_priv->olympic_tx_status_ring[0]),olympic_mmio+TXSTATQ_1);
+ writel(virt_to_bus(&olympic_priv->olympic_tx_status_ring[0]),olympic_mmio+TXCSA_1);
+ writew(OLYMPIC_TX_RING_SIZE,olympic_mmio+TXSTATQCNT_1);
+
+ olympic_priv->tx_ring_free=0; /* next entry in tx ring to use */
+ olympic_priv->tx_ring_last_status=OLYMPIC_TX_RING_SIZE-1; /* last processed tx status */
+
+ writel(SISR_TX1_EOF | SISR_ADAPTER_CHECK | SISR_ARB_CMD | SISR_TRB_REPLY | SISR_ASB_FREE,olympic_mmio+SISR_MASK_SUM);
+
+#if OLYMPIC_DEBUG
+ printk("BMCTL: %x\n",readl(olympic_mmio+BMCTL_SUM));
+ printk("SISR MASK: %x\n",readl(olympic_mmio+SISR_MASK));
+#endif
+
+#if OLYMPIC_NETWORK_MONITOR
+ oat = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ;
+ opt = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ;
+
+ printk("%s: Node Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name,
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+1),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+2),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+3),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+4),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+5));
+ printk("%s: Functional Address: %02x:%02x:%02x:%02x\n",dev->name,
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+1),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+2),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+3));
+
+ printk("%s: NAUN Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name,
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+1),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+2),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+3),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+4),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+5));
+
+
+#endif
+
+ dev->start = 1;
+ dev->interrupt=0;
+ dev->tbusy=0;
+
+ MOD_INC_USE_COUNT ;
+ return 0;
+
+}
+
+/*
+ * When we enter the rx routine we do not know how many frames have been
+ * queued on the rx channel. Therefore we start at the next rx status
+ * position and travel around the receive ring until we have completed
+ * all the frames.
+ *
+ * This means that we may process the frame before we receive the end
+ * of frame interrupt. This is why we always test the status instead
+ * of blindly processing the next frame.
+ *
+ */
+static void olympic_rx(struct device *dev)
+{
+ struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+ __u8 *olympic_mmio=olympic_priv->olympic_mmio;
+ struct olympic_rx_status *rx_status;
+ struct olympic_rx_desc *rx_desc ;
+ int rx_ring_last_received,length, buffer_cnt, cpy_length, frag_len;
+ struct sk_buff *skb, *skb2;
+ int i;
+
+ rx_status=&(olympic_priv->olympic_rx_status_ring[(olympic_priv->rx_status_last_received + 1) & (OLYMPIC_RX_RING_SIZE - 1)]) ;
+
+ while (rx_status->status_buffercnt) {
+
+ olympic_priv->rx_status_last_received++ ;
+ olympic_priv->rx_status_last_received &= (OLYMPIC_RX_RING_SIZE -1);
+#if OLYMPIC_DEBUG
+ printk(" stat_ring addr: %x \n", &(olympic_priv->olympic_rx_status_ring[olympic_priv->rx_status_last_received]) );
+ printk("rx status: %x rx len: %x \n",rx_status->status_buffercnt,rx_status->fragmentcnt_framelen);
+#endif
+ length=rx_status->fragmentcnt_framelen & 0xffff;
+ buffer_cnt = rx_status->status_buffercnt & 0xffff ;
+ i = buffer_cnt ; /* Need buffer_cnt later for rxenq update */
+ frag_len = rx_status->fragmentcnt_framelen >> 16 ;
+
+#if OLYMPIC_DEBUG
+ printk("length: %x, frag_len: %x, buffer_cnt: %x\n",length,frag_len,buffer_cnt);
+#endif
+
+ if(rx_status->status_buffercnt & 0xC0000000) {
+ if (rx_status->status_buffercnt & 0x3B000000) {
+ if (olympic_priv->olympic_message_level) {
+ if (rx_status->status_buffercnt & (1<<29)) /* Rx Frame Truncated */
+ printk(KERN_WARNING "%s: Rx Frame Truncated \n",dev->name);
+ if (rx_status->status_buffercnt & (1<<28)) /*Rx receive overrun */
+ printk(KERN_WARNING "%s: Rx Frame Receive overrun \n",dev->name);
+ if (rx_status->status_buffercnt & (1<<27)) /* No receive buffers */
+ printk(KERN_WARNING "%s: No receive buffers \n",dev->name);
+ if (rx_status->status_buffercnt & (1<<25)) /* Receive frame error detect */
+ printk(KERN_WARNING "%s: Receive frame error detect \n",dev->name);
+ if (rx_status->status_buffercnt & (1<<24)) /* Received Error Detect */
+ printk(KERN_WARNING "%s: Received Error Detect \n",dev->name);
+ }
+ olympic_priv->rx_ring_last_received += i ;
+ olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1) ;
+ olympic_priv->olympic_stats.rx_errors++;
+ } else {
+
+ if (buffer_cnt == 1) {
+ skb = dev_alloc_skb(olympic_priv->pkt_buf_sz) ;
+ } else {
+ skb = dev_alloc_skb(length) ;
+ }
+
+ if (skb == NULL) {
+ printk(KERN_WARNING "%s: Not enough memory to copy packet to upper layers. \n",dev->name) ;
+ olympic_priv->olympic_stats.rx_dropped++ ;
+ /* Update counters even though we don't transfer the frame */
+ olympic_priv->rx_ring_last_received += i ;
+ olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1) ;
+ } else {
+ skb->dev = dev ;
+
+ /* Optimise based upon number of buffers used.
+ If only one buffer is used we can simply swap the buffers around.
+ If more than one then we must use the new buffer and copy the information
+ first. Ideally all frames would be in a single buffer, this can be tuned by
+ altering the buffer size. */
+
+ if (buffer_cnt==1) {
+ olympic_priv->rx_ring_last_received++ ;
+ olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1);
+ rx_ring_last_received = olympic_priv->rx_ring_last_received ;
+ skb2=olympic_priv->rx_ring_skb[rx_ring_last_received] ;
+ skb_put(skb2,length);
+ skb2->protocol = tr_type_trans(skb2,dev);
+ olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer=virt_to_bus(skb->data);
+ olympic_priv->olympic_rx_ring[rx_ring_last_received].res_length = olympic_priv->pkt_buf_sz ;
+ olympic_priv->rx_ring_skb[rx_ring_last_received] = skb ;
+ netif_rx(skb2) ;
+ } else {
+ do { /* Walk the buffers */
+ olympic_priv->rx_ring_last_received++ ;
+ olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1);
+ rx_ring_last_received = olympic_priv->rx_ring_last_received ;
+ rx_desc = &(olympic_priv->olympic_rx_ring[rx_ring_last_received]);
+ cpy_length = (i == 1 ? frag_len : rx_desc->res_length);
+ memcpy(skb_put(skb, cpy_length), bus_to_virt(rx_desc->buffer), cpy_length) ;
+ } while (--i) ;
+
+ skb->protocol = tr_type_trans(skb,dev);
+ netif_rx(skb) ;
+ }
+ olympic_priv->olympic_stats.rx_packets++ ;
+ olympic_priv->olympic_stats.rx_bytes += length ;
+ } /* if skb == null */
+ } /* If status & 0x3b */
+
+ } else { /*if buffercnt & 0xC */
+ olympic_priv->rx_ring_last_received += i ;
+ olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE - 1) ;
+ }
+
+ rx_status->fragmentcnt_framelen = 0 ;
+ rx_status->status_buffercnt = 0 ;
+ rx_status = &(olympic_priv->olympic_rx_status_ring[(olympic_priv->rx_status_last_received+1) & (OLYMPIC_RX_RING_SIZE -1) ]);
+
+ writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) | buffer_cnt , olympic_mmio+RXENQ);
+ } /* while */
+
+}
+
+static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct device *dev= (struct device *)dev_id;
+ struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+ __u8 *olympic_mmio=olympic_priv->olympic_mmio;
+ __u32 sisr;
+ __u8 *adapter_check_area ;
+
+ sisr=readl(olympic_mmio+SISR_RR) ; /* Reset sisr */
+
+ if (!(sisr & SISR_MI)) /* Interrupt isn't for us */
+ return ;
+
+ if (dev->interrupt)
+ printk(KERN_WARNING "%s: Re-entering interrupt \n",dev->name) ;
+
+ dev->interrupt = 1 ;
+
+ if (sisr & (SISR_SRB_REPLY | SISR_TX1_EOF | SISR_RX_STATUS | SISR_ADAPTER_CHECK |
+ SISR_ASB_FREE | SISR_ARB_CMD | SISR_TRB_REPLY | SISR_RX_NOBUF)) {
+
+ if(sisr & SISR_SRB_REPLY) {
+ if(olympic_priv->srb_queued==1) {
+ wake_up_interruptible(&olympic_priv->srb_wait);
+ } else if (olympic_priv->srb_queued==2) {
+ olympic_srb_bh(dev) ;
+ }
+ olympic_priv->srb_queued=0;
+ } /* SISR_SRB_REPLY */
+
+ if (sisr & SISR_TX1_EOF) {
+ olympic_priv->tx_ring_last_status++;
+ olympic_priv->tx_ring_last_status &= (OLYMPIC_TX_RING_SIZE-1);
+ olympic_priv->free_tx_ring_entries++;
+ olympic_priv->olympic_stats.tx_bytes += olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]->len;
+ olympic_priv->olympic_stats.tx_packets++ ;
+ dev_kfree_skb(olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]);
+ olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_last_status].buffer=0xdeadbeef;
+ olympic_priv->olympic_tx_status_ring[olympic_priv->tx_ring_last_status].status=0;
+
+ if(dev->tbusy) {
+ dev->tbusy=0;
+ mark_bh(NET_BH);
+ }
+ } /* SISR_TX1_EOF */
+
+ if (sisr & SISR_RX_STATUS) {
+ olympic_rx(dev);
+ } /* SISR_RX_STATUS */
+
+ if (sisr & SISR_ADAPTER_CHECK) {
+ printk(KERN_WARNING "%s: Adapter Check Interrupt Raised, 8 bytes of information follow:\n", dev->name);
+ writel(readl(olympic_mmio+LAPWWO),olympic_mmio+LAPA);
+ adapter_check_area = (__u8 *)(olympic_mmio+LAPWWO) ;
+ printk(KERN_WARNING "%s: Bytes %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, readb(adapter_check_area+0), readb(adapter_check_area+1), readb(adapter_check_area+2), readb(adapter_check_area+3), readb(adapter_check_area+4), readb(adapter_check_area+5), readb(adapter_check_area+6), readb(adapter_check_area+7)) ;
+ dev->interrupt = 0 ;
+ free_irq(dev->irq, dev) ;
+
+ } /* SISR_ADAPTER_CHECK */
+
+ if (sisr & SISR_ASB_FREE) {
+ /* Wake up anything that is waiting for the asb response */
+ if (olympic_priv->asb_queued) {
+ olympic_asb_bh(dev) ;
+ }
+ } /* SISR_ASB_FREE */
+
+ if (sisr & SISR_ARB_CMD) {
+ olympic_arb_cmd(dev) ;
+ } /* SISR_ARB_CMD */
+
+ if (sisr & SISR_TRB_REPLY) {
+ /* Wake up anything that is waiting for the trb response */
+ if (olympic_priv->trb_queued) {
+ wake_up_interruptible(&olympic_priv->trb_wait);
+ }
+ olympic_priv->trb_queued = 0 ;
+ } /* SISR_TRB_REPLY */
+
+ if (sisr & SISR_RX_NOBUF) {
+ /* According to the documentation, we don't have to do anything, but trapping it keeps it out of
+ /var/log/messages. */
+ } /* SISR_RX_NOBUF */
+ } else {
+ printk(KERN_WARNING "%s: Unexpected interrupt: %x\n",dev->name, sisr);
+ printk(KERN_WARNING "%s: SISR_MASK: %x\n",dev->name, readl(olympic_mmio+SISR_MASK)) ;
+ } /* One if the interrupts we want */
+
+ dev->interrupt = 0 ;
+
+ writel(SISR_MI,olympic_mmio+SISR_MASK_SUM);
+
+}
+
+static int olympic_xmit(struct sk_buff *skb, struct device *dev)
+{
+ struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+ __u8 *olympic_mmio=olympic_priv->olympic_mmio;
+
+ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+ return 1;
+ }
+
+ if(olympic_priv->free_tx_ring_entries) {
+ olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].buffer=virt_to_bus(skb->data);
+ olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].status_length=skb->len | (0x80000000);
+ olympic_priv->tx_ring_skb[olympic_priv->tx_ring_free]=skb;
+ olympic_priv->free_tx_ring_entries--;
+
+ olympic_priv->tx_ring_free++;
+ olympic_priv->tx_ring_free &= (OLYMPIC_TX_RING_SIZE-1);
+
+
+ writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1);
+
+ dev->tbusy=0;
+
+ return 0;
+ } else
+ return 1;
+
+}
+
+
+static int olympic_close(struct device *dev)
+{
+ struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+ __u8 *olympic_mmio=olympic_priv->olympic_mmio,*srb;
+ unsigned long flags;
+ int i;
+
+ writel(olympic_priv->srb,olympic_mmio+LAPA);
+ srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
+
+ writeb(SRB_CLOSE_ADAPTER,srb+0);
+ writeb(0,srb+1);
+ writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+
+ save_flags(flags);
+ cli();
+
+ olympic_priv->srb_queued=1;
+
+ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+ while(olympic_priv->srb_queued) {
+ interruptible_sleep_on_timeout(&olympic_priv->srb_wait, jiffies+60*HZ);
+ if(signal_pending(current)) {
+ printk(KERN_WARNING "%s: SRB timed out.\n",
+ dev->name);
+ printk(KERN_WARNING "SISR=%x MISR=%x\n",
+ readl(olympic_mmio+SISR),
+ readl(olympic_mmio+LISR));
+ olympic_priv->srb_queued=0;
+ break;
+ }
+ }
+
+ restore_flags(flags) ;
+ olympic_priv->rx_status_last_received++;
+ olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
+
+ for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {
+ dev_kfree_skb(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);
+ olympic_priv->rx_status_last_received++;
+ olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
+ }
+
+ /* reset tx/rx fifo's and busmaster logic */
+
+ writel(readl(olympic_mmio+BCTL)|(3<<13),olympic_mmio+BCTL);
+ udelay(1);
+ writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL);
+
+#if OLYMPIC_DEBUG
+ printk("srb(%p): ",srb);
+ for(i=0;i<4;i++)
+ printk("%x ",readb(srb+i));
+ printk("\n");
+#endif
+ dev->start = 0;
+ free_irq(dev->irq,dev);
+
+ MOD_DEC_USE_COUNT ;
+ return 0;
+
+}
+
+static void olympic_set_rx_mode(struct device *dev)
+{
+ struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ;
+ __u8 *olympic_mmio = olympic_priv->olympic_mmio ;
+ __u8 options = 0, set_mc_list = 0 ;
+ __u8 *srb, *ata ;
+ struct dev_mc_list *dmi ;
+
+ writel(olympic_priv->srb,olympic_mmio+LAPA);
+ srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
+ options = olympic_priv->olympic_copy_all_options;
+
+ if (dev->flags&IFF_PROMISC)
+ options |= (3<<5) ; /* All LLC and MAC frames, all through the main rx channel */
+ else
+ options &= ~(3<<5) ;
+
+ if (dev->mc_count) {
+ set_mc_list = 1 ;
+ }
+
+ /* Only issue the srb if there is a change in options */
+
+ if ((options ^ olympic_priv->olympic_copy_all_options)) {
+
+ /* Now to issue the srb command to alter the copy.all.options */
+
+ writeb(SRB_MODIFY_RECEIVE_OPTIONS,srb);
+ writeb(0,srb+1);
+ writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+ writeb(0,srb+3);
+ writeb(olympic_priv->olympic_receive_options,srb+4);
+ writeb(options,srb+5);
+
+ olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */
+
+ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+ olympic_priv->olympic_copy_all_options = options ;
+
+ return ;
+ }
+
+ if (set_mc_list ^ olympic_priv->olympic_multicast_set) { /* Multicast options have changed */
+
+ dmi = dev->mc_list ;
+
+ if (set_mc_list) { /* Turn multicast on */
+
+ /* RFC 1469 Says we must support using the functional address C0 00 00 04 00 00
+ * We do this with a set functional address mask.
+ */
+
+ ata=olympic_priv->olympic_lap + (olympic_priv->olympic_addr_table_addr) ;
+ if (!(readb(ata+11) & 0x04)) { /* Hmmm, need to set the functional mask */
+ writeb(SRB_SET_FUNC_ADDRESS,srb+0);
+ writeb(0,srb+1);
+ writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+ writeb(0,srb+3);
+ writeb(0,srb+4);
+ writeb(0,srb+5);
+ writeb(readb(ata+10),srb+6);
+ writeb(readb(ata+11)|4,srb+7);
+ writeb(readb(ata+12),srb+8);
+ writeb(readb(ata+13),srb+9);
+
+ olympic_priv->srb_queued = 2 ;
+ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+ olympic_priv->olympic_multicast_set = 1 ;
+ }
+
+
+ } else { /* Turn multicast off */
+
+ ata=olympic_priv->olympic_lap + (olympic_priv->olympic_addr_table_addr) ;
+ if ((readb(ata+11) & 0x04)) { /* Hmmm, need to reset the functional mask */
+ writeb(SRB_SET_FUNC_ADDRESS,srb+0);
+ writeb(0,srb+1);
+ writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+ writeb(0,srb+3);
+ writeb(0,srb+4);
+ writeb(0,srb+5);
+ writeb(readb(ata+10),srb+6);
+ writeb(readb(ata+11) & ~4,srb+7);
+ writeb(readb(ata+12),srb+8);
+ writeb(readb(ata+13),srb+9);
+
+ olympic_priv->srb_queued = 2 ;
+ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+ olympic_priv->olympic_multicast_set = 0 ;
+ }
+ }
+
+ }
+
+
+}
+
+static void olympic_srb_bh(struct device *dev)
+{
+ struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ;
+ __u8 *olympic_mmio = olympic_priv->olympic_mmio ;
+ __u8 *srb;
+
+ writel(olympic_priv->srb,olympic_mmio+LAPA);
+ srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
+
+ switch (readb(srb)) {
+
+ /* SRB_MODIFY_RECEIVE_OPTIONS i.e. set_multicast_list options (promiscuous)
+ * At some point we should do something if we get an error, such as
+ * resetting the IFF_PROMISC flag in dev
+ */
+
+ case SRB_MODIFY_RECEIVE_OPTIONS:
+ switch (readb(srb+2)) {
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command\n",dev->name) ;
+ break ;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name);
+ break ;
+ default:
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_WARNING "%s: Receive Options Modified to %x,%x\n",dev->name,olympic_priv->olympic_copy_all_options, olympic_priv->olympic_receive_options) ;
+ break ;
+ } /* switch srb[2] */
+ break ;
+
+ /* SRB_SET_GROUP_ADDRESS - Multicast group setting
+ */
+
+ case SRB_SET_GROUP_ADDRESS:
+ switch (readb(srb+2)) {
+ case 0x00:
+ olympic_priv->olympic_multicast_set = 1 ;
+ break ;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ;
+ break ;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name);
+ break ;
+ case 0x3c:
+ printk(KERN_WARNING "%s: Group/Functional address indicator bits not set correctly\n",dev->name) ;
+ break ;
+ case 0x3e: /* If we ever implement individual multicast addresses, will need to deal with this */
+ printk(KERN_WARNING "%s: Group address registers full\n",dev->name) ;
+ break ;
+ case 0x55:
+ printk(KERN_INFO "%s: Group Address already set.\n",dev->name) ;
+ break ;
+ default:
+ break ;
+ } /* switch srb[2] */
+ break ;
+
+ /* SRB_RESET_GROUP_ADDRESS - Remove a multicast address from group list
+ */
+
+ case SRB_RESET_GROUP_ADDRESS:
+ switch (readb(srb+2)) {
+ case 0x00:
+ olympic_priv->olympic_multicast_set = 0 ;
+ break ;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ;
+ break ;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ;
+ break ;
+ case 0x39: /* Must deal with this if individual multicast addresses used */
+ printk(KERN_INFO "%s: Group address not found \n",dev->name);
+ break ;
+ default:
+ break ;
+ } /* switch srb[2] */
+ break ;
+
+
+ /* SRB_SET_FUNC_ADDRESS - Called by the set_rx_mode
+ */
+
+ case SRB_SET_FUNC_ADDRESS:
+ switch (readb(srb+2)) {
+ case 0x00:
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Functional Address Mask Set \n",dev->name) ;
+ break ;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ;
+ break ;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ;
+ break ;
+ default:
+ break ;
+ } /* switch srb[2] */
+ break ;
+
+ /* SRB_READ_LOG - Read and reset the adapter error counters
+ */
+
+ case SRB_READ_LOG:
+ switch (readb(srb+2)) {
+ case 0x00:
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Read Log issued\n",dev->name) ;
+ break ;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ;
+ break ;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ;
+ break ;
+
+ } /* switch srb[2] */
+ break ;
+
+ /* SRB_READ_SR_COUNTERS - Read and reset the source routing bridge related counters */
+
+ case SRB_READ_SR_COUNTERS:
+ switch (readb(srb+2)) {
+ case 0x00:
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Read Source Routing Counters issued\n",dev->name) ;
+ break ;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ;
+ break ;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ;
+ break ;
+ default:
+ break ;
+ } /* switch srb[2] */
+ break ;
+
+ default:
+ printk(KERN_WARNING "%s: Unrecognized srb bh return value.\n",dev->name);
+ break ;
+ } /* switch srb[0] */
+
+}
+
+static struct net_device_stats * olympic_get_stats(struct device *dev)
+{
+ struct olympic_private *olympic_priv ;
+ olympic_priv=(struct olympic_private *) dev->priv;
+ return (struct net_device_stats *) &olympic_priv->olympic_stats;
+}
+
+static int olympic_set_mac_address (struct device *dev, void *addr)
+{
+ struct sockaddr *saddr = addr ;
+ struct olympic_private *olympic_priv = (struct olympic_private *)dev->priv ;
+
+ if (dev->start) {
+ printk(KERN_WARNING "%s: Cannot set mac/laa address while card is open\n", dev->name) ;
+ return -EIO ;
+ }
+
+ memcpy(olympic_priv->olympic_laa, saddr->sa_data,dev->addr_len) ;
+
+ if (olympic_priv->olympic_message_level) {
+ printk(KERN_INFO "%s: MAC/LAA Set to = %x.%x.%x.%x.%x.%x\n",dev->name, olympic_priv->olympic_laa[0],
+ olympic_priv->olympic_laa[1], olympic_priv->olympic_laa[2],
+ olympic_priv->olympic_laa[3], olympic_priv->olympic_laa[4],
+ olympic_priv->olympic_laa[5]);
+ }
+
+ return 0 ;
+}
+
+static void olympic_arb_cmd(struct device *dev)
+{
+ struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv;
+ __u8 *olympic_mmio=olympic_priv->olympic_mmio;
+ __u8 *arb_block, *asb_block, *srb ;
+ __u8 header_len ;
+ __u16 frame_len, buffer_len ;
+ struct sk_buff *mac_frame ;
+ __u8 *buf_ptr ;
+ __u8 *frame_data ;
+ __u16 buff_off ;
+ __u16 lan_status = 0, lan_status_diff ; /* Initialize to stop compiler warning */
+ __u8 fdx_prot_error ;
+ __u16 next_ptr;
+
+#if OLYMPIC_NETWORK_MONITOR
+ struct trh_hdr *mac_hdr ;
+#endif
+
+ arb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ;
+ asb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ;
+ srb = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->srb) ;
+ writel(readl(olympic_mmio+LAPA),olympic_mmio+LAPWWO);
+
+ if (readb(arb_block+0) == ARB_RECEIVE_DATA) { /* Receive.data, MAC frames */
+
+ header_len = readb(arb_block+8) ; /* 802.5 Token-Ring Header Length */
+ frame_len = ntohs(readw(arb_block + 10)) ;
+
+ buff_off = ntohs(readw(arb_block + 6)) ;
+
+ buf_ptr = olympic_priv->olympic_lap + buff_off ;
+
+#if OLYMPIC_DEBUG
+{
+ int i;
+ frame_data = buf_ptr+offsetof(struct mac_receive_buffer,frame_data) ;
+
+ for (i=0 ; i < 14 ; i++) {
+ printk("Loc %d = %02x\n",i,readb(frame_data + i));
+ }
+
+ printk("next %04x, fs %02x, len %04x \n",readw(buf_ptr+offsetof(struct mac_receive_buffer,next)), readb(buf_ptr+offsetof(struct mac_receive_buffer,frame_status)), readw(buf_ptr+offsetof(struct mac_receive_buffer,buffer_length)));
+}
+#endif
+ mac_frame = dev_alloc_skb(frame_len) ;
+
+ /* Walk the buffer chain, creating the frame */
+
+ do {
+ frame_data = buf_ptr+offsetof(struct mac_receive_buffer,frame_data) ;
+ buffer_len = ntohs(readw(buf_ptr+offsetof(struct mac_receive_buffer,buffer_length)));
+ memcpy_fromio(skb_put(mac_frame, buffer_len), frame_data , buffer_len ) ;
+ next_ptr=readw(buf_ptr+offsetof(struct mac_receive_buffer,next));
+
+ } while (next_ptr && (buf_ptr=olympic_priv->olympic_lap + ntohs(next_ptr)));
+
+#if OLYMPIC_NETWORK_MONITOR
+ printk(KERN_WARNING "%s: Received MAC Frame, details: \n",dev->name) ;
+ mac_hdr = (struct trh_hdr *)mac_frame->data ;
+ printk(KERN_WARNING "%s: MAC Frame Dest. Addr: %02x:%02x:%02x:%02x:%02x:%02x \n", dev->name , mac_hdr->daddr[0], mac_hdr->daddr[1], mac_hdr->daddr[2], mac_hdr->daddr[3], mac_hdr->daddr[4], mac_hdr->daddr[5]) ;
+ printk(KERN_WARNING "%s: MAC Frame Srce. Addr: %02x:%02x:%02x:%02x:%02x:%02x \n", dev->name , mac_hdr->saddr[0], mac_hdr->saddr[1], mac_hdr->saddr[2], mac_hdr->saddr[3], mac_hdr->saddr[4], mac_hdr->saddr[5]) ;
+#endif
+ mac_frame->dev = dev ;
+ mac_frame->protocol = tr_type_trans(mac_frame,dev);
+ netif_rx(mac_frame) ;
+
+ /* Now tell the card we have dealt with the received frame */
+
+ /* Set LISR Bit 1 */
+ writel(LISR_ARB_FREE,olympic_priv->olympic_lap + LISR_SUM);
+
+ /* Is the ASB free ? */
+
+ if (!(readl(olympic_priv->olympic_mmio + SISR) & SISR_ASB_FREE)) {
+ olympic_priv->asb_queued = 1 ;
+ writel(LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM);
+ return ;
+ /* Drop out and wait for the bottom half to be run */
+ }
+
+ writeb(ASB_RECEIVE_DATA,asb_block); /* Receive data */
+ writeb(OLYMPIC_CLEAR_RET_CODE,asb_block+2); /* Necessary ?? */
+ writeb(readb(arb_block+6),asb_block+6); /* Must send the address back to the adapter */
+ writeb(readb(arb_block+7),asb_block+7); /* To let it know we have dealt with the data */
+
+ writel(LISR_ASB_REPLY | LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM);
+
+ olympic_priv->asb_queued = 2 ;
+
+ return ;
+
+ } else if (readb(arb_block) == ARB_LAN_CHANGE_STATUS) { /* Lan.change.status */
+ lan_status = readw(arb_block+6);
+ fdx_prot_error = readb(arb_block+8) ;
+
+ /* Issue ARB Free */
+ writel(LISR_ARB_FREE,olympic_priv->olympic_mmio+LISR_SUM);
+
+ lan_status_diff = olympic_priv->olympic_lan_status ^ lan_status ;
+
+ if (lan_status_diff & (LSC_LWF | LSC_ARW | LSC_FPE | LSC_RR) ) {
+ if (lan_status_diff & LSC_LWF)
+ printk(KERN_WARNING "%s: Short circuit detected on the lobe\n",dev->name);
+ if (lan_status_diff & LSC_ARW)
+ printk(KERN_WARNING "%s: Auto removal error\n",dev->name);
+ if (lan_status_diff & LSC_FPE)
+ printk(KERN_WARNING "%s: FDX Protocol Error\n",dev->name);
+ if (lan_status_diff & LSC_RR)
+ printk(KERN_WARNING "%s: Force remove MAC frame received\n",dev->name);
+
+ /* Adapter has been closed by the hardware */
+
+ /* reset tx/rx fifo's and busmaster logic */
+
+ writel(readl(olympic_mmio+BCTL)|(3<<13),olympic_mmio+BCTL);
+ udelay(1);
+ writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL);
+ dev->tbusy = 1 ;
+ dev->interrupt = 1 ;
+ dev->start = 0 ;
+ olympic_priv->srb = readw(olympic_priv->olympic_lap + LAPWWO) ;
+ free_irq(dev->irq,dev);
+
+ printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ;
+
+ } /* If serious error */
+
+ if (olympic_priv->olympic_message_level) {
+ if (lan_status_diff & LSC_SIG_LOSS)
+ printk(KERN_WARNING "%s: No receive signal detected \n", dev->name) ;
+ if (lan_status_diff & LSC_HARD_ERR)
+ printk(KERN_INFO "%s: Beaconing \n",dev->name);
+ if (lan_status_diff & LSC_SOFT_ERR)
+ printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame \n",dev->name);
+ if (lan_status_diff & LSC_TRAN_BCN)
+ printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n",dev->name);
+ if (lan_status_diff & LSC_SS)
+ printk(KERN_INFO "%s: Single Station on the ring \n", dev->name);
+ if (lan_status_diff & LSC_RING_REC)
+ printk(KERN_INFO "%s: Ring recovery ongoing\n",dev->name);
+ if (lan_status_diff & LSC_FDX_MODE)
+ printk(KERN_INFO "%s: Operating in FDX mode\n",dev->name);
+ }
+
+ if (lan_status_diff & LSC_CO) {
+
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Counter Overflow \n", dev->name);
+
+ /* Issue READ.LOG command */
+
+ writeb(SRB_READ_LOG, srb);
+ writeb(0,srb+1);
+ writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+ writeb(0,srb+3);
+ writeb(0,srb+4);
+ writeb(0,srb+5);
+
+ olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */
+
+ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+ }
+
+ if (lan_status_diff & LSC_SR_CO) {
+
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Source routing counters overflow\n", dev->name);
+
+ /* Issue a READ.SR.COUNTERS */
+
+ writeb(SRB_READ_SR_COUNTERS,srb);
+ writeb(0,srb+1);
+ writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+ writeb(0,srb+3);
+
+ olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */
+
+ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+ }
+
+ olympic_priv->olympic_lan_status = lan_status ;
+
+ } /* Lan.change.status */
+ else
+ printk(KERN_WARNING "%s: Unknown arb command \n", dev->name);
+}
+
+static void olympic_asb_bh(struct device *dev)
+{
+ struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ;
+ __u8 *arb_block, *asb_block ;
+
+ arb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ;
+ asb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ;
+
+ if (olympic_priv->asb_queued == 1) { /* Dropped through the first time */
+
+ writeb(ASB_RECEIVE_DATA,asb_block); /* Receive data */
+ writeb(OLYMPIC_CLEAR_RET_CODE,asb_block+2); /* Necessary ?? */
+ writeb(readb(arb_block+6),asb_block+6); /* Must send the address back to the adapter */
+ writeb(readb(arb_block+7),asb_block+7); /* To let it know we have dealt with the data */
+
+ writel(LISR_ASB_REPLY | LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM);
+ olympic_priv->asb_queued = 2 ;
+
+ return ;
+ }
+
+ if (olympic_priv->asb_queued == 2) {
+ switch (readb(asb_block+2)) {
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized command code \n", dev->name);
+ break ;
+ case 0x26:
+ printk(KERN_WARNING "%s: Unrecognized buffer address \n", dev->name);
+ break ;
+ case 0xFF:
+ /* Valid response, everything should be ok again */
+ break ;
+ default:
+ printk(KERN_WARNING "%s: Invalid return code in asb\n",dev->name);
+ break ;
+ }
+ }
+ olympic_priv->asb_queued = 0 ;
+}
+
+static int olympic_change_mtu(struct device *dev, int mtu)
+{
+ struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv;
+ __u16 max_mtu ;
+
+ if (olympic_priv->olympic_ring_speed == 4)
+ max_mtu = 4500 ;
+ else
+ max_mtu = 18000 ;
+
+ if (mtu > max_mtu)
+ return -EINVAL ;
+ if (mtu < 100)
+ return -EINVAL ;
+
+ dev->mtu = mtu ;
+ olympic_priv->pkt_buf_sz = mtu + TR_HLEN ;
+
+ return 0 ;
+}
+
+#if OLYMPIC_NETWORK_MONITOR
+#ifdef CONFIG_PROC_FS
+static int olympic_proc_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+{
+ struct pci_dev *pci_device = NULL ;
+ int len=0;
+ off_t begin=0;
+ off_t pos=0;
+ int size;
+
+ struct device *dev;
+
+
+ size = sprintf(buffer,
+ "IBM Pit/Pit-Phy/Olympic Chipset Token Ring Adapters\n");
+
+ pos+=size;
+ len+=size;
+
+
+ while((pci_device=pci_find_device(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_TR_WAKE, pci_device))) {
+
+ for (dev = dev_base; dev != NULL; dev = dev->next)
+ {
+ if (dev->base_addr == (pci_device->base_address[0] & (~3)) ) { /* Yep, an Olympic device */
+ size = sprintf_info(buffer+len, dev);
+ len+=size;
+ pos=begin+len;
+
+ if(pos<offset)
+ {
+ len=0;
+ begin=pos;
+ }
+ if(pos>offset+length)
+ break;
+ } /* if */
+ } /* for */
+ } /* While */
+
+ *start=buffer+(offset-begin); /* Start of wanted data */
+ len-=(offset-begin); /* Start slop */
+ if(len>length)
+ len=length; /* Ending slop */
+ return len;
+}
+
+static int sprintf_info(char *buffer, struct device *dev)
+{
+ struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+ __u8 *oat = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ;
+ __u8 *opt = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ;
+ int size = 0 ;
+
+ size = sprintf(buffer, "\n%6s: Adapter Address : Node Address : Functional Addr\n",
+ dev->name);
+
+ size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x\n",
+ dev->name,
+ dev->dev_addr[0],
+ dev->dev_addr[1],
+ dev->dev_addr[2],
+ dev->dev_addr[3],
+ dev->dev_addr[4],
+ dev->dev_addr[5],
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+1),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+2),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+3),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+4),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+5),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+1),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+2),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+3));
+
+ size += sprintf(buffer+size, "\n%6s: Token Ring Parameters Table:\n", dev->name);
+
+ size += sprintf(buffer+size, "%6s: Physical Addr : Up Node Address : Poll Address : AccPri : Auth Src : Att Code :\n",
+ dev->name) ;
+
+ size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %04x : %04x : %04x :\n",
+ dev->name,
+ readb(opt+offsetof(struct olympic_parameters_table, phys_addr)),
+ readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+1),
+ readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+2),
+ readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+3),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+1),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+2),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+3),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+4),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+5),
+ readb(opt+offsetof(struct olympic_parameters_table, poll_addr)),
+ readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+1),
+ readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+2),
+ readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+3),
+ readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+4),
+ readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+5),
+ ntohs(readw(opt+offsetof(struct olympic_parameters_table, acc_priority))),
+ ntohs(readw(opt+offsetof(struct olympic_parameters_table, auth_source_class))),
+ ntohs(readw(opt+offsetof(struct olympic_parameters_table, att_code))));
+
+ size += sprintf(buffer+size, "%6s: Source Address : Bcn T : Maj. V : Lan St : Lcl Rg : Mon Err : Frame Correl : \n",
+ dev->name) ;
+
+ size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x:%02x:%02x : %04x : %04x : %04x : %04x : %04x : %04x : \n",
+ dev->name,
+ readb(opt+offsetof(struct olympic_parameters_table, source_addr)),
+ readb(opt+offsetof(struct olympic_parameters_table, source_addr)+1),
+ readb(opt+offsetof(struct olympic_parameters_table, source_addr)+2),
+ readb(opt+offsetof(struct olympic_parameters_table, source_addr)+3),
+ readb(opt+offsetof(struct olympic_parameters_table, source_addr)+4),
+ readb(opt+offsetof(struct olympic_parameters_table, source_addr)+5),
+ ntohs(readw(opt+offsetof(struct olympic_parameters_table, beacon_type))),
+ ntohs(readw(opt+offsetof(struct olympic_parameters_table, major_vector))),
+ ntohs(readw(opt+offsetof(struct olympic_parameters_table, lan_status))),
+ ntohs(readw(opt+offsetof(struct olympic_parameters_table, local_ring))),
+ ntohs(readw(opt+offsetof(struct olympic_parameters_table, mon_error))),
+ ntohs(readw(opt+offsetof(struct olympic_parameters_table, frame_correl))));
+
+ size += sprintf(buffer+size, "%6s: Beacon Details : Tx : Rx : NAUN Node Address : NAUN Node Phys : \n",
+ dev->name) ;
+
+ size += sprintf(buffer+size, "%6s: : %02x : %02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x : \n",
+ dev->name,
+ ntohs(readw(opt+offsetof(struct olympic_parameters_table, beacon_transmit))),
+ ntohs(readw(opt+offsetof(struct olympic_parameters_table, beacon_receive))),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+1),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+2),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+3),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+4),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+5),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+1),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+2),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+3));
+
+
+ return size;
+}
+#endif
+#endif
+
+#ifdef MODULE
+
+static struct device* dev_olympic[OLYMPIC_MAX_ADAPTERS];
+
+int init_module(void)
+{
+ int i;
+
+#if OLYMPIC_NETWORK_MONITOR
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *ent ;
+
+ ent = create_proc_entry("net/olympic_tr",0,0);
+ ent->read_proc = &olympic_proc_info ;
+#endif
+#endif
+ for (i = 0; (i<OLYMPIC_MAX_ADAPTERS); i++) {
+ dev_olympic[i] = NULL;
+ dev_olympic[i] = init_trdev(dev_olympic[i], 0);
+ if (dev_olympic[i] == NULL)
+ return -ENOMEM;
+
+ dev_olympic[i]->init = &olympic_probe;
+
+ if (register_trdev(dev_olympic[i]) != 0) {
+ kfree_s(dev_olympic[i], sizeof(struct device));
+ dev_olympic[i] = NULL;
+ if (i == 0) {
+ printk("Olympic: No IBM PCI Token Ring cards found in system.\n");
+ return -EIO;
+ } else {
+ printk("Olympic: %d IBM PCI Token Ring card(s) found in system.\n",i) ;
+ return 0;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ int i;
+
+ for (i = 0; i < OLYMPIC_MAX_ADAPTERS; i++)
+ if (dev_olympic[i]) {
+ unregister_trdev(dev_olympic[i]);
+ release_region(dev_olympic[i]->base_addr, OLYMPIC_IO_SPACE);
+ kfree_s(dev_olympic[i]->priv, sizeof(struct olympic_private));
+ kfree_s(dev_olympic[i], sizeof(struct device));
+ dev_olympic[i] = NULL;
+ }
+
+#if OLYMPIC_NETWORK_MONITOR
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("net/olympic_tr", NULL) ;
+#endif
+#endif
+}
+#endif /* MODULE */
+
diff --git a/drivers/net/olympic.h b/drivers/net/olympic.h
new file mode 100644
index 000000000..6f98b3b82
--- /dev/null
+++ b/drivers/net/olympic.h
@@ -0,0 +1,303 @@
+/*
+ * olympic.h (c) 1999 Peter De Schrijver All Rights Reserved
+ * 1999 Mike Phillips (phillim@amtrak.com)
+ *
+ * Linux driver for IBM PCI tokenring cards based on the olympic and the PIT/PHY chipset.
+ *
+ * Base Driver Skeleton:
+ * Written 1993-94 by Donald Becker.
+ *
+ * Copyright 1993 United States Government as represented by the
+ * Director, National Security Agency.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ */
+
+#define CID 0x4e
+
+#define BCTL 0x70
+#define BCTL_SOFTRESET (1<<15)
+#define BCTL_MIMREB (1<<6)
+
+#define GPR 0x4a
+#define GPR_OPTI_BF (1<<6)
+#define GPR_NEPTUNE_BF (1<<4)
+#define GPR_AUTOSENSE (1<<2)
+#define GPR_16MBPS (1<<3)
+
+#define PAG 0x85
+#define LBC 0x8e
+
+#define LISR 0x10
+#define LISR_SUM 0x14
+#define LISR_RWM 0x18
+
+#define LISR_LIE (1<<15)
+#define LISR_SLIM (1<<13)
+#define LISR_SLI (1<<12)
+#define LISR_PCMSRMASK (1<<11)
+#define LISR_PCMSRINT (1<<10)
+#define LISR_WOLMASK (1<<9)
+#define LISR_WOL (1<<8)
+#define LISR_SRB_CMD (1<<5)
+#define LISR_ASB_REPLY (1<<4)
+#define LISR_ASB_FREE_REQ (1<<2)
+#define LISR_ARB_FREE (1<<1)
+#define LISR_TRB_FRAME (1<<0)
+
+#define SISR 0x20
+#define SISR_SUM 0x24
+#define SISR_RWM 0x28
+#define SISR_RR 0x2C
+#define SISR_RESMASK 0x30
+#define SISR_MASK 0x54
+#define SISR_MASK_SUM 0x58
+#define SISR_MASK_RWM 0x5C
+
+#define SISR_TX2_IDLE (1<<31)
+#define SISR_TX2_HALT (1<<29)
+#define SISR_TX2_EOF (1<<28)
+#define SISR_TX1_IDLE (1<<27)
+#define SISR_TX1_HALT (1<<25)
+#define SISR_TX1_EOF (1<<24)
+#define SISR_TIMEOUT (1<<23)
+#define SISR_RX_NOBUF (1<<22)
+#define SISR_RX_STATUS (1<<21)
+#define SISR_RX_HALT (1<<18)
+#define SISR_RX_EOF_EARLY (1<<16)
+#define SISR_MI (1<<15)
+#define SISR_PI (1<<13)
+#define SISR_ERR (1<<9)
+#define SISR_ADAPTER_CHECK (1<<6)
+#define SISR_SRB_REPLY (1<<5)
+#define SISR_ASB_FREE (1<<4)
+#define SISR_ARB_CMD (1<<3)
+#define SISR_TRB_REPLY (1<<2)
+
+#define EISR 0x34
+#define EISR_RWM 0x38
+#define EISR_MASK 0x3c
+
+#define LAPA 0x60
+#define LAPWWO 0x64
+#define LAPWWC 0x68
+#define LAPCTL 0x6C
+#define LAIPD 0x78
+#define LAIPDDINC 0x7C
+
+#define TIMER 0x50
+
+#define CLKCTL 0x74
+
+#define PM_CON 0x4
+
+#define BMCTL_SUM 0x40
+#define BMCTL_RWM 0x44
+#define BMCTL_TX2_DIS (1<<30)
+#define BMCTL_TX1_DIS (1<<26)
+#define BMCTL_RX_DIS (1<<22)
+
+#define BMASR 0xcc
+
+#define RXDESCQ 0x90
+#define RXDESCQCNT 0x94
+#define RXCDA 0x98
+#define RXENQ 0x9C
+#define RXSTATQ 0xA0
+#define RXSTATQCNT 0xA4
+#define RXCSA 0xA8
+#define RXCLEN 0xAC
+#define RXHLEN 0xAE
+
+#define TXDESCQ_1 0xb0
+#define TXDESCQ_2 0xd0
+#define TXDESCQCNT_1 0xb4
+#define TXDESCQCNT_2 0xd4
+#define TXCDA_1 0xb8
+#define TXCDA_2 0xd8
+#define TXENQ_1 0xbc
+#define TXENQ_2 0xdc
+#define TXSTATQ_1 0xc0
+#define TXSTATQ_2 0xe0
+#define TXSTATQCNT_1 0xc4
+#define TXSTATQCNT_2 0xe4
+#define TXCSA_1 0xc8
+#define TXCSA_2 0xe8
+
+#define OLYMPIC_IO_SPACE 256
+
+#define SRB_COMMAND_SIZE 50
+
+#define OLYMPIC_MAX_ADAPTERS 8 /* 0x08 __MODULE_STRING can't hand 0xnn */
+
+/* Defines for LAN STATUS CHANGE reports */
+#define LSC_SIG_LOSS 0x8000
+#define LSC_HARD_ERR 0x4000
+#define LSC_SOFT_ERR 0x2000
+#define LSC_TRAN_BCN 0x1000
+#define LSC_LWF 0x0800
+#define LSC_ARW 0x0400
+#define LSC_FPE 0x0200
+#define LSC_RR 0x0100
+#define LSC_CO 0x0080
+#define LSC_SS 0x0040
+#define LSC_RING_REC 0x0020
+#define LSC_SR_CO 0x0010
+#define LSC_FDX_MODE 0x0004
+
+/* Defines for OPEN ADAPTER command */
+
+#define OPEN_ADAPTER_EXT_WRAP (1<<15)
+#define OPEN_ADAPTER_DIS_HARDEE (1<<14)
+#define OPEN_ADAPTER_DIS_SOFTERR (1<<13)
+#define OPEN_ADAPTER_PASS_ADC_MAC (1<<12)
+#define OPEN_ADAPTER_PASS_ATT_MAC (1<<11)
+#define OPEN_ADAPTER_ENABLE_EC (1<<10)
+#define OPEN_ADAPTER_CONTENDER (1<<8)
+#define OPEN_ADAPTER_PASS_BEACON (1<<7)
+#define OPEN_ADAPTER_ENABLE_FDX (1<<6)
+#define OPEN_ADAPTER_ENABLE_RPL (1<<5)
+#define OPEN_ADAPTER_INHIBIT_ETR (1<<4)
+#define OPEN_ADAPTER_INTERNAL_WRAP (1<<3)
+#define OPEN_ADAPTER_USE_OPTS2 (1<<0)
+
+#define OPEN_ADAPTER_2_ENABLE_ONNOW (1<<15)
+
+/* Defines for SRB Commands */
+
+#define SRB_ACCESS_REGISTER 0x1f
+#define SRB_CLOSE_ADAPTER 0x04
+#define SRB_CONFIGURE_BRIDGE 0x0c
+#define SRB_CONFIGURE_WAKEUP_EVENT 0x1a
+#define SRB_MODIFY_BRIDGE_PARMS 0x15
+#define SRB_MODIFY_OPEN_OPTIONS 0x01
+#define SRB_MODIFY_RECEIVE_OPTIONS 0x17
+#define SRB_NO_OPERATION 0x00
+#define SRB_OPEN_ADAPTER 0x03
+#define SRB_READ_LOG 0x08
+#define SRB_READ_SR_COUNTERS 0x16
+#define SRB_RESET_GROUP_ADDRESS 0x02
+#define SRB_SAVE_CONFIGURATION 0x1b
+#define SRB_SET_BRIDGE_PARMS 0x09
+#define SRB_SET_BRIDGE_TARGETS 0x10
+#define SRB_SET_FUNC_ADDRESS 0x07
+#define SRB_SET_GROUP_ADDRESS 0x06
+#define SRB_SET_GROUP_ADDR_OPTIONS 0x11
+#define SRB_UPDATE_WAKEUP_PATTERN 0x19
+
+/* Clear return code */
+
+#define OLYMPIC_CLEAR_RET_CODE 0xfe
+
+/* ARB Commands */
+#define ARB_RECEIVE_DATA 0x81
+#define ARB_LAN_CHANGE_STATUS 0x84
+/* ASB Response commands */
+
+#define ASB_RECEIVE_DATA 0x81
+
+
+/* Olympic defaults for buffers */
+
+#define OLYMPIC_RX_RING_SIZE 16 /* should be a power of 2 */
+#define OLYMPIC_TX_RING_SIZE 8 /* should be a power of 2 */
+
+#define PKT_BUF_SZ 4096 /* Default packet size */
+
+/* Olympic data structures */
+
+struct olympic_tx_desc {
+ __u32 buffer;
+ __u32 status_length;
+};
+
+struct olympic_tx_status {
+ __u32 status;
+};
+
+struct olympic_rx_desc {
+ __u32 buffer;
+ __u32 res_length ;
+};
+
+struct olympic_rx_status {
+ __u32 fragmentcnt_framelen;
+ __u32 status_buffercnt;
+};
+
+struct mac_receive_buffer {
+ __u16 next ;
+ __u8 padding ;
+ __u8 frame_status ;
+ __u16 buffer_length ;
+ __u8 frame_data ;
+};
+
+struct olympic_private {
+
+ __u16 srb;
+ __u16 trb;
+ __u16 arb;
+ __u16 asb;
+
+ __u8 *olympic_mmio;
+ __u8 *olympic_lap;
+
+ volatile int srb_queued; /* True if an SRB is still posted */
+ wait_queue_head_t srb_wait;
+
+ volatile int asb_queued; /* True if an ASB is posted */
+
+ volatile int trb_queued; /* True if a TRB is posted */
+ wait_queue_head_t trb_wait ;
+
+ struct olympic_rx_desc olympic_rx_ring[OLYMPIC_RX_RING_SIZE];
+ struct olympic_tx_desc olympic_tx_ring[OLYMPIC_TX_RING_SIZE];
+ struct olympic_rx_status olympic_rx_status_ring[OLYMPIC_RX_RING_SIZE];
+ struct olympic_tx_status olympic_tx_status_ring[OLYMPIC_TX_RING_SIZE];
+ struct sk_buff *tx_ring_skb[OLYMPIC_TX_RING_SIZE], *rx_ring_skb[OLYMPIC_RX_RING_SIZE];
+ int tx_ring_free, tx_ring_last_status, rx_ring_last_received,rx_status_last_received, free_tx_ring_entries;
+
+ struct net_device_stats olympic_stats ;
+ __u16 olympic_lan_status ;
+ __u8 olympic_ring_speed ;
+ __u16 pkt_buf_sz ;
+ __u8 olympic_receive_options, olympic_copy_all_options, olympic_message_level;
+ __u8 olympic_multicast_set ;
+ __u16 olympic_addr_table_addr, olympic_parms_addr ;
+ __u8 olympic_laa[6] ;
+};
+
+struct olympic_adapter_addr_table {
+
+ __u8 node_addr[6] ;
+ __u8 reserved[4] ;
+ __u8 func_addr[4] ;
+} ;
+
+struct olympic_parameters_table {
+
+ __u8 phys_addr[4] ;
+ __u8 up_node_addr[6] ;
+ __u8 up_phys_addr[6] ;
+ __u8 poll_addr[6] ;
+ __u16 reserved ;
+ __u16 acc_priority ;
+ __u16 auth_source_class ;
+ __u16 att_code ;
+ __u8 source_addr[6] ;
+ __u16 beacon_type ;
+ __u16 major_vector ;
+ __u16 lan_status ;
+ __u16 soft_error_time ;
+ __u16 reserved1 ;
+ __u16 local_ring ;
+ __u16 mon_error ;
+ __u16 beacon_transmit ;
+ __u16 beacon_receive ;
+ __u16 frame_correl ;
+ __u8 beacon_naun[6] ;
+ __u32 reserved2 ;
+ __u8 beacon_phys[4] ;
+};
diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c
index ab73353ac..42514f2bd 100644
--- a/drivers/net/ppp.c
+++ b/drivers/net/ppp.c
@@ -60,7 +60,6 @@
#include <linux/malloc.h>
#include <linux/tty.h>
#include <linux/errno.h>
-#include <linux/sched.h> /* to get the struct task_struct */
#include <linux/string.h> /* used in new tty drivers */
#include <linux/signal.h> /* used in new tty drivers */
#include <asm/system.h>
diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c
index 21f69fa3b..d8a5b63b7 100644
--- a/drivers/net/rtl8139.c
+++ b/drivers/net/rtl8139.c
@@ -1,6 +1,6 @@
/* rtl8139.c: A RealTek RTL8129/8139 Fast Ethernet driver for Linux. */
/*
- Written 1997-1998 by Donald Becker.
+ Written 1997-1999 by Donald Becker.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
@@ -16,11 +16,11 @@
Support and updates available at
http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html
- Twister-tuning code contributed by Kinston <shangh@realtek.com.tw>.
+ Twister-tuning table provided by Kinston <shangh@realtek.com.tw>.
*/
static const char *version =
-"rtl8139.c:v1.04 9/22/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n";
+"rtl8139.c:v1.07 5/6/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n";
/* A few user-configurable values. */
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
@@ -178,7 +178,9 @@ static struct pci_id_info pci_tbl[] =
0x10ec, 0x8129, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
{ "RealTek RTL8139 Fast Ethernet",
0x10ec, 0x8139, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
- { "RealTek RTL8139 Fast Ethernet (mislabeled)",
+ { "SMC1211TX EZCard 10/100 (RealTek RTL8139)",
+ 0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
+ { "Accton MPX5030 (RealTek RTL8139)",
0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
{0,}, /* 0 terminated list. */
};
@@ -235,13 +237,13 @@ enum RxStatusBits {
RxBadAlign=0x0002, RxStatusOK=0x0001,
};
+/* Twister tuning parameters from RealTek.
+ Completely undocumented, but required to tune bad links. */
enum CSCRBits {
CSCR_LinkOKBit=0x0400, CSCR_LinkChangeBit=0x0800,
CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0,
CSCR_LinkDownCmd=0x0f3c0,
-};
-
-/* Twister tuning parameters from RealTek. Completely undocumented. */
+};
unsigned long param[4][4]={
{0x0cb39de43,0x0cb39ce43,0x0fb38de03,0x0cb38de43},
{0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83},
@@ -270,9 +272,10 @@ struct rtl8129_private {
unsigned char *rx_ring;
unsigned char *tx_bufs; /* Tx bounce buffer region. */
char phys[4]; /* MII device addresses. */
+ char twistie, twist_cnt; /* Twister tune state. */
unsigned int tx_full:1; /* The Tx queue is full. */
unsigned int full_duplex:1; /* Full-duplex operation requested. */
- unsigned int duplex_lock:1; /* Full-duplex operation requested. */
+ unsigned int duplex_lock:1;
unsigned int default_port:4; /* Last dev->if_port value. */
unsigned int media2:4; /* Secondary monitored media port. */
unsigned int medialock:1; /* Don't sense media type. */
@@ -325,7 +328,7 @@ int rtl8139_probe(struct device *dev)
if ( ! pcibios_present())
return -ENODEV;
- for (;pci_index < 0xff; pci_index++) {
+ for (; pci_index < 0xff; pci_index++) {
u16 vendor, device, pci_command, new_command;
int chip_idx, irq;
long ioaddr;
@@ -402,9 +405,9 @@ int rtl8139_probe(struct device *dev)
return cards_found ? 0 : -ENODEV;
}
-static struct device * rtl8129_probe1(int pci_bus, int pci_devfn,
- struct device *dev, long ioaddr,
- int irq, int chip_idx, int found_cnt)
+static struct device *rtl8129_probe1(int pci_bus, int pci_devfn,
+ struct device *dev, long ioaddr,
+ int irq, int chip_idx, int found_cnt)
{
static int did_version = 0; /* Already printed version info. */
struct rtl8129_private *tp;
@@ -470,9 +473,8 @@ static struct device * rtl8129_probe1(int pci_bus, int pci_devfn,
dev->name);
tp->phys[0] = -1;
}
- } else {
- tp->phys[0] = 32;
- }
+ } else
+ tp->phys[0] = 32;
/* Put the chip into low-power mode. */
outb(0xC0, ioaddr + Cfg9346);
@@ -601,7 +603,7 @@ static int mdio_read(struct device *dev, int phy_id, int location)
int retval = 0;
int i;
- if ((phy_id & 0x1f) == 0) { /* Really a 8139. Use internal registers. */
+ if (phy_id > 31) { /* Really a 8139. Use internal registers. */
return location < 8 && mii_2_8139_map[location] ?
inw(dev->base_addr + mii_2_8139_map[location]) : 0;
}
@@ -633,7 +635,7 @@ static void mdio_write(struct device *dev, int phy_id, int location, int value)
int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
int i;
- if (phy_id == 32) { /* Really a 8139. Use internal registers. */
+ if (phy_id > 31) { /* Really a 8139. Use internal registers. */
if (location < 8 && mii_2_8139_map[location])
outw(value, dev->base_addr + mii_2_8139_map[location]);
return;
@@ -736,7 +738,7 @@ rtl8129_open(struct device *dev)
/* Enable all known interrupts by setting the interrupt mask. */
outw(PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver
- | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask);
+ | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask);
if (rtl8129_debug > 1)
printk(KERN_DEBUG"%s: rtl8129_open() ioaddr %#lx IRQ %d"
@@ -749,7 +751,7 @@ rtl8129_open(struct device *dev)
init_timer(&tp->timer);
tp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */
tp->timer.data = (unsigned long)dev;
- tp->timer.function = &rtl8129_timer; /* timer handler */
+ tp->timer.function = &rtl8129_timer;
add_timer(&tp->timer);
return 0;
@@ -760,7 +762,7 @@ static void rtl8129_timer(unsigned long data)
struct device *dev = (struct device *)data;
struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
long ioaddr = dev->base_addr;
- int next_tick = 0;
+ int next_tick = 60*HZ;
int mii_reg5 = mdio_read(dev, tp->phys[0], 5);
if (! tp->duplex_lock && mii_reg5 != 0xffff) {
@@ -774,8 +776,65 @@ static void rtl8129_timer(unsigned long data)
outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);
outb(0x00, ioaddr + Cfg9346);
}
- next_tick = 60*HZ;
}
+ /* Check for bogusness. */
+ if (inw(ioaddr + IntrStatus) & (TxOK | RxOK)) {
+ int status = inw(ioaddr + IntrStatus);
+ if (status & (TxOK | RxOK)) { /* Double check */
+ printk(KERN_ERR "%s: RTL8139 Interrupt line blocked, status %x.\n",
+ dev->name, status);
+ rtl8129_interrupt(dev->irq, dev, 0);
+ }
+ }
+ if (dev->tbusy && jiffies - dev->trans_start >= 2*TX_TIMEOUT)
+ rtl8129_tx_timeout(dev);
+
+#if 0
+ if (tp->twistie) {
+ unsigned int CSCRval = inw(ioaddr + CSCR); /* Read link status. */
+ if (tp->twistie == 1) {
+ if (CSCRval & CSCR_LinkOKBit) {
+ outw(CSCR_LinkDownOffCmd, ioaddr + CSCR);
+ tp->twistie = 2;
+ next_tick = HZ/10;
+ } else {
+ outw(CSCR_LinkDownCmd, ioaddr + CSCR);
+ outl(FIFOTMS_default,ioaddr + FIFOTMS);
+ outl(PARA78_default ,ioaddr + PARA78);
+ outl(PARA7c_default ,ioaddr + PARA7c);
+ tp->twistie = 0;
+ }
+ } else if (tp->twistie == 2) {
+ int linkcase = (CSCRval & CSCR_LinkStatusBits) >> 12;
+ int row;
+ if (linkcase >= 0x7000) row = 3;
+ else if (linkcase >= 0x3000) row = 2;
+ else if (linkcase >= 0x1000) row = 1;
+ else row = 0;
+ tp->twistie == row + 3;
+ outw(0,ioaddr+FIFOTMS);
+ outl(param[row][0], ioaddr+PARA7c);
+ tp->twist_cnt = 1;
+ } else {
+ outl(param[tp->twistie-3][tp->twist_cnt], ioaddr+PARA7c);
+ if (++tp->twist_cnt < 4) {
+ next_tick = HZ/10;
+ } else if (tp->twistie-3 == 3) {
+ if ((CSCRval & CSCR_LinkStatusBits) != 0x7000) {
+ outl(PARA7c_xxx, ioaddr+PARA7c);
+ next_tick = HZ/10; /* 100ms. */
+ outl(FIFOTMS_default, ioaddr+FIFOTMS);
+ outl(PARA78_default, ioaddr+PARA78);
+ outl(PARA7c_default, ioaddr+PARA7c);
+ tp->twistie == 3 + 3;
+ outw(0,ioaddr+FIFOTMS);
+ outl(param[3][0], ioaddr+PARA7c);
+ tp->twist_cnt = 1;
+ }
+ }
+ }
+ }
+#endif
if (rtl8129_debug > 2) {
if (rtl_cap_tbl[tp->chip_id] & HAS_MII_XCVR)
@@ -792,10 +851,8 @@ static void rtl8129_timer(unsigned long data)
dev->name, inb(ioaddr + Config0), inb(ioaddr + Config1));
}
- if (next_tick) {
- tp->timer.expires = RUN_AT(next_tick);
- add_timer(&tp->timer);
- }
+ tp->timer.expires = RUN_AT(next_tick);
+ add_timer(&tp->timer);
}
static void rtl8129_tx_timeout(struct device *dev)
@@ -861,7 +918,7 @@ static void rtl8129_tx_timeout(struct device *dev)
}
tp->cur_tx = i;
while (i < NUM_TX_DESC)
- tp->tx_skbuff[i] = 0;
+ tp->tx_skbuff[i++] = 0;
if (tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */
dev->tbusy = 0;
tp->tx_full = 0;
@@ -906,9 +963,8 @@ rtl8129_start_xmit(struct sk_buff *skb, struct device *dev)
/* Block a timer-based transmit from overlapping. This could better be
done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- if (jiffies - dev->trans_start < TX_TIMEOUT)
- return 1;
- rtl8129_tx_timeout(dev);
+ if (jiffies - dev->trans_start >= TX_TIMEOUT)
+ rtl8129_tx_timeout(dev);
return 1;
}
@@ -925,7 +981,7 @@ rtl8129_start_xmit(struct sk_buff *skb, struct device *dev)
outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN),
ioaddr + TxStatus0 + entry*4);
- if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */
+ if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) { /* Typical path */
clear_bit(0, (void*)&dev->tbusy);
} else {
tp->tx_full = 1;
@@ -946,7 +1002,7 @@ static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
struct device *dev = (struct device *)dev_instance;
struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
int boguscnt = max_interrupt_work;
- int status;
+ int status, link_changed = 0;
long ioaddr = dev->base_addr;
#if defined(__i386__)
@@ -967,7 +1023,10 @@ static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
do {
status = inw(ioaddr + IntrStatus);
- /* Acknowledge all of the current interrupt sources ASAP. */
+ /* Acknowledge all of the current interrupt sources ASAP, but
+ an first get an additional status bit from CSCR. */
+ if ((status & RxUnderrun) && inw(ioaddr+CSCR) & CSCR_LinkChangeBit)
+ link_changed = 1;
outw(status, ioaddr + IntrStatus);
if (rtl8129_debug > 4)
@@ -982,9 +1041,9 @@ static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
rtl8129_rx(dev);
if (status & (TxOK | TxErr)) {
- unsigned int dirty_tx;
+ unsigned int dirty_tx = tp->dirty_tx;
- for (dirty_tx = tp->dirty_tx; dirty_tx < tp->cur_tx; dirty_tx++) {
+ while (tp->cur_tx - dirty_tx > 0) {
int entry = dirty_tx % NUM_TX_DESC;
int txstatus = inl(ioaddr + TxStatus0 + entry*4);
@@ -994,11 +1053,9 @@ static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
/* Note: TxCarrierLost is always asserted at 100mbps. */
if (txstatus & (TxOutOfWindow | TxAborted)) {
/* There was an major error, log it. */
-#ifndef final_version
if (rtl8129_debug > 1)
printk(KERN_NOTICE"%s: Transmit error, Tx status %8.8x.\n",
dev->name, txstatus);
-#endif
tp->stats.tx_errors++;
if (txstatus&TxAborted) {
tp->stats.tx_aborted_errors++;
@@ -1011,9 +1068,6 @@ static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
tp->stats.collisions16++;
#endif
} else {
-#ifdef ETHER_STATS
- /* No count for tp->stats.tx_deferred */
-#endif
if (txstatus & TxUnderrun) {
/* Add 64 to the Tx FIFO threshold. */
if (tp->tx_flag < 0x00300000)
@@ -1030,6 +1084,13 @@ static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
/* Free the original skb. */
dev_free_skb(tp->tx_skbuff[entry]);
tp->tx_skbuff[entry] = 0;
+ if (tp->tx_full) {
+ /* The ring is no longer full, clear tbusy. */
+ tp->tx_full = 0;
+ clear_bit(0, (void*)&dev->tbusy);
+ mark_bh(NET_BH);
+ }
+ dirty_tx++;
}
#ifndef final_version
@@ -1039,14 +1100,6 @@ static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
dirty_tx += NUM_TX_DESC;
}
#endif
-
- if (tp->tx_full && dirty_tx > tp->cur_tx - NUM_TX_DESC) {
- /* The ring is no longer full, clear tbusy. */
- tp->tx_full = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
-
tp->dirty_tx = dirty_tx;
}
@@ -1063,7 +1116,7 @@ static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
outl(0, ioaddr + RxMissed);
- if ((status & RxUnderrun) &&
+ if ((status & RxUnderrun) && link_changed &&
(rtl_cap_tbl[tp->chip_id] & HAS_LNK_CHNG)) {
/* Really link-change on new chips. */
int lpar = inw(ioaddr + NWayLPAR);
@@ -1284,12 +1337,12 @@ static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
data[0] = tp->phys[0] & 0x3f;
/* Fall Through */
case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
- data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+ data[3] = mdio_read(dev, data[0], data[1] & 0x1f);
return 0;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
- mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+ mdio_write(dev, data[0], data[1] & 0x1f, data[2]);
return 0;
default:
return -EOPNOTSUPP;
@@ -1318,7 +1371,7 @@ static inline u32 ether_crc(int length, unsigned char *data)
{
int crc = -1;
- while(--length >= 0) {
+ while (--length >= 0) {
unsigned char current_octet = *data++;
int bit;
for (bit = 0; bit < 8; bit++, current_octet >>= 1)
diff --git a/drivers/net/sealevel.c b/drivers/net/sealevel.c
new file mode 100644
index 000000000..03e90828e
--- /dev/null
+++ b/drivers/net/sealevel.c
@@ -0,0 +1,471 @@
+#define LINUX_21
+
+/*
+ * Sealevel Systems 4021 driver.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * (c) Copyright 1999 Building Number Three Ltd
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <net/arp.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+#include "syncppp.h"
+#include "z85230.h"
+
+
+struct slvl_device
+{
+ struct z8530_channel *chan;
+ struct ppp_device netdev;
+ char name[16];
+ int channel;
+};
+
+
+struct slvl_board
+{
+ struct slvl_device dev[2];
+ struct z8530_dev board;
+ int iobase;
+};
+
+/*
+ * Network driver support routines
+ */
+
+/*
+ * Frame receive. Simple for our card as we do sync ppp and there
+ * is no funny garbage involved
+ */
+
+static void sealevel_input(struct z8530_channel *c, struct sk_buff *skb)
+{
+ /* Drop the CRC - its not a good idea to try and negotiate it ;) */
+ skb_trim(skb, skb->len-2);
+ skb->protocol=htons(ETH_P_WAN_PPP);
+ skb->mac.raw=skb->data;
+ skb->dev=c->netdevice;
+ /*
+ * Send it to the PPP layer. We dont have time to process
+ * it right now.
+ */
+ netif_rx(skb);
+}
+
+/*
+ * We've been placed in the UP state
+ */
+
+static int sealevel_open(struct device *d)
+{
+ struct slvl_device *slvl=d->priv;
+ int err = -1;
+ int unit = slvl->channel;
+
+ /*
+ * Link layer up.
+ */
+
+ switch(unit)
+ {
+ case 0:
+ err=z8530_sync_dma_open(d, slvl->chan);
+ break;
+ case 1:
+ err=z8530_sync_open(d, slvl->chan);
+ break;
+ }
+
+ if(err)
+ return err;
+ /*
+ * Begin PPP
+ */
+ err=sppp_open(d);
+ if(err)
+ {
+ switch(unit)
+ {
+ case 0:
+ z8530_sync_dma_close(d, slvl->chan);
+ break;
+ case 1:
+ z8530_sync_close(d, slvl->chan);
+ break;
+ }
+ return err;
+ }
+
+ slvl->chan->rx_function=sealevel_input;
+
+ /*
+ * Go go go
+ */
+ d->tbusy=0;
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int sealevel_close(struct device *d)
+{
+ struct slvl_device *slvl=d->priv;
+ int unit = slvl->channel;
+
+ /*
+ * Discard new frames
+ */
+
+ slvl->chan->rx_function=z8530_null_rx;
+
+ /*
+ * PPP off
+ */
+ sppp_close(d);
+ /*
+ * Link layer down
+ */
+ d->tbusy=1;
+
+ switch(unit)
+ {
+ case 0:
+ z8530_sync_dma_close(d, slvl->chan);
+ break;
+ case 1:
+ z8530_sync_close(d, slvl->chan);
+ break;
+ }
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static int sealevel_ioctl(struct device *d, struct ifreq *ifr, int cmd)
+{
+ /* struct slvl_device *slvl=d->priv;
+ z8530_ioctl(d,&slvl->sync.chanA,ifr,cmd) */
+ return sppp_do_ioctl(d, ifr,cmd);
+}
+
+static struct enet_statistics *sealevel_get_stats(struct device *d)
+{
+ struct slvl_device *slvl=d->priv;
+ if(slvl)
+ return z8530_get_stats(slvl->chan);
+ else
+ return NULL;
+}
+
+/*
+ * Passed PPP frames, fire them downwind.
+ */
+
+static int sealevel_queue_xmit(struct sk_buff *skb, struct device *d)
+{
+ struct slvl_device *slvl=d->priv;
+ return z8530_queue_xmit(slvl->chan, skb);
+}
+
+#ifdef LINUX_21
+static int sealevel_neigh_setup(struct neighbour *n)
+{
+ if (n->nud_state == NUD_NONE) {
+ n->ops = &arp_broken_ops;
+ n->output = n->ops->output;
+ }
+ return 0;
+}
+
+static int sealevel_neigh_setup_dev(struct device *dev, struct neigh_parms *p)
+{
+ if (p->tbl->family == AF_INET) {
+ p->neigh_setup = sealevel_neigh_setup;
+ p->ucast_probes = 0;
+ p->mcast_probes = 0;
+ }
+ return 0;
+}
+
+#else
+
+static int return_0(struct device *d)
+{
+ return 0;
+}
+
+#endif
+
+/*
+ * Description block for a Comtrol Hostess SV11 card
+ */
+
+static struct slvl_board *slvl_init(int iobase, int irq, int txdma, int rxdma, int slow)
+{
+ struct z8530_dev *dev;
+ struct slvl_device *sv;
+ struct slvl_board *b;
+
+ int i;
+ unsigned long flags;
+ int u;
+
+ /*
+ * Get the needed I/O space
+ */
+
+ if(check_region(iobase, 8))
+ {
+ printk(KERN_WARNING "sealevel: I/O 0x%X already in use.\n", iobase);
+ return NULL;
+ }
+ request_region(iobase, 8, "Sealevel 4021");
+
+ b=(struct slvl_board *)kmalloc(sizeof(struct slvl_board), GFP_KERNEL);
+ if(!b)
+ goto fail3;
+
+ memset(b, 0, sizeof(*sv));
+
+ b->dev[0].chan = &b->board.chanA;
+ b->dev[1].chan = &b->board.chanB;
+
+ dev=&b->board;
+
+ /*
+ * Stuff in the I/O addressing
+ */
+
+ dev->active = 0;
+
+ b->iobase = iobase;
+
+ /*
+ * Select 8530 delays for the old board
+ */
+
+ if(slow)
+ iobase |= Z8530_PORT_SLEEP;
+
+ dev->chanA.ctrlio=iobase+1;
+ dev->chanA.dataio=iobase;
+ dev->chanB.ctrlio=iobase+3;
+ dev->chanB.dataio=iobase+2;
+
+ dev->chanA.irqs=&z8530_nop;
+ dev->chanB.irqs=&z8530_nop;
+
+ /*
+ * Assert DTR enable DMA
+ */
+
+ outb(3|(1<<7), b->iobase+4);
+
+
+ /* We want a fast IRQ for this device. Actually we'd like an even faster
+ IRQ ;) - This is one driver RtLinux is made for */
+
+ if(request_irq(irq, &z8530_interrupt, SA_INTERRUPT, "SeaLevel", dev)<0)
+ {
+ printk(KERN_WARNING "sealevel: IRQ %d already in use.\n", irq);
+ goto fail2;
+ }
+
+ dev->irq=irq;
+ dev->chanA.private=&b->dev[0];
+ dev->chanB.private=&b->dev[1];
+ dev->chanA.netdevice=&b->dev[0].netdev.dev;
+ dev->chanB.netdevice=&b->dev[1].netdev.dev;
+ dev->chanA.dev=dev;
+ dev->chanB.dev=dev;
+ dev->name=b->dev[0].name;
+
+ dev->chanA.txdma=3;
+ dev->chanA.rxdma=1;
+ if(request_dma(dev->chanA.txdma, "SeaLevel (TX)")!=0)
+ goto fail;
+
+ if(request_dma(dev->chanA.rxdma, "SeaLevel (RX)")!=0)
+ goto dmafail;
+
+ save_flags(flags);
+ cli();
+
+ /*
+ * Begin normal initialise
+ */
+
+ if(z8530_init(dev)!=0)
+ {
+ printk(KERN_ERR "Z8530 series device not found.\n");
+ goto dmafail2;
+ }
+ if(dev->type==Z85C30)
+ {
+ z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream);
+ z8530_channel_load(&dev->chanB, z8530_hdlc_kilostream);
+ }
+ else
+ {
+ z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream_85230);
+ z8530_channel_load(&dev->chanB, z8530_hdlc_kilostream_85230);
+ }
+
+ /*
+ * Now we can take the IRQ
+ */
+
+ restore_flags(flags);
+
+ for(u=0; u<2; u++)
+ {
+ sv=&b->dev[u];
+ sv->channel = u;
+
+ for(i=0;i<999;i++)
+ {
+ sprintf(sv->name,"hdlc%d", i);
+ if(dev_get(sv->name)==NULL)
+ {
+ struct device *d=sv->chan->netdevice;
+
+ /*
+ * Initialise the PPP components
+ */
+ sppp_attach(&sv->netdev);
+
+ /*
+ * Local fields
+ */
+ sprintf(sv->name,"hdlc%d", i);
+
+ d->name = sv->name;
+ d->base_addr = iobase;
+ d->irq = irq;
+ d->priv = sv;
+ d->init = NULL;
+
+ d->open = sealevel_open;
+ d->stop = sealevel_close;
+ d->hard_start_xmit = sealevel_queue_xmit;
+ d->get_stats = sealevel_get_stats;
+ d->set_multicast_list = NULL;
+ d->do_ioctl = sealevel_ioctl;
+#ifdef LINUX_21
+ d->neigh_setup = sealevel_neigh_setup_dev;
+ dev_init_buffers(d);
+#else
+ d->init = return_0;
+#endif
+ d->set_mac_address = NULL;
+
+ if(register_netdev(d)==-1)
+ {
+ printk(KERN_ERR "%s: unable to register device.\n",
+ sv->name);
+ goto fail_unit;
+ }
+
+ break;
+ }
+ }
+ }
+ z8530_describe(dev, "I/O", iobase);
+ dev->active=1;
+ return b;
+
+fail_unit:
+ if(u==1)
+ unregister_netdev(b->dev[0].chan->netdevice);
+
+dmafail2:
+ free_dma(dev->chanA.rxdma);
+dmafail:
+ free_dma(dev->chanA.txdma);
+fail:
+ free_irq(irq, dev);
+fail2:
+ kfree(b);
+fail3:
+ release_region(iobase,8);
+ return NULL;
+}
+
+static void slvl_shutdown(struct slvl_board *b)
+{
+ int u;
+
+ z8530_shutdown(&b->board);
+
+ for(u=0; u<2; u++)
+ {
+ sppp_detach(&b->dev[u].netdev.dev);
+ unregister_netdev(&b->dev[u].netdev.dev);
+ }
+
+ free_irq(b->board.irq, &b->board);
+ free_dma(b->board.chanA.rxdma);
+ free_dma(b->board.chanA.txdma);
+ /* DMA off on the card, drop DTR */
+ outb(0, b->iobase);
+ release_region(b->iobase, 8);
+}
+
+#ifdef MODULE
+
+static int io=0x238;
+static int txdma=1;
+static int rxdma=3;
+static int irq=5;
+static int slow=0;
+
+#ifdef LINUX_21
+MODULE_PARM(io,"i");
+MODULE_PARM_DESC(io, "The I/O base of the Sealevel card");
+MODULE_PARM(txdma,"i");
+MODULE_PARM_DESC(txdma, "Transmit DMA channel");
+MODULE_PARM(rxdma,"i");
+MODULE_PARM_DESC(rxdma, "Receive DMA channel");
+MODULE_PARM(irq,"i");
+MODULE_PARM_DESC(irq, "The interrupt line setting for the SeaLevel card");
+MODULE_PARM(slow,"i");
+MODULE_PARM_DESC(slow, "Set this for an older Sealevel card such as the 4012");
+
+MODULE_AUTHOR("Bulding Number Three Ltd");
+MODULE_DESCRIPTION("Modular driver for the SeaLevel 4021");
+#endif
+
+static struct slvl_board *slvl_unit;
+
+int init_module(void)
+{
+ printk(KERN_INFO "SeaLevel Z85230 Synchronous Driver v 0.01.\n");
+ printk(KERN_INFO "(c) Copyright 1998, Building Number Three Ltd.\n");
+ if((slvl_unit=slvl_init(io,irq, txdma, rxdma, slow))==NULL)
+ return -ENODEV;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ if(slvl_unit)
+ slvl_shutdown(slvl_unit);
+}
+
+#endif
+
diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c
index c01c31d5b..ee8104b6e 100644
--- a/drivers/net/seeq8005.c
+++ b/drivers/net/seeq8005.c
@@ -108,8 +108,8 @@ static inline void wait_for_buffer(struct device *dev);
struct netdev_entry seeq8005_drv =
{"seeq8005", seeq8005_probe1, SEEQ8005_IO_EXTENT, seeq8005_portlist};
#else
-__initfunc(int
-seeq8005_probe(struct device *dev))
+int __init
+seeq8005_probe(struct device *dev)
{
int i;
int base_addr = dev ? dev->base_addr : 0;
@@ -135,7 +135,7 @@ seeq8005_probe(struct device *dev))
probes on the ISA bus. A good device probes avoids doing writes, and
verifies that the correct device exists and functions. */
-__initfunc(static int seeq8005_probe1(struct device *dev, int ioaddr))
+static int __init seeq8005_probe1(struct device *dev, int ioaddr)
{
static unsigned version_printed = 0;
int i,j;
@@ -736,6 +736,54 @@ inline void wait_for_buffer(struct device * dev)
outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
}
+#ifdef MODULE
+
+static char devicename[9] = { 0, };
+
+static struct device dev_seeq =
+{
+ devicename, /* device name is inserted by linux/drivers/net/net_init.c */
+ 0, 0, 0, 0,
+ 0x300, 5,
+ 0, 0, 0, NULL, seeq8005_probe
+};
+
+static int io=0x320;
+static int irq=10;
+MODULE_PARM(io, "i");
+MODULE_PARM(irq, "i");
+
+int init_module(void)
+{
+ dev_seeq.irq=irq;
+ dev_seeq.base_addr=io;
+ if (register_netdev(&dev_seeq) != 0)
+ return -EIO;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ /*
+ * No need to check MOD_IN_USE, as sys_delete_module() checks.
+ */
+
+ unregister_netdev(&dev_seeq);
+
+ /*
+ * Free up the private structure, or leak memory :-)
+ */
+
+ kfree(dev_seeq.priv);
+ dev_seeq.priv = NULL; /* gets re-allocated by el1_probe1 */
+
+ /*
+ * If we don't do this, we can't re-insmod it later.
+ */
+ release_region(dev_seeq.base_addr, EL1_IO_EXTENT);
+}
+
+#endif /* MODULE */
/*
* Local variables:
diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c
index 118a0e1ec..690c75e84 100644
--- a/drivers/net/slhc.c
+++ b/drivers/net/slhc.c
@@ -77,7 +77,6 @@
#include <linux/timer.h>
#include <asm/system.h>
#include <asm/uaccess.h>
-#include <linux/mm.h>
#include <linux/init.h>
#include <net/checksum.h>
#include <net/slhc_vj.h>
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 772f50649..b9f773e5d 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -32,7 +32,6 @@ static char *version =
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/auxio.h>
-#include <asm/system.h>
#include <asm/pgtable.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 1cc57315b..86ce45951 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -3406,7 +3406,7 @@ static int __init happy_meal_pci_init(struct device *dev, struct pci_dev *pdev)
/* Set the latency timer and cache line size as well,
* PROM leaves it at zero.
*/
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
#ifdef __sparc_v9__
/* NOTE: Cache line size is in 32-bit word units. */
pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x10);
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 3485a2a84..0d5311080 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -108,7 +108,6 @@ static char *lancedma = "LANCE DMA";
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-#include <asm/idprom.h>
#include <asm/machines.h>
/* Define: 2^4 Tx buffers and 2^4 Rx buffers */
diff --git a/drivers/net/tulip.c b/drivers/net/tulip.c
index 555776826..c8c329731 100644
--- a/drivers/net/tulip.c
+++ b/drivers/net/tulip.c
@@ -327,6 +327,10 @@ enum status_bits {
TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,
};
+enum desc_status_bits {
+ DescOwned=0x80000000, RxDescFatalErr=0x8000, RxWholePkt=0x0300,
+};
+
/* The Tulip Rx and Tx buffer descriptors. */
struct tulip_rx_desc {
s32 status;
@@ -469,10 +473,12 @@ int tulip_probe(struct device *dev)
(PCI_CLASS_NETWORK_ETHERNET << 8,
reverse_probe ? 0xfe - pci_index : pci_index,
&pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL)
+ {
if (reverse_probe)
continue;
else
break;
+ }
pcibios_read_config_word(pci_bus, pci_device_fn,
PCI_VENDOR_ID, &vendor);
pcibios_read_config_word(pci_bus, pci_device_fn,
@@ -1536,10 +1542,12 @@ static void select_media(struct device *dev, int startup)
outl(dev->if_port ? 0x0000000C : 0x00000004, ioaddr + CSR13);
} else { /* Unknown chip type with no media table. */
if (tp->default_port == 0)
- if (tp->mii_cnt) {
+ {
+ if (tp->mii_cnt)
dev->if_port = 11;
- } else
+ else
dev->if_port = 3;
+ }
if (media_cap[dev->if_port] & MediaIsMII) {
new_csr6 = 0x020E0000;
} else if (media_cap[dev->if_port] & MediaIsFx) {
@@ -2698,8 +2706,8 @@ static void set_rx_mode(struct device *dev, int num_addrs, void *addrs)
/* Same setup recently queued, we need not add it. */
} else {
unsigned long flags;
- unsigned int entry;
-
+ unsigned int entry, dummy = 0;
+
save_flags(flags); cli();
entry = tp->cur_tx++ % TX_RING_SIZE;
@@ -2709,7 +2717,8 @@ static void set_rx_mode(struct device *dev, int num_addrs, void *addrs)
tp->tx_ring[entry].length =
(entry == TX_RING_SIZE-1) ? 0x02000000 : 0;
tp->tx_ring[entry].buffer1 = 0;
- tp->tx_ring[entry].status = 0x80000000;
+ /* race with chip, set DescOwned later */
+ dummy = entry;
entry = tp->cur_tx++ % TX_RING_SIZE;
}
@@ -2724,6 +2733,8 @@ static void set_rx_mode(struct device *dev, int num_addrs, void *addrs)
dev->tbusy = 1;
tp->tx_full = 1;
}
+ if (dummy >= 0)
+ tp->tx_ring[dummy].status = DescOwned;
restore_flags(flags);
/* Trigger an immediate transmit demand. */
outl(0, ioaddr + CSR1);
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 3b22143ea..be7646b65 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -1,6 +1,6 @@
/* via-rhine.c: A Linux Ethernet device driver for VIA Rhine family chips. */
/*
- Written 1998 by Donald Becker.
+ Written 1998-1999 by Donald Becker.
This software may be used and distributed according to the terms
of the GNU Public License (GPL), incorporated herein by reference.
@@ -20,7 +20,7 @@
*/
static const char *versionA =
-"via-rhine.c:v1.00 9/5/98 Written by Donald Becker\n";
+"via-rhine.c:v1.01 2/27/99 Written by Donald Becker\n";
static const char *versionB =
" http://cesdis.gsfc.nasa.gov/linux/drivers/via-rhine.html\n";
@@ -81,9 +81,11 @@ static const int multicast_filter_limit = 32;
#include <asm/bitops.h>
#include <asm/io.h>
-/* This driver was written to use PCI memory space, however some boards
- only work with I/O space accesses. */
+/* This driver was written to use PCI memory space, however some x86
+ motherboards only configure I/O space accesses correctly. */
+#if defined(__i386__) && !defined(VIA_USE_MEMORY)
#define VIA_USE_IO
+#endif
#ifdef VIA_USE_IO
#undef readb
#undef readw
@@ -105,6 +107,7 @@ static const int multicast_filter_limit = 32;
#define RUN_AT(x) (jiffies + (x))
#if (LINUX_VERSION_CODE >= 0x20100)
+char kernel_version[] = UTS_RELEASE;
#else
#ifndef __alpha__
#define ioremap vremap
@@ -502,6 +505,7 @@ static int pci_etherdev_probe(struct device *dev, struct pci_id_info pci_tbl[])
#ifndef MODULE
int via_rhine_probe(struct device *dev)
{
+ printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
return pci_etherdev_probe(dev, pci_tbl);
}
#endif
@@ -510,13 +514,9 @@ static struct device *via_probe1(int pci_bus, int pci_devfn,
struct device *dev, long ioaddr, int irq,
int chip_id, int card_idx)
{
- static int did_version = 0; /* Already printed version info */
struct netdev_private *np;
int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0;
- if (debug > 0 && did_version++ == 0)
- printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
-
dev = init_etherdev(dev, 0);
printk(KERN_INFO "%s: %s at 0x%lx, ",
@@ -685,6 +685,8 @@ static int netdev_open(struct device *dev)
ioaddr + IntrEnable);
np->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll;
+ if (np->duplex_lock)
+ np->chip_cmd |= CmdFDuplex;
writew(np->chip_cmd, ioaddr + ChipCmd);
check_duplex(dev);
@@ -1053,7 +1055,6 @@ static int netdev_rx(struct device *dev)
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->last_rx = jiffies;
- np->stats.rx_bytes += pkt_len;
np->stats.rx_packets++;
}
entry = (++np->cur_rx) % RX_RING_SIZE;
@@ -1182,7 +1183,7 @@ static void set_rx_mode(struct device *dev)
}
writel(mc_filter[0], ioaddr + MulticastFilter0);
writel(mc_filter[1], ioaddr + MulticastFilter1);
- rx_mode = 0x0C;
+ rx_mode = 0x08;
}
writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig);
}
diff --git a/drivers/net/wavelan.c b/drivers/net/wavelan.c
index e175eb0e6..22caf3a71 100644
--- a/drivers/net/wavelan.c
+++ b/drivers/net/wavelan.c
@@ -64,8 +64,8 @@ wv_irq_to_psa(int irq)
/*
* Translate PSA irq parameter to irq number
*/
-__initfunc(static int
-wv_psa_to_irq(u_char irqval))
+static int __init
+wv_psa_to_irq(u_char irqval)
{
int irq;
@@ -2087,12 +2087,6 @@ wavelan_ioctl(struct device * dev, /* device on which the ioctl is applied */
{
struct iw_range range;
- /* Verify the user buffer. */
- ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
- sizeof(struct iw_range));
- if(ret)
- break;
-
/* Set the length (useless: it's constant). */
wrq->u.data.length = sizeof(struct iw_range);
@@ -2118,8 +2112,8 @@ wavelan_ioctl(struct device * dev, /* device on which the ioctl is applied */
range.max_qual.noise = MMR_SILENCE_LVL;
/* Copy structure to the user buffer. */
- copy_to_user(wrq->u.data.pointer, &range,
- sizeof(struct iw_range));
+ if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range)))
+ ret = -EFAULT;
}
break;
@@ -2136,18 +2130,12 @@ wavelan_ioctl(struct device * dev, /* device on which the ioctl is applied */
{ SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16, "gethisto" },
};
- /* Verify the user buffer. */
- ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
- sizeof(priv));
- if(ret)
- break;
-
/* Set the number of available ioctls. */
wrq->u.data.length = 4;
/* Copy structure to the user buffer. */
- copy_to_user(wrq->u.data.pointer, (u_char *) priv,
- sizeof(priv));
+ if (copy_to_user(wrq->u.data.pointer, (u_char *) priv, sizeof(priv)))
+ ret = -EFAULT;
}
break;
@@ -2169,14 +2157,11 @@ wavelan_ioctl(struct device * dev, /* device on which the ioctl is applied */
struct sockaddr address[IW_MAX_SPY];
int i;
- /* Verify where the user has set his addresses. */
- ret = verify_area(VERIFY_READ, wrq->u.data.pointer,
- sizeof(struct sockaddr) * lp->spy_number);
- if(ret)
- break;
/* Copy addresses to the driver. */
- copy_from_user(address, wrq->u.data.pointer,
- sizeof(struct sockaddr) * lp->spy_number);
+ if (copy_from_user(address, wrq->u.data.pointer, sizeof(struct sockaddr) * lp->spy_number)) {
+ ret = -EFAULT;
+ break;
+ }
/* Copy addresses to the lp structure. */
for(i = 0; i < lp->spy_number; i++)
@@ -2215,13 +2200,6 @@ wavelan_ioctl(struct device * dev, /* device on which the ioctl is applied */
struct sockaddr address[IW_MAX_SPY];
int i;
- /* Verify the user buffer. */
- ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
- (sizeof(iw_qual) + sizeof(struct sockaddr))
- * IW_MAX_SPY);
- if(ret)
- break;
-
/* Copy addresses from the lp structure. */
for(i = 0; i < lp->spy_number; i++)
{
@@ -2231,13 +2209,18 @@ wavelan_ioctl(struct device * dev, /* device on which the ioctl is applied */
}
/* Copy addresses to the user buffer. */
- copy_to_user(wrq->u.data.pointer, address,
- sizeof(struct sockaddr) * lp->spy_number);
-
+ if (copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * lp->spy_number)) {
+ ret = -EFAULT;
+ break;
+ }
+
/* Copy stats to the user buffer (just after). */
- copy_to_user(wrq->u.data.pointer +
+ if (copy_to_user(wrq->u.data.pointer +
(sizeof(struct sockaddr) * lp->spy_number),
- lp->spy_stat, sizeof(iw_qual) * lp->spy_number);
+ lp->spy_stat, sizeof(iw_qual) * lp->spy_number)) {
+ ret = -EFAULT;
+ break;
+ }
/* Reset updated flags. */
for(i = 0; i < lp->spy_number; i++)
@@ -2283,14 +2266,11 @@ wavelan_ioctl(struct device * dev, /* device on which the ioctl is applied */
/* Are there addresses to copy? */
if(lp->his_number > 0)
{
- /* Verify where the user has set his addresses. */
- ret = verify_area(VERIFY_READ, wrq->u.data.pointer,
- sizeof(char) * lp->his_number);
- if(ret)
- break;
/* Copy interval ranges to the driver */
- copy_from_user(lp->his_range, wrq->u.data.pointer,
- sizeof(char) * lp->his_number);
+ if (copy_from_user(lp->his_range, wrq->u.data.pointer, sizeof(char) * lp->his_number)) {
+ ret = -EFAULT;
+ break;
+ }
/* Reset structure. */
memset(lp->his_sum, 0x00, sizeof(long) * 16);
@@ -2304,15 +2284,10 @@ wavelan_ioctl(struct device * dev, /* device on which the ioctl is applied */
/* Give back the distribution statistics */
if((lp->his_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
{
- /* Verify the user buffer. */
- ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
- sizeof(long) * 16);
- if(ret)
- break;
-
/* Copy data to the user buffer. */
- copy_to_user(wrq->u.data.pointer, lp->his_sum,
- sizeof(long) * lp->his_number);
+ if (copy_to_user(wrq->u.data.pointer, lp->his_sum, sizeof(long) * lp->his_number))
+ ret = -EFAULT;
+
} /* if(pointer != NULL) */
break;
#endif /* HISTOGRAM */
@@ -4015,8 +3990,8 @@ wavelan_close(device * dev)
* device structure
* (called by wavelan_probe() and via init_module()).
*/
-__initfunc(static int
-wavelan_config(device * dev))
+static int __init
+wavelan_config(device * dev)
{
u_long ioaddr = dev->base_addr;
u_char irq_mask;
@@ -4132,8 +4107,8 @@ wavelan_config(device * dev))
* We follow the example in drivers/net/ne.c.
* (called in "Space.c")
*/
-__initfunc(int
-wavelan_probe(device * dev))
+int __init
+wavelan_probe(device * dev)
{
short base_addr;
mac_addr mac; /* MAC address (check existence of WaveLAN) */
@@ -4265,6 +4240,11 @@ init_module(void)
/* Create device and set basic arguments. */
dev = kmalloc(sizeof(struct device), GFP_KERNEL);
+ if(dev==NULL)
+ {
+ ret = -ENOMEM;
+ break;
+ }
memset(dev, 0x00, sizeof(struct device));
dev->name = name[i];
dev->base_addr = io[i];
diff --git a/drivers/net/z85230.c b/drivers/net/z85230.c
index 889a82d90..9fea5980d 100644
--- a/drivers/net/z85230.c
+++ b/drivers/net/z85230.c
@@ -23,7 +23,8 @@
* Z85230:
* Non DMA you want a 486DX50 or better to do 64Kbits. 9600 baud
* X.25 is not unrealistic on all machines. DMA mode can in theory
- * handle T1/E1 quite nicely.
+ * handle T1/E1 quite nicely. In practice the limit seems to be about
+ * 512Kbit->1Mbit depending on motherboard.
*
* Z85C30:
* 64K will take DMA, 9600 baud X.25 should be ok.
@@ -187,7 +188,6 @@ u8 z8530_hdlc_kilostream_85230[]=
1, EXT_INT_ENAB|TxINT_ENAB|INT_ALL_Rx,
9, NV|MIE|NORESET,
23, 3, /* Extended mode AUTO TX and EOM*/
- 31, 3, /* Extended mode AUTO TX and EOM*/
255
};
@@ -834,6 +834,8 @@ EXPORT_SYMBOL(z8530_sync_dma_close);
int z8530_sync_txdma_open(struct device *dev, struct z8530_channel *c)
{
+ unsigned long flags;
+
printk("Opening sync interface for TX-DMA\n");
c->sync = 1;
c->mtu = dev->mtu+64;
@@ -889,14 +891,21 @@ int z8530_sync_txdma_open(struct device *dev, struct z8530_channel *c)
c->regs[R14]|= DTRREQ;
write_zsreg(c, R14, c->regs[R14]);
+ c->regs[R1]&= ~TxINT_ENAB;
+ write_zsreg(c, R1, c->regs[R1]);
+
/*
* Set up the DMA configuration
*/
+ flags = claim_dma_lock();
+
disable_dma(c->txdma);
clear_dma_ff(c->txdma);
set_dma_mode(c->txdma, DMA_MODE_WRITE);
disable_dma(c->txdma);
+
+ release_dma_lock(flags);
/*
* Select the DMA interrupt handlers
@@ -918,6 +927,7 @@ EXPORT_SYMBOL(z8530_sync_txdma_open);
int z8530_sync_txdma_close(struct device *dev, struct z8530_channel *c)
{
+ unsigned long flags;
u8 chk;
c->irqs = &z8530_nop;
c->max = 0;
@@ -927,11 +937,15 @@ int z8530_sync_txdma_close(struct device *dev, struct z8530_channel *c)
* Disable the PC DMA channels
*/
+ flags = claim_dma_lock();
+
disable_dma(c->txdma);
clear_dma_ff(c->txdma);
c->txdma_on = 0;
c->tx_dma_used = 0;
+ release_dma_lock(flags);
+
/*
* Disable DMA control mode
*/
diff --git a/drivers/net/zlib.c b/drivers/net/zlib.c
index e8db586d8..6595b3e41 100644
--- a/drivers/net/zlib.c
+++ b/drivers/net/zlib.c
@@ -5113,10 +5113,6 @@ z_streamp z;
/* From: zutil.c,v 1.17 1996/07/24 13:41:12 me Exp $ */
-#ifdef DEBUG_ZLIB
-#include <stdio.h>
-#endif
-
/* #include "zutil.h" */
#ifndef NO_DUMMY_DECL