summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/7990.c96
-rw-r--r--drivers/net/7990.h5
-rw-r--r--drivers/net/8390.c4
-rw-r--r--drivers/net/8390.h5
-rw-r--r--drivers/net/Config.in2
-rw-r--r--drivers/net/Makefile2
-rw-r--r--drivers/net/Space.c8
-rw-r--r--drivers/net/acenic.c2
-rw-r--r--drivers/net/ariadne2.c115
-rw-r--r--drivers/net/hamradio/6pack.c594
-rw-r--r--drivers/net/hamradio/6pack.h136
-rw-r--r--drivers/net/hamradio/Makefile2
-rw-r--r--drivers/net/hamradio/mkiss.c3
-rw-r--r--drivers/net/hamradio/pi2.c1677
-rw-r--r--drivers/net/hamradio/pt.c1777
-rw-r--r--drivers/net/hamradio/scc.c121
-rw-r--r--drivers/net/hydra.c788
-rw-r--r--drivers/net/ioc3-eth.c1
-rw-r--r--drivers/net/irda/toshoboe.c2
-rw-r--r--drivers/net/mvme147.c5
-rw-r--r--drivers/net/ne.c2
-rw-r--r--drivers/net/pcmcia/wavelan_cs.c8
-rw-r--r--drivers/net/rcpci45.c2
-rw-r--r--drivers/net/setup.c12
-rw-r--r--drivers/net/tulip/media.c18
-rw-r--r--drivers/net/tulip/tulip_core.c45
26 files changed, 700 insertions, 4732 deletions
diff --git a/drivers/net/7990.c b/drivers/net/7990.c
index 118f92af3..1c53a8a4c 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/7990.c
@@ -100,7 +100,6 @@ static void load_csrs (struct lance_private *lp)
/* #define to 0 or 1 appropriately */
#define DEBUG_IRING 0
/* Set up the Lance Rx and Tx rings and the init block */
-/* Sets dev->tbusy */
static void lance_init_ring (struct net_device *dev)
{
struct lance_private *lp = (struct lance_private *) dev->priv;
@@ -111,8 +110,6 @@ static void lance_init_ring (struct net_device *dev)
aib = lp->lance_init_block;
- /* Lock out other processes while setting up hardware */
- dev->tbusy = 1;
lp->rx_new = lp->tx_new = 0;
lp->rx_old = lp->tx_old = 0;
@@ -143,6 +140,7 @@ static void lance_init_ring (struct net_device *dev)
if (DEBUG_IRING)
printk ("TX rings:\n");
+ lp->tx_full = 0;
/* Setup the Tx ring entries */
for (i = 0; i < (1<<lp->lance_log_tx_bufs); i++) {
leptr = LANCE_ADDR(&aib->tx_buf[i][0]);
@@ -232,9 +230,6 @@ static int lance_reset (struct net_device *dev)
load_csrs (lp);
lance_init_ring (dev);
dev->trans_start = jiffies;
- dev->interrupt = 0;
- dev->start = 1;
- dev->tbusy = 0;
status = init_restart_lance (lp);
#ifdef DEBUG_DRIVER
printk ("Lance restart=%d\n", status);
@@ -409,19 +404,18 @@ static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
struct lance_private *lp = (struct lance_private *)dev->priv;
int csr0;
DECLARE_LL;
-
+
+ spin_lock (&lp->devlock);
+
WRITERAP(LE_CSR0); /* LANCE Controller Status */
csr0 = READRDP();
PRINT_RINGS();
- if (!(csr0 & LE_C0_INTR)) /* Check if any interrupt has */
+ if (!(csr0 & LE_C0_INTR)) { /* Check if any interrupt has */
+ spin_lock (&lp->devlock);
return; /* been generated by the Lance. */
-
- if (dev->interrupt)
- printk ("%s: again", dev->name);
-
- dev->interrupt = 1;
+ }
/* Acknowledge all the interrupt sources ASAP */
WRITERDP(csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|LE_C0_INIT));
@@ -449,27 +443,32 @@ static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
WRITERDP(LE_C0_STRT);
}
- if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) {
- dev->tbusy = 0;
- mark_bh (NET_BH);
+ if (lp->tx_full && netif_queue_stopped(dev) && (TX_BUFFS_AVAIL >= 0)) {
+ lp->tx_full = 0;
+ netif_wake_queue (dev);
}
WRITERAP(LE_CSR0);
WRITERDP(LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|LE_C0_IDON|LE_C0_INEA);
-
- dev->interrupt = 0;
+
+ spin_unlock (&lp->devlock);
}
int lance_open (struct net_device *dev)
{
struct lance_private *lp = (struct lance_private *)dev->priv;
+ int res;
DECLARE_LL;
/* Install the Interrupt handler. Or we could shunt this out to specific drivers? */
if (request_irq(lp->irq, lance_interrupt, 0, lp->name, dev))
return -EAGAIN;
- return lance_reset(dev);
+ res = lance_reset(dev);
+ lp->devlock = SPIN_LOCK_UNLOCKED;
+ netif_start_queue (dev);
+
+ return res;
}
int lance_close (struct net_device *dev)
@@ -477,8 +476,7 @@ int lance_close (struct net_device *dev)
struct lance_private *lp = (struct lance_private *) dev->priv;
DECLARE_LL;
- dev->start = 0;
- dev->tbusy = 1;
+ netif_stop_queue (dev);
/* Stop the LANCE */
WRITERAP(LE_CSR0);
@@ -489,41 +487,30 @@ int lance_close (struct net_device *dev)
return 0;
}
+void lance_tx_timeout(struct net_device *dev)
+{
+ printk("lance_tx_timeout\n");
+ lance_reset(dev);
+ dev->trans_start = jiffies;
+ netif_start_queue (dev);
+}
+
+
int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
struct lance_private *lp = (struct lance_private *)dev->priv;
volatile struct lance_init_block *ib = lp->init_block;
int entry, skblen, len;
- int status = 0;
static int outs;
+ unsigned long flags;
DECLARE_LL;
- lance_reset(dev);
-
- /* Transmitter timeout, serious problems */
- if (dev->tbusy) {
- int tickssofar = jiffies - dev->trans_start;
-
- if (tickssofar < 100) {
- status = -1;
- } else {
- printk ("%s: transmit timed out, status %04x, resetting\n",
- dev->name, READRDP());
- lance_reset (dev);
- }
- return status;
- }
-
- /* Block a timer-based transmit from overlapping. */
- if (test_and_set_bit (0, (void *) &dev->tbusy) != 0) {
- printk ("Transmitter access conflict.\n");
+ if (!TX_BUFFS_AVAIL)
return -1;
- }
- skblen = skb->len;
+ netif_stop_queue (dev);
- if (!TX_BUFFS_AVAIL)
- return -1;
+ skblen = skb->len;
#ifdef DEBUG_DRIVER
/* dump the packet */
@@ -554,10 +541,14 @@ int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
dev_kfree_skb (skb);
+ spin_lock_irqsave (&lp->devlock, flags);
if (TX_BUFFS_AVAIL)
- dev->tbusy = 0;
+ netif_start_queue (dev);
+ else
+ lp->tx_full = 1;
+ spin_unlock_irqrestore (&lp->devlock, flags);
- return status;
+ return 0;
}
struct net_device_stats *lance_get_stats (struct net_device *dev)
@@ -623,11 +614,12 @@ void lance_set_multicast (struct net_device *dev)
{
struct lance_private *lp = (struct lance_private *) dev->priv;
volatile struct lance_init_block *ib = lp->init_block;
+ int stopped;
DECLARE_LL;
- while (dev->tbusy)
- schedule();
- set_bit (0, (void *) &dev->tbusy);
+ stopped = netif_queue_stopped(dev);
+ if (!stopped)
+ netif_stop_queue (dev);
while (lp->tx_old != lp->tx_new)
schedule();
@@ -644,6 +636,8 @@ void lance_set_multicast (struct net_device *dev)
}
load_csrs (lp);
init_restart_lance (lp);
- dev->tbusy = 0;
+
+ if (!stopped)
+ netif_start_queue (dev);
}
diff --git a/drivers/net/7990.h b/drivers/net/7990.h
index 18fb26d92..0fb2a48fa 100644
--- a/drivers/net/7990.h
+++ b/drivers/net/7990.h
@@ -127,7 +127,9 @@ struct lance_private
*/
void (*writerap)(void *, unsigned short);
void (*writerdp)(void *, unsigned short);
- unsigned short (*readrdp)(struct lance_private *);
+ unsigned short (*readrdp)(void *);
+ spinlock_t devlock;
+ char tx_full;
};
#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */
@@ -252,5 +254,6 @@ extern int lance_close (struct net_device *dev);
extern int lance_start_xmit (struct sk_buff *skb, struct net_device *dev);
extern struct net_device_stats *lance_get_stats (struct net_device *dev);
extern void lance_set_multicast (struct net_device *dev);
+extern void lance_tx_timeout(struct net_device *dev);
#endif /* ndef _7990_H */
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index a4ec3fb54..da0ffc102 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -1054,7 +1054,9 @@ void NS8390_init(struct net_device *dev, int startp)
long e8390_base = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *) dev->priv;
int i;
- int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48;
+ int endcfg = ei_local->word16
+ ? (0x48 | ENDCFG_WTS | (ei_local->bigendian ? ENDCFG_BOS : 0))
+ : 0x48;
if(sizeof(struct e8390_pkt_hdr)!=4)
panic("8390.c: header struct mispacked\n");
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index 9db9fdb3c..20f1d0111 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -67,6 +67,7 @@ struct ei_device {
unsigned char mcfilter[8];
unsigned open:1;
unsigned word16:1; /* We have the 16-bit (vs 8-bit) version of the card. */
+ unsigned bigendian:1; /* 16-bit big endian mode */
unsigned txing:1; /* Transmit Active */
unsigned irqlock:1; /* 8390's intrs disabled when '1'. */
unsigned dmaing:1; /* Remote DMA Active */
@@ -117,7 +118,8 @@ struct ei_device {
*/
#if defined(CONFIG_MAC) || defined(CONFIG_AMIGA_PCMCIA) || \
- defined(CONFIG_ARIADNE2) || defined(CONFIG_ARIADNE2_MODULE)
+ defined(CONFIG_ARIADNE2) || defined(CONFIG_ARIADNE2_MODULE) || \
+ defined(CONFIG_HYDRA) || defined(CONFIG_HYDRA_MODULE)
#define EI_SHIFT(x) (ei_local->reg_offset[x])
#else
#define EI_SHIFT(x) (x)
@@ -165,6 +167,7 @@ struct ei_device {
/* Bits in EN0_DCFG - Data config register */
#define ENDCFG_WTS 0x01 /* word transfer mode selection */
+#define ENDCFG_BOS 0x02 /* byte order selection */
/* Page 1 register offsets. */
#define EN1_PHYS EI_SHIFT(0x01) /* This board's physical enet addr RD WR */
diff --git a/drivers/net/Config.in b/drivers/net/Config.in
index 2db6d44ad..775dce51e 100644
--- a/drivers/net/Config.in
+++ b/drivers/net/Config.in
@@ -42,7 +42,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
fi
if [ "$CONFIG_ZORRO" = "y" ]; then
tristate ' Ariadne support' CONFIG_ARIADNE
- tristate ' Ariadne II support' CONFIG_ARIADNE2
+ tristate ' Ariadne II and X-Surf support' CONFIG_NE2K_ZORRO
tristate ' A2065 support' CONFIG_A2065
tristate ' Hydra support' CONFIG_HYDRA
fi
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 826ec8765..290efb51c 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -195,7 +195,7 @@ obj-$(CONFIG_ATARILANCE) += atarilance.o
obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o
obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o
obj-$(CONFIG_A2065) += a2065.o
-obj-$(CONFIG_HYDRA) += hydra.o
+obj-$(CONFIG_HYDRA) += hydra.o 8390.o
obj-$(CONFIG_ARIADNE) += ariadne.o
obj-$(CONFIG_CS89x0) += cs89x0.o
obj-$(CONFIG_MACSONIC) += macsonic.o
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index ebdcd30e8..4426e76cb 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -86,8 +86,6 @@ extern int smc_init( struct net_device * );
extern int sgiseeq_probe(struct net_device *);
extern int atarilance_probe(struct net_device *);
extern int sun3lance_probe(struct net_device *);
-extern int ariadne2_probe(struct net_device *);
-extern int hydra_probe(struct net_device *);
extern int apne_probe(struct net_device *);
extern int bionet_probe(struct net_device *);
extern int pamsnet_probe(struct net_device *);
@@ -338,12 +336,6 @@ struct devprobe m68k_probes[] __initdata = {
#ifdef CONFIG_SUN3LANCE /* sun3 onboard Lance chip */
{sun3lance_probe, 0},
#endif
-#ifdef CONFIG_ARIADNE2 /* Village Tronic Ariadne II Ethernet Board */
- {ariadne2_probe, 0},
-#endif
-#ifdef CONFIG_HYDRA /* Hydra Systems Amiganet Ethernet board */
- {hydra_probe, 0},
-#endif
#ifdef CONFIG_APNE /* A1200 PCMCIA NE2000 */
{apne_probe, 0},
#endif
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 7bd21d874..cb8adc9a3 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -3098,6 +3098,6 @@ static int __init read_eeprom_byte(struct net_device *dev,
/*
* Local variables:
- * compile-command: "gcc -D__SMP__ -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c"
+ * compile-command: "gcc -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c"
* End:
*/
diff --git a/drivers/net/ariadne2.c b/drivers/net/ariadne2.c
index 0283ff3b9..09826f0cc 100644
--- a/drivers/net/ariadne2.c
+++ b/drivers/net/ariadne2.c
@@ -1,7 +1,7 @@
/*
- * Amiga Linux/m68k Ariadne II Ethernet Driver
+ * Amiga Linux/m68k and Linux/PPC Ariadne II and X-Surf Ethernet Driver
*
- * (C) Copyright 1998 by some Elitist 680x0 Users(TM)
+ * (C) Copyright 1998-2000 by some Elitist 680x0 Users(TM)
*
* ---------------------------------------------------------------------------
*
@@ -15,8 +15,8 @@
*
* ---------------------------------------------------------------------------
*
- * The Ariadne II is a Zorro-II board made by Village Tronic. It contains a
- * Realtek RTL8019AS Ethernet Controller.
+ * The Ariadne II and X-Surf are Zorro-II boards containing Realtek RTL8019AS
+ * Ethernet Controllers.
*/
#include <linux/module.h>
@@ -38,10 +38,6 @@
#include "8390.h"
-#define ARIADNE2_BASE 0x0300
-#define ARIADNE2_BOOTROM 0xc000
-
-
#define NE_BASE (dev->base_addr)
#define NE_CMD (0x00*2)
#define NE_DATAPORT (0x10*2) /* NatSemi-defined port window offset. */
@@ -65,12 +61,24 @@
#define WORDSWAP(a) ((((a)>>8)&0xff) | ((a)<<8))
-int ariadne2_probe(struct net_device *dev);
-static int ariadne2_init(struct net_device *dev, unsigned long board);
+#ifdef MODULE
+static struct net_device *root_ariadne2_dev = NULL;
+#endif
+static const struct card_info {
+ zorro_id id;
+ const char *name;
+ unsigned int offset;
+} cards[] __initdata = {
+ { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 },
+ { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
+};
+
+static int __init ariadne2_probe(void);
+static int __init ariadne2_init(struct net_device *dev, unsigned long board,
+ const char *name, unsigned long ioaddr);
static int ariadne2_open(struct net_device *dev);
static int ariadne2_close(struct net_device *dev);
-
static void ariadne2_reset_8390(struct net_device *dev);
static void ariadne2_get_8390_hdr(struct net_device *dev,
struct e8390_pkt_hdr *hdr, int ring_page);
@@ -79,40 +87,56 @@ static void ariadne2_block_input(struct net_device *dev, int count,
static void ariadne2_block_output(struct net_device *dev, const int count,
const unsigned char *buf,
const int start_page);
+static void __exit ariadne2_cleanup(void);
-int __init ariadne2_probe(struct net_device *dev)
+static int __init ariadne2_probe(void)
{
+ struct net_device *dev;
struct zorro_dev *z = NULL;
unsigned long board, ioaddr;
- int err;
-
- SET_MODULE_OWNER(dev);
+ int err = -ENODEV;
+ int i;
- while ((z = zorro_find_device(ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, z))) {
+ while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
+ for (i = ARRAY_SIZE(cards)-1; i >= 0; i--)
+ if (z->id == cards[i].id)
+ break;
+ if (i < 0)
+ continue;
board = z->resource.start;
- ioaddr = board+ARIADNE2_BASE*2;
- if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, dev->name))
+ ioaddr = board+cards[i].offset;
+ dev = init_etherdev(0, 0);
+ SET_MODULE_OWNER(dev);
+ if (!dev)
+ return -ENOMEM;
+ if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, dev->name)) {
+ kfree(dev);
continue;
- if ((err = ariadne2_init(dev, ZTWO_VADDR(board)))) {
+ }
+ if ((err = ariadne2_init(dev, board, cards[i].name,
+ ZTWO_VADDR(ioaddr)))) {
release_mem_region(ioaddr, NE_IO_EXTENT*2);
+ kfree(dev);
return err;
}
- return 0;
+ err = 0;
}
- return -ENODEV;
+
+ if (err == -ENODEV)
+ printk("No Ariadne II or X-Surf ethernet card found.\n");
+ return err;
}
-static int __init ariadne2_init(struct net_device *dev, unsigned long board)
+static int __init ariadne2_init(struct net_device *dev, unsigned long board,
+ const char *name, unsigned long ioaddr)
{
int i;
unsigned char SA_prom[32];
- const char *name = NULL;
int start_page, stop_page;
static u32 ariadne2_offsets[16] = {
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
};
- unsigned long ioaddr = board+ARIADNE2_BASE*2;
/* Reset card. Who knows what dain-bramaged state it was left in. */
{
@@ -166,8 +190,6 @@ static int __init ariadne2_init(struct net_device *dev, unsigned long board)
start_page = NESM_START_PG;
stop_page = NESM_STOP_PG;
- name = "NE2000";
-
dev->base_addr = ioaddr;
dev->irq = IRQ_AMIGA_PORTS;
@@ -188,8 +210,8 @@ static int __init ariadne2_init(struct net_device *dev, unsigned long board)
dev->dev_addr[i] = SA_prom[i];
}
- printk("%s: AriadNE2 at 0x%08lx, Ethernet Address "
- "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, board,
+ printk("%s: %s at 0x%08lx, Ethernet Address "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, name, board,
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
@@ -207,6 +229,10 @@ static int __init ariadne2_init(struct net_device *dev, unsigned long board)
ei_status.reg_offset = ariadne2_offsets;
dev->open = &ariadne2_open;
dev->stop = &ariadne2_close;
+#ifdef MODULE
+ ei_status.priv = (unsigned long)root_ariadne2_dev;
+ root_ariadne2_dev = dev;
+#endif
NS8390_init(dev, 0);
return 0;
}
@@ -379,26 +405,21 @@ static void ariadne2_block_output(struct net_device *dev, int count,
return;
}
-#ifdef MODULE
-static struct net_device ariadne2_dev;
-
-int init_module(void)
+static void __exit ariadne2_cleanup(void)
{
- int err;
-
- ariadne2_dev.init = ariadne2_probe;
- if ((err = register_netdev(&ariadne2_dev))) {
- printk(KERN_WARNING "No AriadNE2 ethernet card found.\n");
- return err;
+#ifdef MODULE
+ struct net_device *dev, *next;
+
+ while ((dev = root_ariadne2_dev)) {
+ next = (struct net_device *)(ei_status.priv);
+ unregister_netdev(dev);
+ free_irq(IRQ_AMIGA_PORTS, dev);
+ release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT*2);
+ kfree(dev);
+ root_ariadne2_dev = next;
}
- return 0;
-}
-
-void cleanup_module(void)
-{
- free_irq(IRQ_AMIGA_PORTS, &ariadne2_dev);
- release_mem_region(ZTWO_PADDR(ariadne2_dev.base_addr), NE_IO_EXTENT*2);
- unregister_netdev(&ariadne2_dev);
+#endif
}
-#endif /* MODULE */
+module_init(ariadne2_probe);
+module_exit(ariadne2_cleanup);
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 81a1ce88f..3b416ea79 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -13,10 +13,9 @@
* Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
*
*/
-
+
#include <linux/config.h>
#include <linux/module.h>
-
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
@@ -37,24 +36,109 @@
#include <linux/init.h>
#include <linux/ip.h>
#include <linux/tcp.h>
-/*
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <unistd.h>
-*/
-
-#include "6pack.h"
-
-typedef unsigned char byte;
+#define SIXPACK_VERSION "Revision: 0.3.0"
+
+/* sixpack priority commands */
+#define SIXP_SEOF 0x40 /* start and end of a 6pack frame */
+#define SIXP_TX_URUN 0x48 /* transmit overrun */
+#define SIXP_RX_ORUN 0x50 /* receive overrun */
+#define SIXP_RX_BUF_OVL 0x58 /* receive buffer overflow */
+
+#define SIXP_CHKSUM 0xFF /* valid checksum of a 6pack frame */
+
+/* masks to get certain bits out of the status bytes sent by the TNC */
+
+#define SIXP_CMD_MASK 0xC0
+#define SIXP_CHN_MASK 0x07
+#define SIXP_PRIO_CMD_MASK 0x80
+#define SIXP_STD_CMD_MASK 0x40
+#define SIXP_PRIO_DATA_MASK 0x38
+#define SIXP_TX_MASK 0x20
+#define SIXP_RX_MASK 0x10
+#define SIXP_RX_DCD_MASK 0x18
+#define SIXP_LEDS_ON 0x78
+#define SIXP_LEDS_OFF 0x60
+#define SIXP_CON 0x08
+#define SIXP_STA 0x10
+
+#define SIXP_FOUND_TNC 0xe9
+#define SIXP_CON_ON 0x68
+#define SIXP_DCD_MASK 0x08
+#define SIXP_DAMA_OFF 0
+
+/* default level 2 parameters */
+#define SIXP_TXDELAY 25 /* in 10 ms */
+#define SIXP_PERSIST 50 /* in 256ths */
+#define SIXP_SLOTTIME 10 /* in 10 ms */
+#define SIXP_INIT_RESYNC_TIMEOUT 150 /* in 10 ms */
+#define SIXP_RESYNC_TIMEOUT 500 /* in 10 ms */
+
+/* 6pack configuration. */
+#define SIXP_NRUNIT 256 /* MAX number of 6pack channels */
+#define SIXP_MTU 256 /* Default MTU */
+
+enum sixpack_flags {
+ SIXPF_INUSE, /* Channel in use */
+ SIXPF_ERROR, /* Parity, etc. error */
+};
+
+struct sixpack {
+ int magic;
+
+ /* Various fields. */
+ struct tty_struct *tty; /* ptr to TTY structure */
+ struct net_device *dev; /* easy for intr handling */
+
+ /* These are pointers to the malloc()ed frame buffers. */
+ unsigned char *rbuff; /* receiver buffer */
+ int rcount; /* received chars counter */
+ unsigned char *xbuff; /* transmitter buffer */
+ unsigned char *xhead; /* pointer to next byte to XMIT */
+ int xleft; /* bytes left in XMIT queue */
+
+ unsigned char raw_buf[4];
+ unsigned char cooked_buf[400];
+
+ unsigned int rx_count;
+ unsigned int rx_count_cooked;
+
+ /* 6pack interface statistics. */
+ struct net_device_stats stats;
+
+ int mtu; /* Our mtu (to spot changes!) */
+ int buffsize; /* Max buffers sizes */
+
+ unsigned long flags; /* Flag values/ mode etc */
+ unsigned char mode; /* 6pack mode */
+
+ /* 6pack stuff */
+ unsigned char tx_delay;
+ unsigned char persistance;
+ unsigned char slottime;
+ unsigned char duplex;
+ unsigned char led_state;
+ unsigned char status;
+ unsigned char status1;
+ unsigned char status2;
+ unsigned char tx_enable;
+ unsigned char tnc_ok;
+
+ struct timer_list tx_t;
+ struct timer_list resync_t;
+};
+
+/* should later be moved to include/net/ax25.h */
+#define AX25_6PACK_HEADER_LEN 0
+#define SIXPACK_MAGIC 0x5304
+
+static const char banner[] __initdata = KERN_INFO "AX.25: 6pack driver, " SIXPACK_VERSION " (dynamic channels, max=%d)\n";
typedef struct sixpack_ctrl {
struct sixpack ctrl; /* 6pack things */
struct net_device dev; /* the device */
} sixpack_ctrl_t;
-static sixpack_ctrl_t **sixpack_ctrls = NULL;
+static sixpack_ctrl_t **sixpack_ctrls;
int sixpack_maxdev = SIXP_NRUNIT; /* Can be overridden with insmod! */
static struct tty_ldisc sp_ldisc;
@@ -62,26 +146,23 @@ static struct tty_ldisc sp_ldisc;
static void sp_start_tx_timer(struct sixpack *);
static void sp_xmit_on_air(unsigned long);
static void resync_tnc(unsigned long);
-void sixpack_decode(struct sixpack *, unsigned char[], int);
-int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
+static void sixpack_decode(struct sixpack *, unsigned char[], int);
+static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
+static int sixpack_init(struct net_device *dev);
-void decode_prio_command(byte, struct sixpack *);
-void decode_std_command(byte, struct sixpack *);
-void decode_data(byte, struct sixpack *);
+static void decode_prio_command(unsigned char, struct sixpack *);
+static void decode_std_command(unsigned char, struct sixpack *);
+static void decode_data(unsigned char, struct sixpack *);
static int tnc_init(struct sixpack *);
/* Find a free 6pack channel, and link in this `tty' line. */
-static inline struct sixpack *
-sp_alloc(void)
+static inline struct sixpack *sp_alloc(void)
{
sixpack_ctrl_t *spp = NULL;
int i;
- if (sixpack_ctrls == NULL) return NULL; /* Master array missing ! */
-
- for (i = 0; i < sixpack_maxdev; i++)
- {
+ for (i = 0; i < sixpack_maxdev; i++) {
spp = sixpack_ctrls[i];
if (spp == NULL)
@@ -92,14 +173,13 @@ sp_alloc(void)
}
/* Too many devices... */
- if (i >= sixpack_maxdev)
+ if (i >= sixpack_maxdev)
return NULL;
/* If no channels are available, allocate one */
if (!spp &&
(sixpack_ctrls[i] = (sixpack_ctrl_t *)kmalloc(sizeof(sixpack_ctrl_t),
- GFP_KERNEL)) != NULL)
- {
+ GFP_KERNEL)) != NULL) {
spp = sixpack_ctrls[i];
memset(spp, 0, sizeof(sixpack_ctrl_t));
@@ -108,26 +188,24 @@ sp_alloc(void)
spp->ctrl.tty = NULL;
sprintf(spp->dev.name, "sp%d", i);
spp->dev.base_addr = i;
- spp->dev.priv = (void*)&(spp->ctrl);
+ spp->dev.priv = (void *) &spp->ctrl;
spp->dev.next = NULL;
spp->dev.init = sixpack_init;
}
- if (spp != NULL)
- {
+ if (spp != NULL) {
/* register device so that it can be ifconfig'ed */
/* sixpack_init() will be called as a side-effect */
/* SIDE-EFFECT WARNING: sixpack_init() CLEARS spp->ctrl ! */
- if (register_netdev(&(spp->dev)) == 0)
- {
+ if (register_netdev(&spp->dev) == 0) {
set_bit(SIXPF_INUSE, &spp->ctrl.flags);
- spp->ctrl.dev = &(spp->dev);
- spp->dev.priv = (void*)&(spp->ctrl);
-
- return (&(spp->ctrl));
+ spp->ctrl.dev = &spp->dev;
+ spp->dev.priv = (void *) &spp->ctrl;
+ SET_MODULE_OWNER(&spp->dev);
+ return &spp->ctrl;
} else {
- clear_bit(SIXPF_INUSE,&(spp->ctrl.flags));
+ clear_bit(SIXPF_INUSE, &spp->ctrl.flags);
printk(KERN_WARNING "sp_alloc() - register_netdev() failure.\n");
}
}
@@ -137,22 +215,18 @@ sp_alloc(void)
/* Free a 6pack channel. */
-static inline void
-sp_free(struct sixpack *sp)
+static inline void sp_free(struct sixpack *sp)
{
/* Free all 6pack frame buffers. */
if (sp->rbuff)
kfree(sp->rbuff);
sp->rbuff = NULL;
- if (sp->xbuff) {
+ if (sp->xbuff)
kfree(sp->xbuff);
- }
sp->xbuff = NULL;
- if (!test_and_clear_bit(SIXPF_INUSE, &sp->flags))
- {
+ if (!test_and_clear_bit(SIXPF_INUSE, &sp->flags))
printk(KERN_WARNING "%s: sp_free for already free unit.\n", sp->dev->name);
- }
}
@@ -161,8 +235,7 @@ sp_free(struct sixpack *sp)
/* This is the routine that sends the received data to the kernel AX.25.
'cmd' is the KISS command. For AX.25 data, it is zero. */
-static void
-sp_bump(struct sixpack *sp, char cmd)
+static void sp_bump(struct sixpack *sp, char cmd)
{
struct sk_buff *skb;
int count;
@@ -170,13 +243,11 @@ sp_bump(struct sixpack *sp, char cmd)
count = sp->rcount+1;
- sp->rx_bytes+=count;
+ sp->stats.rx_bytes += count;
- skb = dev_alloc_skb(count);
- if (skb == NULL)
- {
+ if ((skb = dev_alloc_skb(count)) == NULL) {
printk(KERN_DEBUG "%s: memory squeeze, dropping packet.\n", sp->dev->name);
- sp->rx_dropped++;
+ sp->stats.rx_dropped++;
return;
}
@@ -185,61 +256,54 @@ sp_bump(struct sixpack *sp, char cmd)
*ptr++ = cmd; /* KISS command */
memcpy(ptr, (sp->cooked_buf)+1, count);
- skb->mac.raw=skb->data;
- skb->protocol=htons(ETH_P_AX25);
+ skb->mac.raw = skb->data;
+ skb->protocol = htons(ETH_P_AX25);
netif_rx(skb);
- sp->rx_packets++;
+ sp->stats.rx_packets++;
}
/* ----------------------------------------------------------------------- */
/* Encapsulate one AX.25 frame and stuff into a TTY queue. */
-static void
-sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
+static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
{
unsigned char *p;
int actual, count;
- if (len > sp->mtu) /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
- {
- len = sp->mtu;
+ if (len > sp->mtu) { /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
printk(KERN_DEBUG "%s: truncating oversized transmit packet!\n", sp->dev->name);
- sp->tx_dropped++;
+ sp->stats.tx_dropped++;
netif_start_queue(sp->dev);
return;
}
p = icp;
- if (p[0] > 5)
- {
+ if (p[0] > 5) {
printk(KERN_DEBUG "%s: invalid KISS command -- dropped\n", sp->dev->name);
netif_start_queue(sp->dev);
return;
}
- if ((p[0] != 0) && (len > 2))
- {
+ if ((p[0] != 0) && (len > 2)) {
printk(KERN_DEBUG "%s: KISS control packet too long -- dropped\n", sp->dev->name);
netif_start_queue(sp->dev);
return;
}
- if ((p[0] == 0) && (len < 15))
- {
+ if ((p[0] == 0) && (len < 15)) {
printk(KERN_DEBUG "%s: bad AX.25 packet to transmit -- dropped\n", sp->dev->name);
netif_start_queue(sp->dev);
- sp->tx_dropped++;
+ sp->stats.tx_dropped++;
return;
}
count = encode_sixpack(p, (unsigned char *) sp->xbuff, len, sp->tx_delay);
sp->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
- switch(p[0])
- {
- case 1: sp->tx_delay = p[1]; return;
+ switch (p[0]) {
+ case 1: sp->tx_delay = p[1]; return;
case 2: sp->persistance = p[1]; return;
case 3: sp->slottime = p[1]; return;
case 4: /* ignored */ return;
@@ -251,17 +315,16 @@ sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
about the state of the DCD or of any timers, as the determination
of the correct time to send is the job of the AX.25 layer. We send
immediately after data has arrived. */
- if (sp->duplex == 1){
+ if (sp->duplex == 1) {
sp->led_state = 0x70;
- sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+ sp->tty->driver.write(sp->tty, 0, &sp->led_state, 1);
sp->tx_enable = 1;
actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, count);
sp->xleft = count - actual;
sp->xhead = sp->xbuff + actual;
sp->led_state = 0x60;
- sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
- }
- else {
+ sp->tty->driver.write(sp->tty, 0, &sp->led_state, 1);
+ } else {
sp->xleft = count;
sp->xhead = sp->xbuff;
sp->status2 = count;
@@ -282,14 +345,13 @@ static void sixpack_write_wakeup(struct tty_struct *tty)
/* First make sure we're connected. */
if (!sp || sp->magic != SIXPACK_MAGIC ||
- !netif_running(sp->dev)) {
+ !netif_running(sp->dev))
return;
- }
if (sp->xleft <= 0) {
/* Now serial buffer is almost free & we can start
* transmission of another packet */
- sp->tx_packets++;
+ sp->stats.tx_packets++;
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
sp->tx_enable = 0;
netif_wake_queue(sp->dev);
@@ -307,51 +369,45 @@ static void sixpack_write_wakeup(struct tty_struct *tty)
/* Encapsulate an IP datagram and kick it into a TTY queue. */
-static int
-sp_xmit(struct sk_buff *skb, struct net_device *dev)
+static int sp_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct sixpack *sp = (struct sixpack*)(dev->priv);
+ struct sixpack *sp = (struct sixpack *) dev->priv;
/* We were not busy, so we are now... :-) */
- if (skb != NULL) {
- netif_stop_queue(dev);
- sp->tx_bytes+=skb->len; /*---2.1.x---*/
- sp_encaps(sp, skb->data, skb->len);
- dev_kfree_skb(skb);
- }
+ netif_stop_queue(dev);
+ sp->stats.tx_bytes += skb->len;
+ sp_encaps(sp, skb->data, skb->len);
+ dev_kfree_skb(skb);
return 0;
}
-/* #endif */
/* perform the persistence/slottime algorithm for CSMA access. If the persistence
check was successful, write the data to the serial driver. Note that in case
of DAMA operation, the data is not sent here. */
-static
-void sp_xmit_on_air(unsigned long channel)
+static void sp_xmit_on_air(unsigned long channel)
{
struct sixpack *sp = (struct sixpack *) channel;
int actual;
static unsigned char random;
-
+
random = random * 17 + 41;
if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistance)) {
sp->led_state = 0x70;
- sp->tty->driver.write(sp->tty, 0, &(sp->led_state),1);
+ sp->tty->driver.write(sp->tty, 0, &sp->led_state, 1);
sp->tx_enable = 1;
actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, sp->status2);
sp->xleft -= actual;
sp->xhead += actual;
sp->led_state = 0x60;
- sp->tty->driver.write(sp->tty, 0, &(sp->led_state),1);
+ sp->tty->driver.write(sp->tty, 0, &sp->led_state, 1);
sp->status2 = 0;
} else
sp_start_tx_timer(sp);
-} /* sp_xmit */
+}
-/* #if defined(CONFIG_6PACK) || defined(CONFIG_6PACK_MODULE) */
/* Return the frame type ID */
static int sp_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
@@ -374,16 +430,14 @@ static int sp_rebuild_header(struct sk_buff *skb)
#endif
}
-/* #endif */ /* CONFIG_{AX25,AX25_MODULE} */
/* Open the low-level part of the 6pack channel. */
-static int
-sp_open(struct net_device *dev)
+static int sp_open(struct net_device *dev)
{
- struct sixpack *sp = (struct sixpack*)(dev->priv);
+ struct sixpack *sp = (struct sixpack *) dev->priv;
unsigned long len;
- if (sp->tty == NULL)
+ if (sp->tty == NULL)
return -ENODEV;
/*
@@ -391,21 +445,17 @@ sp_open(struct net_device *dev)
*
* rbuff Receive buffer.
* xbuff Transmit buffer.
- * cbuff Temporary compression buffer.
*/
-
+
/* !!! length of the buffers. MTU is IP MTU, not PACLEN!
*/
len = dev->mtu * 2;
- sp->rbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
- if (sp->rbuff == NULL)
+ if ((sp->rbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)
return -ENOMEM;
- sp->xbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
- if (sp->xbuff == NULL)
- {
+ if ((sp->xbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL) {
kfree(sp->rbuff);
return -ENOMEM;
}
@@ -429,7 +479,7 @@ sp_open(struct net_device *dev)
sp->status2 = 0;
sp->tnc_ok = 0;
sp->tx_enable = 0;
-
+
netif_start_queue(dev);
init_timer(&sp->tx_t);
@@ -439,22 +489,20 @@ sp_open(struct net_device *dev)
/* Close the low-level part of the 6pack channel. */
-static int
-sp_close(struct net_device *dev)
+static int sp_close(struct net_device *dev)
{
- struct sixpack *sp = (struct sixpack*)(dev->priv);
+ struct sixpack *sp = (struct sixpack *) dev->priv;
- if (sp->tty == NULL) {
+ if (sp->tty == NULL)
return -EBUSY;
- }
+
sp->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
-
+
netif_stop_queue(dev);
return 0;
}
-static int
-sixpack_receive_room(struct tty_struct *tty)
+static int sixpack_receive_room(struct tty_struct *tty)
{
return 65536; /* We can handle an infinite amount of data. :-) */
}
@@ -467,8 +515,7 @@ sixpack_receive_room(struct tty_struct *tty)
* a block of 6pack data has been received, which can now be decapsulated
* and sent on to some IP layer for further processing.
*/
-static void
-sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
+static void sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
{
unsigned char buf[512];
unsigned long flags;
@@ -484,18 +531,15 @@ sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, i
cli();
memcpy(buf, cp, count<sizeof(buf)? count:sizeof(buf));
restore_flags(flags);
-
+
/* Read the characters out of the buffer */
count1 = count;
- while(count)
- {
+ while (count) {
count--;
- if (fp && *fp++)
- {
- if (!test_and_set_bit(SIXPF_ERROR, &sp->flags)) {
- sp->rx_errors++;
- }
+ if (fp && *fp++) {
+ if (!test_and_set_bit(SIXPF_ERROR, &sp->flags))
+ sp->stats.rx_errors++;
continue;
}
}
@@ -509,15 +553,14 @@ sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, i
* sure the tty line exists, we only have to link it to
* a free 6pcack channel...
*/
-static int
-sixpack_open(struct tty_struct *tty)
+static int sixpack_open(struct tty_struct *tty)
{
struct sixpack *sp = (struct sixpack *) tty->disc_data;
int err;
/* First make sure we're not already connected. */
- if (sp && sp->magic == SIXPACK_MAGIC)
+ if (sp && sp->magic == SIXPACK_MAGIC)
return -EEXIST;
/* OK. Find a free 6pack channel to use. */
@@ -525,21 +568,18 @@ sixpack_open(struct tty_struct *tty)
return -ENFILE;
sp->tty = tty;
tty->disc_data = sp;
- if (tty->driver.flush_buffer)
+ if (tty->driver.flush_buffer)
tty->driver.flush_buffer(tty);
if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);
-
/* Restore default settings */
sp->dev->type = ARPHRD_AX25;
/* Perform the low-level 6pack initialization. */
- if ((err = sp_open(sp->dev)))
+ if ((err = sp_open(sp->dev)))
return err;
-
- MOD_INC_USE_COUNT;
/* Done. We have linked the TTY line to a channel. */
@@ -555,8 +595,7 @@ sixpack_open(struct tty_struct *tty)
* TTY line discipline to what it was before it got hooked to 6pack
* (which usually is TTY again).
*/
-static void
-sixpack_close(struct tty_struct *tty)
+static void sixpack_close(struct tty_struct *tty)
{
struct sixpack *sp = (struct sixpack *) tty->disc_data;
@@ -565,106 +604,62 @@ sixpack_close(struct tty_struct *tty)
return;
rtnl_lock();
- if (sp->dev->flags & IFF_UP)
- (void) dev_close(sp->dev);
+ dev_close(sp->dev);
+
+ del_timer(&sp->tx_t);
+ del_timer(&sp->resync_t);
- del_timer(&(sp->tx_t));
- del_timer(&(sp->resync_t));
-
tty->disc_data = 0;
sp->tty = NULL;
- /* VSV = very important to remove timers */
sp_free(sp);
- unregister_netdev(sp->dev);
+ unregister_netdevice(sp->dev);
rtnl_unlock();
- MOD_DEC_USE_COUNT;
}
-static struct net_device_stats *
-sp_get_stats(struct net_device *dev)
+static struct net_device_stats *sp_get_stats(struct net_device *dev)
{
- static struct net_device_stats stats;
- struct sixpack *sp = (struct sixpack*)(dev->priv);
-
- memset(&stats, 0, sizeof(struct net_device_stats));
-
- stats.rx_packets = sp->rx_packets;
- stats.tx_packets = sp->tx_packets;
- stats.rx_bytes = sp->rx_bytes;
- stats.tx_bytes = sp->tx_bytes;
- stats.rx_dropped = sp->rx_dropped;
- stats.tx_dropped = sp->tx_dropped;
- stats.tx_errors = sp->tx_errors;
- stats.rx_errors = sp->rx_errors;
- stats.rx_over_errors = sp->rx_over_errors;
- return (&stats);
+ struct sixpack *sp = (struct sixpack *) dev->priv;
+ return &sp->stats;
}
-int
-sp_set_mac_address(struct net_device *dev, void *addr)
+static int sp_set_mac_address(struct net_device *dev, void *addr)
{
- int err;
-
- err = verify_area(VERIFY_READ, addr, AX25_ADDR_LEN);
- if (err) {
- return err;
- }
-
- copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN); /* addr is an AX.25 shifted ASCII mac address */
-
- return 0;
+ return copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN) ? -EFAULT : 0;
}
-static int
-sp_set_dev_mac_address(struct net_device *dev, void *addr)
+static int sp_set_dev_mac_address(struct net_device *dev, void *addr)
{
- struct sockaddr *sa=addr;
+ struct sockaddr *sa = addr;
memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN);
return 0;
}
/* Perform I/O control on an active 6pack channel. */
-static int
-sixpack_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
+static int sixpack_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
{
struct sixpack *sp = (struct sixpack *) tty->disc_data;
- int err;
unsigned int tmp;
/* First make sure we're connected. */
- if (!sp || sp->magic != SIXPACK_MAGIC) {
+ if (!sp || sp->magic != SIXPACK_MAGIC)
return -EINVAL;
- }
switch(cmd) {
- case SIOCGIFNAME:
- err = verify_area(VERIFY_WRITE, arg, strlen(sp->dev->name) + 1);
- if (err) {
- return err;
- }
- copy_to_user(arg, sp->dev->name, strlen(sp->dev->name) + 1);
- return 0;
+ case SIOCGIFNAME:
+ return copy_to_user(arg, sp->dev->name, strlen(sp->dev->name) + 1) ? -EFAULT : 0;
case SIOCGIFENCAP:
- err = verify_area(VERIFY_WRITE, arg, sizeof(int));
- if (err) {
- return err;
- }
- put_user(0, (int *)arg);
- return 0;
+ return put_user(0, (int *)arg);
case SIOCSIFENCAP:
- err = verify_area(VERIFY_READ, arg, sizeof(int));
- if (err) {
- return err;
- }
- get_user(tmp,(int *)arg);
+ if (get_user(tmp, (int *) arg))
+ return -EFAULT;
- sp->mode = tmp;
+ sp->mode = tmp;
sp->dev->addr_len = AX25_ADDR_LEN; /* sizeof an AX.25 addr */
sp->dev->hard_header_len = AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3;
sp->dev->type = ARPHRD_AX25;
@@ -686,26 +681,25 @@ sixpack_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
static int sp_open_dev(struct net_device *dev)
{
- struct sixpack *sp = (struct sixpack*)(dev->priv);
- if(sp->tty==NULL)
+ struct sixpack *sp = (struct sixpack *) dev->priv;
+ if (sp->tty == NULL)
return -ENODEV;
return 0;
}
/* Initialize 6pack control device -- register 6pack line discipline */
-static int __init sixpack_init_ctrl_dev(void)
+static int __init sixpack_init_driver(void)
{
int status;
- if (sixpack_maxdev < 4) sixpack_maxdev = 4; /* Sanity */
+ if (sixpack_maxdev < 4)
+ sixpack_maxdev = 4; /* Sanity */
- printk(KERN_INFO "AX.25: 6pack driver, %s (dynamic channels, max=%d)\n",
- SIXPACK_VERSION, sixpack_maxdev);
+ printk(banner, sixpack_maxdev);
sixpack_ctrls = (sixpack_ctrl_t **) kmalloc(sizeof(void*)*sixpack_maxdev, GFP_KERNEL);
- if (sixpack_ctrls == NULL)
- {
+ if (sixpack_ctrls == NULL) {
printk(KERN_WARNING "6pack: Can't allocate sixpack_ctrls[] array! Uaargh! (-> No 6pack available)\n");
return -ENOMEM;
}
@@ -713,9 +707,7 @@ static int __init sixpack_init_ctrl_dev(void)
/* Clear the pointer array, we allocate devices when we need them */
memset(sixpack_ctrls, 0, sizeof(void*)*sixpack_maxdev); /* Pointers */
-
/* Fill in our line protocol discipline, and register it */
- memset(&sp_ldisc, 0, sizeof(sp_ldisc));
sp_ldisc.magic = TTY_LDISC_MAGIC;
sp_ldisc.name = "6pack";
sp_ldisc.flags = 0;
@@ -731,6 +723,7 @@ static int __init sixpack_init_ctrl_dev(void)
sp_ldisc.write_wakeup = sixpack_write_wakeup;
if ((status = tty_register_ldisc(N_6PACK, &sp_ldisc)) != 0) {
printk(KERN_WARNING "6pack: can't register line discipline (err = %d)\n", status);
+ kfree(sixpack_ctrls);
}
return status;
@@ -740,38 +733,28 @@ static void __exit sixpack_cleanup_driver(void)
{
int i;
- if (sixpack_ctrls != NULL)
- {
- for (i = 0; i < sixpack_maxdev; i++)
- {
- if (sixpack_ctrls[i])
- {
- /*
- * VSV = if dev->start==0, then device
- * unregistered while close proc.
- */
- if (netif_running(&sixpack_ctrls[i]->dev))
- unregister_netdev(&sixpack_ctrls[i]->dev);
-
- kfree(sixpack_ctrls[i]);
- sixpack_ctrls[i] = NULL;
- }
+ for (i = 0; i < sixpack_maxdev; i++) {
+ if (sixpack_ctrls[i]) {
+ /*
+ * VSV = if dev->start==0, then device
+ * unregistered while close proc.
+ */
+ if (netif_running(&sixpack_ctrls[i]->dev))
+ unregister_netdev(&sixpack_ctrls[i]->dev);
+
+ kfree(sixpack_ctrls[i]);
}
- kfree(sixpack_ctrls);
- sixpack_ctrls = NULL;
}
- if ((i = tty_register_ldisc(N_6PACK, NULL)))
- {
+ kfree(sixpack_ctrls);
+ if ((i = tty_register_ldisc(N_6PACK, NULL)))
printk(KERN_WARNING "6pack: can't unregister line discipline (err = %d)\n", i);
- }
}
/* Initialize the 6pack driver. Called by DDI. */
-int
-sixpack_init(struct net_device *dev)
+static int sixpack_init(struct net_device *dev)
{
- struct sixpack *sp = (struct sixpack*)(dev->priv);
+ struct sixpack *sp = (struct sixpack *) dev->priv;
static char ax25_bcast[AX25_ADDR_LEN] =
{'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
@@ -779,14 +762,14 @@ sixpack_init(struct net_device *dev)
{'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
if (sp == NULL) /* Allocation failed ?? */
- return -ENODEV;
+ return -ENODEV;
/* Set up the "6pack Control Block". (And clear statistics) */
-
+
memset(sp, 0, sizeof (struct sixpack));
sp->magic = SIXPACK_MAGIC;
sp->dev = dev;
-
+
/* Finish setting up the DEVICE info. */
dev->mtu = SIXP_MTU;
dev->hard_start_xmit = sp_xmit;
@@ -817,66 +800,62 @@ sixpack_init(struct net_device *dev)
/* ----> 6pack timer interrupt handler and friends. <---- */
-static void
-sp_start_tx_timer(struct sixpack *sp)
+static void sp_start_tx_timer(struct sixpack *sp)
{
int when = sp->slottime;
-
- del_timer(&(sp->tx_t));
+
+ del_timer(&sp->tx_t);
sp->tx_t.data = (unsigned long) sp;
sp->tx_t.function = sp_xmit_on_air;
sp->tx_t.expires = jiffies + ((when+1)*HZ)/100;
- add_timer(&(sp->tx_t));
+ add_timer(&sp->tx_t);
}
/* encode an AX.25 packet into 6pack */
-int encode_sixpack(byte *tx_buf, byte *tx_buf_raw, int length, byte tx_delay)
+static int encode_sixpack(unsigned char *tx_buf, unsigned char *tx_buf_raw, int length, unsigned char tx_delay)
{
int count = 0;
- byte checksum = 0, buf[400];
+ unsigned char checksum = 0, buf[400];
int raw_count = 0;
tx_buf_raw[raw_count++] = SIXP_PRIO_CMD_MASK | SIXP_TX_MASK;
tx_buf_raw[raw_count++] = SIXP_SEOF;
buf[0] = tx_delay;
- for(count = 1; count < length; count++)
+ for (count = 1; count < length; count++)
buf[count] = tx_buf[count];
- for(count = 0; count < length; count++)
+ for (count = 0; count < length; count++)
checksum += buf[count];
- buf[length] = (byte)0xff - checksum;
-
- for(count = 0; count <= length; count++) {
- if((count % 3) == 0) {
+ buf[length] = (unsigned char) 0xff - checksum;
+
+ for (count = 0; count <= length; count++) {
+ if ((count % 3) == 0) {
tx_buf_raw[raw_count++] = (buf[count] & 0x3f);
tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x30);
- }
- else if((count % 3) == 1) {
+ } else if ((count % 3) == 1) {
tx_buf_raw[raw_count++] |= (buf[count] & 0x0f);
- tx_buf_raw[raw_count] =
- ((buf[count] >> 2) & 0x3c);
+ tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x3c);
} else {
tx_buf_raw[raw_count++] |= (buf[count] & 0x03);
- tx_buf_raw[raw_count++] =
- (buf[count] >> 2);
- } /* else */
- } /* for */
+ tx_buf_raw[raw_count++] = (buf[count] >> 2);
+ }
+ }
if ((length % 3) != 2)
raw_count++;
tx_buf_raw[raw_count++] = SIXP_SEOF;
- return(raw_count);
+ return raw_count;
}
/* decode a 6pack packet */
-void
+static void
sixpack_decode(struct sixpack *sp, unsigned char pre_rbuff[], int count)
{
- byte inbyte;
+ unsigned char inbyte;
int count1;
for (count1 = 0; count1 < count; count1++) {
@@ -884,32 +863,28 @@ sixpack_decode(struct sixpack *sp, unsigned char pre_rbuff[], int count)
if (inbyte == SIXP_FOUND_TNC) {
printk(KERN_INFO "6pack: TNC found.\n");
sp->tnc_ok = 1;
- del_timer(&(sp->resync_t));
+ del_timer(&sp->resync_t);
}
- if((inbyte & SIXP_PRIO_CMD_MASK) != 0)
+ if ((inbyte & SIXP_PRIO_CMD_MASK) != 0)
decode_prio_command(inbyte, sp);
- else if((inbyte & SIXP_STD_CMD_MASK) != 0)
+ else if ((inbyte & SIXP_STD_CMD_MASK) != 0)
decode_std_command(inbyte, sp);
- else {
- if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)
- decode_data(inbyte, sp);
- } /* else */
- } /* for */
+ else if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)
+ decode_data(inbyte, sp);
+ }
}
-static int
-tnc_init(struct sixpack *sp)
+static int tnc_init(struct sixpack *sp)
{
- static byte inbyte;
-
- inbyte = 0xe8;
+ unsigned char inbyte = 0xe8;
+
sp->tty->driver.write(sp->tty, 0, &inbyte, 1);
- del_timer(&(sp->resync_t));
+ del_timer(&sp->resync_t);
sp->resync_t.data = (unsigned long) sp;
sp->resync_t.function = resync_tnc;
sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
- add_timer(&(sp->resync_t));
+ add_timer(&sp->resync_t);
return 0;
}
@@ -917,9 +892,9 @@ tnc_init(struct sixpack *sp)
/* identify and execute a 6pack priority command byte */
-void decode_prio_command(byte cmd, struct sixpack *sp)
+static void decode_prio_command(unsigned char cmd, struct sixpack *sp)
{
- byte channel;
+ unsigned char channel;
int actual;
channel = cmd & SIXP_CHN_MASK;
@@ -941,11 +916,11 @@ void decode_prio_command(byte cmd, struct sixpack *sp)
cmd &= !SIXP_RX_DCD_MASK;
}
sp->status = cmd & SIXP_PRIO_DATA_MASK;
- } /* if */
+ }
else { /* output watchdog char if idle */
if ((sp->status2 != 0) && (sp->duplex == 1)) {
sp->led_state = 0x70;
- sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+ sp->tty->driver.write(sp->tty, 0, &sp->led_state, 1);
sp->tx_enable = 1;
actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, sp->status2);
sp->xleft -= actual;
@@ -953,21 +928,21 @@ void decode_prio_command(byte cmd, struct sixpack *sp)
sp->led_state = 0x60;
sp->status2 = 0;
- } /* if */
- } /* else */
+ }
+ }
/* needed to trigger the TNC watchdog */
- sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+ sp->tty->driver.write(sp->tty, 0, &sp->led_state, 1);
/* if the state byte has been received, the TNC is present,
so the resync timer can be reset. */
if (sp->tnc_ok == 1) {
- del_timer(&(sp->resync_t));
+ del_timer(&sp->resync_t);
sp->resync_t.data = (unsigned long) sp;
sp->resync_t.function = resync_tnc;
sp->resync_t.expires = jiffies + SIXP_INIT_RESYNC_TIMEOUT;
- add_timer(&(sp->resync_t));
+ add_timer(&sp->resync_t);
}
sp->status1 = cmd & SIXP_PRIO_DATA_MASK;
@@ -976,8 +951,7 @@ void decode_prio_command(byte cmd, struct sixpack *sp)
/* try to resync the TNC. Called by the resync timer defined in
decode_prio_command */
-static void
-resync_tnc(unsigned long channel)
+static void resync_tnc(unsigned long channel)
{
static char resync_cmd = 0xe8;
struct sixpack *sp = (struct sixpack *) channel;
@@ -985,7 +959,7 @@ resync_tnc(unsigned long channel)
printk(KERN_INFO "6pack: resyncing TNC\n");
/* clear any data that might have been received */
-
+
sp->rx_count = 0;
sp->rx_count_cooked = 0;
@@ -995,63 +969,63 @@ resync_tnc(unsigned long channel)
sp->status1 = 1;
sp->status2 = 0;
sp->tnc_ok = 0;
-
+
/* resync the TNC */
sp->led_state = 0x60;
- sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+ sp->tty->driver.write(sp->tty, 0, &sp->led_state, 1);
sp->tty->driver.write(sp->tty, 0, &resync_cmd, 1);
/* Start resync timer again -- the TNC might be still absent */
- del_timer(&(sp->resync_t));
+ del_timer(&sp->resync_t);
sp->resync_t.data = (unsigned long) sp;
sp->resync_t.function = resync_tnc;
sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
- add_timer(&(sp->resync_t));
+ add_timer(&sp->resync_t);
}
/* identify and execute a standard 6pack command byte */
-void decode_std_command(byte cmd, struct sixpack *sp)
+static void decode_std_command(unsigned char cmd, struct sixpack *sp)
{
- byte checksum = 0, rest = 0, channel;
+ unsigned char checksum = 0, rest = 0, channel;
short i;
channel = cmd & SIXP_CHN_MASK;
- switch(cmd & SIXP_CMD_MASK) { /* normal command */
+ switch (cmd & SIXP_CMD_MASK) { /* normal command */
case SIXP_SEOF:
if ((sp->rx_count == 0) && (sp->rx_count_cooked == 0)) {
if ((sp->status & SIXP_RX_DCD_MASK) ==
SIXP_RX_DCD_MASK) {
sp->led_state = 0x68;
- sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
- } /* if */
+ sp->tty->driver.write(sp->tty, 0, &sp->led_state, 1);
+ }
} else {
sp->led_state = 0x60;
/* fill trailing bytes with zeroes */
- sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+ sp->tty->driver.write(sp->tty, 0, &sp->led_state, 1);
rest = sp->rx_count;
if (rest != 0)
- for(i=rest; i<=3; i++)
+ for (i = rest; i <= 3; i++)
decode_data(0, sp);
if (rest == 2)
sp->rx_count_cooked -= 2;
else if (rest == 3)
sp->rx_count_cooked -= 1;
- for (i=0; i<sp->rx_count_cooked; i++)
- checksum+=sp->cooked_buf[i];
+ for (i = 0; i < sp->rx_count_cooked; i++)
+ checksum += sp->cooked_buf[i];
if (checksum != SIXP_CHKSUM) {
printk(KERN_DEBUG "6pack: bad checksum %2.2x\n", checksum);
} else {
sp->rcount = sp->rx_count_cooked-2;
sp_bump(sp, 0);
- } /* else */
+ }
sp->rx_count_cooked = 0;
- } /* else */
+ }
break;
case SIXP_TX_URUN: printk(KERN_DEBUG "6pack: TX underrun\n");
break;
@@ -1059,14 +1033,13 @@ void decode_std_command(byte cmd, struct sixpack *sp)
break;
case SIXP_RX_BUF_OVL:
printk(KERN_DEBUG "6pack: RX buffer overflow\n");
- } /* switch */
-} /* function */
+ }
+}
/* decode 4 sixpack-encoded bytes into 3 data bytes */
-void decode_data(byte inbyte, struct sixpack *sp)
+static void decode_data(unsigned char inbyte, struct sixpack *sp)
{
-
unsigned char *buf;
if (sp->rx_count != 3)
@@ -1086,5 +1059,8 @@ void decode_data(byte inbyte, struct sixpack *sp)
MODULE_AUTHOR("Andreas Könsgen <ajk@ccac.rwth-aachen.de>");
MODULE_DESCRIPTION("6pack driver for AX.25");
-module_init(sixpack_init_ctrl_dev);
+MODULE_PARM(sixpack_maxdev, "i");
+MODULE_PARM_DESC(sixpack_maxdev, "number of 6PACK devices");
+
+module_init(sixpack_init_driver);
module_exit(sixpack_cleanup_driver);
diff --git a/drivers/net/hamradio/6pack.h b/drivers/net/hamradio/6pack.h
deleted file mode 100644
index 08cee0485..000000000
--- a/drivers/net/hamradio/6pack.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 6pack.h Define the 6pack device driver interface and constants.
- *
- * NOTE: THIS FILE WILL BE MOVED TO THE LINUX INCLUDE DIRECTORY
- * AS SOON AS POSSIBLE!
- *
- * Version: @(#)6pack.h 0.3.0 04/07/98
- *
- * Fixes:
- *
- * Author: Andreas Könsgen <ajk@iehk.rwth-aachen.de>
- *
- * This file is derived from slip.h, written by
- * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
- */
-
-#ifndef _LINUX_6PACK_H
-#define _LINUX_6PACK_H
-
-#define SIXPACK_VERSION "Revision: 0.3.0"
-
-#ifdef __KERNEL__
-
-/* sixpack priority commands */
-#define SIXP_SEOF 0x40 /* start and end of a 6pack frame */
-#define SIXP_TX_URUN 0x48 /* transmit overrun */
-#define SIXP_RX_ORUN 0x50 /* receive overrun */
-#define SIXP_RX_BUF_OVL 0x58 /* receive buffer overflow */
-
-#define SIXP_CHKSUM 0xFF /* valid checksum of a 6pack frame */
-
-/* masks to get certain bits out of the status bytes sent by the TNC */
-
-#define SIXP_CMD_MASK 0xC0
-#define SIXP_CHN_MASK 0x07
-#define SIXP_PRIO_CMD_MASK 0x80
-#define SIXP_STD_CMD_MASK 0x40
-#define SIXP_PRIO_DATA_MASK 0x38
-#define SIXP_TX_MASK 0x20
-#define SIXP_RX_MASK 0x10
-#define SIXP_RX_DCD_MASK 0x18
-#define SIXP_LEDS_ON 0x78
-#define SIXP_LEDS_OFF 0x60
-#define SIXP_CON 0x08
-#define SIXP_STA 0x10
-
-#define SIXP_FOUND_TNC 0xe9
-#define SIXP_CON_ON 0x68
-#define SIXP_DCD_MASK 0x08
-#define SIXP_DAMA_OFF 0
-
-/* default level 2 parameters */
-#define SIXP_TXDELAY 25 /* in 10 ms */
-#define SIXP_PERSIST 50 /* in 256ths */
-#define SIXP_SLOTTIME 10 /* in 10 ms */
-#define SIXP_INIT_RESYNC_TIMEOUT 150 /* in 10 ms */
-#define SIXP_RESYNC_TIMEOUT 500 /* in 10 ms */
-
-/* 6pack configuration. */
-#define SIXP_NRUNIT 256 /* MAX number of 6pack channels */
-#define SIXP_MTU 256 /* Default MTU */
-
-enum sixpack_flags {
- SIXPF_INUSE, /* Channel in use */
- SIXPF_ERROR, /* Parity, etc. error */
-};
-
-struct sixpack {
- int magic;
-
- /* Various fields. */
- struct tty_struct *tty; /* ptr to TTY structure */
- struct net_device *dev; /* easy for intr handling */
-
- /* These are pointers to the malloc()ed frame buffers. */
- unsigned char *rbuff; /* receiver buffer */
- int rcount; /* received chars counter */
- unsigned char *xbuff; /* transmitter buffer */
- unsigned char *xhead; /* pointer to next byte to XMIT */
- int xleft; /* bytes left in XMIT queue */
-
- unsigned char raw_buf[4];
- unsigned char cooked_buf[400];
-
- unsigned int rx_count;
- unsigned int rx_count_cooked;
-
- /* 6pack interface statistics. */
- unsigned long rx_packets; /* inbound frames counter */
- unsigned long tx_packets; /* outbound frames counter */
- unsigned long rx_bytes; /* inbound bytes counter */
- unsigned long tx_bytes; /* outboud bytes counter */
- unsigned long rx_errors; /* Parity, etc. errors */
- unsigned long tx_errors; /* Planned stuff */
- unsigned long rx_dropped; /* No memory for skb */
- unsigned long tx_dropped; /* When MTU change */
- unsigned long rx_over_errors; /* Frame bigger then 6pack buf. */
-
- /* Detailed 6pack statistics. */
-
- int mtu; /* Our mtu (to spot changes!) */
- int buffsize; /* Max buffers sizes */
-
- unsigned long flags; /* Flag values/ mode etc */
- /* long req'd for set_bit --RR */
- unsigned char mode; /* 6pack mode */
-
-/* 6pack stuff */
-
- unsigned char tx_delay;
- unsigned char persistance;
- unsigned char slottime;
- unsigned char duplex;
- unsigned char led_state;
- unsigned char status;
- unsigned char status1;
- unsigned char status2;
- unsigned char tx_enable;
- unsigned char tnc_ok;
-
-/* unsigned char retval; */
-
- struct timer_list tx_t;
- struct timer_list resync_t;
-}; /* struct sixpack */
-
-
-/* should later be moved to include/net/ax25.h */
-#define AX25_6PACK_HEADER_LEN 0
-#define SIXPACK_MAGIC 0x5304
-
-extern int sixpack_init(struct net_device *dev);
-
-#endif
-
-#endif /* _LINUX_6PACK.H */
diff --git a/drivers/net/hamradio/Makefile b/drivers/net/hamradio/Makefile
index 57304cc47..964a184c4 100644
--- a/drivers/net/hamradio/Makefile
+++ b/drivers/net/hamradio/Makefile
@@ -21,8 +21,6 @@ obj-$(CONFIG_SCC) += scc.o
obj-$(CONFIG_MKISS) += mkiss.o
obj-$(CONFIG_6PACK) += 6pack.o
obj-$(CONFIG_YAM) += yam.o
-obj-$(CONFIG_PI) += pi2.o
-obj-$(CONFIG_PT) += pt.o
obj-$(CONFIG_BPQETHER) += bpqether.o
obj-$(CONFIG_BAYCOM_SER_FDX) += baycom_ser_fdx.o hdlcdrv.o
obj-$(CONFIG_BAYCOM_SER_HDX) += baycom_ser_hdx.o hdlcdrv.o
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 976bb9ebd..7dab437e6 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -690,13 +690,12 @@ static void ax25_close(struct tty_struct *tty)
if (ax == NULL || ax->magic != AX25_MAGIC)
return;
- dev_close(ax->dev);
+ unregister_netdev(ax->dev);
tty->disc_data = 0;
ax->tty = NULL;
ax_free(ax);
- unregister_netdev(ax->dev);
MOD_DEC_USE_COUNT;
}
diff --git a/drivers/net/hamradio/pi2.c b/drivers/net/hamradio/pi2.c
deleted file mode 100644
index 12fc8e338..000000000
--- a/drivers/net/hamradio/pi2.c
+++ /dev/null
@@ -1,1677 +0,0 @@
-/*
- pi2.c: Driver for the Ottawa Amateur Radio Club PI and PI2 interface.
- Copyright (c) 1994 David Perry
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 675 Mass Ave, Cambridge MA 02139, USA.
-
- The file skeleton.c by Donald Becker was used as a starting point
- for this driver.
-
- Revision History
-
- April 6, 1994 (dp) Created
- version 0.0 ALPHA
- April 10, 1994 (dp) Included cleanup, suggestions from J. P. Morrison.
- version 0.1 ALPHA
- April 13, 1994 (dp) Included address probing from JPM, autoirq
- version 0.2 ALPHA
- April 14, 1994 (ac) Sketched in the NET3 changes.
- April 17, 1994 (dp) Finished the NET3 changes. Used init_etherdev()
- instead of kmalloc() to ensure that DMA buffers will
- reside under the 16 meg line.
- version 0.4 ALPHA
- April 18, 1994 (dp) Now using the kernel provided sk_buff handling functions.
- Fixed a nasty problem with DMA.
- version 0.5 ALPHA
- June 6, 1994 (ac) Fixed to match the buffer locking changes. Added a hack to
- fix a funny I see (search for HACK) and fixed the calls in
- init() so it doesn't migrate module based ethernet cards up
- to eth2 Took out the old module ideas as they are no longer
- relevant to the PI driver.
- July 16, 1994 (dp) Fixed the B channel rx overrun problem ac referred to
- above. Also added a bit of a hack to improve the maximum
- baud rate on the B channel (Search for STUFF2). Included
- ioctl stuff from John Paul Morrison. version 0.6 ALPHA
- Feb 9, 1995 (dp) Updated for 1.1.90 kernel
- version 0.7 ALPHA
- Apr 6, 1995 (ac) Tweaks for NET3 pre snapshot 002 AX.25
- April 23, 1995 (dp) Fixed ioctl so it works properly with piconfig program
- when changing the baud rate or clock mode.
- version 0.8 ALPHA
- July 17, 1995 (ac) Finally polishing of AX25.030+ support
- Oct 29, 1995 (ac) A couple of minor fixes before this, and this release changes
- to the proper set_mac_address semantics which will break
- a few programs I suspect.
- Aug 18, 1996 (jsn) Converted to be used as a module.
- Dec 13, 1996 (jsn) Fixed to match Linux networking changes.
-*/
-
-/* The following #define invokes a hack that will improve performance (baud)
- for the B port. The up side is it makes 9600 baud work ok on the B port.
- It may do 38400, depending on the host. The down side is it burns up
- CPU cycles with ints locked for up to 1 character time, at the beginning
- of each transmitted packet. If this causes you to lose sleep, #undefine it.
-*/
-
-/*#define STUFF2 1*/
-
-/* The default configuration */
-#define PI_DMA 3
-
-#define DEF_A_SPEED 0 /* 0 means external clock */
-#define DEF_A_TXDELAY 15 /* 15 mS transmit delay */
-#define DEF_A_PERSIST 128 /* 50% persistence */
-#define DEF_A_SLOTIME 15 /* 15 mS slot time */
-#define DEF_A_SQUELDELAY 1 /* 1 mS squelch delay - allows fcs and flag */
-#define DEF_A_CLOCKMODE 0 /* clock mode - 0 is normal */
-
-#define DEF_B_SPEED 1200 /* 1200 baud */
-#define DEF_B_TXDELAY 40 /* 400 mS */
-#define DEF_B_PERSIST 128 /* 50% */
-#define DEF_B_SLOTIME 30 /* 300 mS */
-#define DEF_B_SQUELDELAY 3 /* 30 mS */
-#define DEF_B_CLOCKMODE 0 /* Normal clock mode */
-
-/* The following #define is only really required for the PI card, not
- the PI2 - but it's safer to leave it in. */
-#define REALLY_SLOW_IO 1
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/malloc.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/uaccess.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/timer.h>
-#include <linux/if_arp.h>
-#include <linux/pi2.h>
-#include <linux/init.h>
-#include "z8530.h"
-#include <net/ax25.h>
-
-struct mbuf {
- struct mbuf *next;
- int cnt;
- char data[0];
-};
-
-/*
- * The actual devices we will use
- */
-
-/*
- * PI device declarations.
- */
-
-static int pi0_preprobe(struct net_device *dev){return 0;} /* Dummy probe function */
-static struct net_device pi0a = { "pi0a", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pi0_preprobe };
-static struct net_device pi0b = { "pi0b", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pi0_preprobe };
-
-
-/* The number of low I/O ports used by the card. */
-#define PI_TOTAL_SIZE 8
-
-
-/* Index to functions, as function prototypes. */
-
-static int pi_probe(struct net_device *dev, int card_type);
-static int pi_open(struct net_device *dev);
-static int pi_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void pi_interrupt(int reg_ptr, void *dev_id, struct pt_regs *regs);
-static int pi_close(struct net_device *dev);
-static int pi_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-static struct net_device_stats *pi_get_stats(struct net_device *dev);
-static void rts(struct pi_local *lp, int x);
-static void b_rxint(struct net_device *dev, struct pi_local *lp);
-static void b_txint(struct pi_local *lp);
-static void b_exint(struct pi_local *lp);
-static void a_rxint(struct net_device *dev, struct pi_local *lp);
-static void a_txint(struct pi_local *lp);
-static void a_exint(struct pi_local *lp);
-static char *get_dma_buffer(unsigned long *mem_ptr);
-static int valid_dma_page(unsigned long addr, unsigned long dev_buffsize);
-
-static char ax25_bcast[7] =
-{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static char ax25_test[7] =
-{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
-static int ext2_secrm_seed = 152; /* Random generator base */
-
-extern inline unsigned char random(void)
-{
- return (unsigned char) (ext2_secrm_seed = ext2_secrm_seed
- * 69069l + 1);
-}
-
-extern inline void wrtscc(int cbase, int ctl, int sccreg, int val)
-{
- /* assume caller disables interrupts! */
- outb_p(0, cbase + DMAEN); /* Disable DMA while we touch the scc */
- outb_p(sccreg, ctl); /* Select register */
- outb_p(val, ctl); /* Output value */
- outb_p(1, cbase + DMAEN); /* Enable DMA */
-}
-
-extern inline int rdscc(int cbase, int ctl, int sccreg)
-{
- int retval;
-
- /* assume caller disables interrupts! */
- outb_p(0, cbase + DMAEN); /* Disable DMA while we touch the scc */
- outb_p(sccreg, ctl); /* Select register */
- retval = inb_p(ctl);
- outb_p(1, cbase + DMAEN); /* Enable DMA */
- return retval;
-}
-
-static void switchbuffers(struct pi_local *lp)
-{
- if (lp->rcvbuf == lp->rxdmabuf1)
- lp->rcvbuf = lp->rxdmabuf2;
- else
- lp->rcvbuf = lp->rxdmabuf1;
-}
-
-static void hardware_send_packet(struct pi_local *lp, struct sk_buff *skb)
-{
- char kickflag;
- unsigned long flags;
-
- lp->stats.tx_packets++;
-
- save_flags(flags);
- cli();
- kickflag = (skb_peek(&lp->sndq) == NULL) && (lp->sndbuf == NULL);
- restore_flags(flags);
-
- skb_queue_tail(&lp->sndq, skb);
- if (kickflag)
- {
- /* simulate interrupt to xmit */
- switch (lp->base & 2)
- {
- case 2:
- a_txint(lp); /* process interrupt */
- break;
- case 0:
- save_flags(flags);
- cli();
- if (lp->tstate == IDLE)
- b_txint(lp);
- restore_flags(flags);
- break;
- }
- }
-}
-
-static void setup_rx_dma(struct pi_local *lp)
-{
- unsigned long flags;
- int cmd;
- unsigned long dma_abs;
- unsigned dmachan;
-
- save_flags(flags);
- cli();
-
- dma_abs = (unsigned long) (lp->rcvbuf->data);
- dmachan = lp->dmachan;
- cmd = lp->base + CTL;
-
- if(!valid_dma_page(dma_abs, DMA_BUFF_SIZE + sizeof(struct mbuf)))
- panic("PI: RX buffer violates DMA boundary!");
-
- /* Get ready for RX DMA */
- wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | WT_RDY_RT | INT_ERR_Rx | EXT_INT_ENAB);
-
- disable_dma(dmachan);
- clear_dma_ff(dmachan);
-
- /* Set DMA mode register to single transfers, incrementing address,
- * auto init, writes
- */
- set_dma_mode(dmachan, DMA_MODE_READ | 0x10);
- set_dma_addr(dmachan, dma_abs);
- set_dma_count(dmachan, lp->bufsiz);
- enable_dma(dmachan);
-
- /* If a packet is already coming in, this line is supposed to
- avoid receiving a partial packet.
- */
- wrtscc(lp->cardbase, cmd, R0, RES_Rx_CRC);
-
- /* Enable RX dma */
- wrtscc(lp->cardbase, cmd, R1,
- WT_RDY_ENAB | WT_FN_RDYFN | WT_RDY_RT | INT_ERR_Rx | EXT_INT_ENAB);
-
- restore_flags(flags);
-}
-
-static void setup_tx_dma(struct pi_local *lp, int length)
-{
- unsigned long dma_abs;
- unsigned long flags;
- unsigned long dmachan;
-
- save_flags(flags);
- cli();
-
- dmachan = lp->dmachan;
- dma_abs = (unsigned long) (lp->txdmabuf);
-
- if(!valid_dma_page(dma_abs, DMA_BUFF_SIZE + sizeof(struct mbuf)))
- panic("PI: TX buffer violates DMA boundary!");
-
- disable_dma(dmachan);
- /* Set DMA mode register to single transfers, incrementing address,
- * no auto init, reads
- */
- set_dma_mode(dmachan, DMA_MODE_WRITE);
- clear_dma_ff(dmachan);
- set_dma_addr(dmachan, dma_abs);
- /* output byte count */
- set_dma_count(dmachan, length);
-
- restore_flags(flags);
-}
-
-static void tdelay(struct pi_local *lp, int time)
-{
- int port;
- unsigned int t1;
- unsigned char sc;
-
- if (lp->base & 2) { /* If A channel */
- sc = SC1;
- t1 = time;
- port = lp->cardbase + TMR1;
- } else {
- sc = SC2;
- t1 = 10 * time; /* 10s of milliseconds for the B channel */
- port = lp->cardbase + TMR2;
- wrtscc(lp->cardbase, lp->base + CTL, R1, INT_ALL_Rx | EXT_INT_ENAB);
- }
-
- /* Setup timer sc */
- outb_p(sc | LSB_MSB | MODE0, lp->cardbase + TMRCMD);
-
- /* times 2 to make millisecs */
- outb_p((t1 << 1) & 0xFF, port);
- outb_p((t1 >> 7) & 0xFF, port);
-
- /* Enable correct int for timeout */
- wrtscc(lp->cardbase, lp->base + CTL, R15, CTSIE);
- wrtscc(lp->cardbase, lp->base + CTL, R0, RES_EXT_INT);
-}
-
-static void a_txint(struct pi_local *lp)
-{
- int cmd;
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- cmd = CTL + lp->base;
-
- switch (lp->tstate) {
- case IDLE:
- /* Transmitter idle. Find a frame for transmission */
- if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL) {
- rts(lp, OFF);
- restore_flags(flags);
- return;
- }
- /* If a buffer to send, we drop thru here */
- case DEFER:
- /* we may have deferred prev xmit attempt */
- /* Check DCD - debounce it
- * See Intel Microcommunications Handbook, p2-308
- */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) {
- lp->tstate = DEFER;
- tdelay(lp, 100);
- /* defer until DCD transition or timeout */
- wrtscc(lp->cardbase, cmd, R15, CTSIE | DCDIE);
- restore_flags(flags);
- return;
- }
- if (random() > lp->persist) {
- lp->tstate = DEFER;
- tdelay(lp, lp->slotime);
- restore_flags(flags);
- return;
- }
- /* Assert RTS early minimize collision window */
- wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);
- rts(lp, ON); /* Transmitter on */
- lp->tstate = ST_TXDELAY;
- tdelay(lp, lp->txdelay);
- restore_flags(flags);
- return;
- default:
- break;
- } /* end switch(lp->state) */
-
- restore_flags(flags);
-} /*a_txint */
-
-static void a_exint(struct pi_local *lp)
-{
- unsigned long flags;
- int cmd;
- char st;
- int length;
-
- save_flags(flags);
- cli(); /* disable interrupts */
-
- st = rdscc(lp->cardbase, lp->base + CTL, R0); /* Fetch status */
-
- /* reset external status latch */
- wrtscc(lp->cardbase, CTL + lp->base, R0, RES_EXT_INT);
- cmd = lp->base + CTL;
-
- if ((lp->rstate >= ACTIVE) && (st & BRK_ABRT)) {
- setup_rx_dma(lp);
- lp->rstate = ACTIVE;
- }
- switch (lp->tstate) {
- case ACTIVE:
- kfree_skb(lp->sndbuf);
- lp->sndbuf = NULL;
- lp->tstate = FLAGOUT;
- tdelay(lp, lp->squeldelay);
- break;
- case FLAGOUT:
- if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL) {
- /* Nothing to send - return to receive mode */
- lp->tstate = IDLE;
- rts(lp, OFF);
- restore_flags(flags);
- return;
- }
- /* NOTE - fall through if more to send */
- case ST_TXDELAY:
- /* Disable DMA chan */
- disable_dma(lp->dmachan);
-
- /* Set up for TX dma */
- wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);
-
-
- /* Get all chars */
- /* Strip KISS control byte */
- length = lp->sndbuf->len - 1;
- memcpy(lp->txdmabuf, &lp->sndbuf->data[1], length);
-
-
- /* Setup DMA controller for tx */
- setup_tx_dma(lp, length);
-
- /* select transmit interrupts to enable */
- /* Allow DMA on chan */
- enable_dma(lp->dmachan);
-
- /* reset CRC, Txint pend*/
- wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC | RES_Tx_P);
-
- /* allow Underrun int only */
- wrtscc(lp->cardbase, cmd, R15, TxUIE);
-
- /* Enable TX DMA */
- wrtscc(lp->cardbase, cmd, R1, WT_RDY_ENAB | WT_FN_RDYFN | EXT_INT_ENAB);
-
- /* Send CRC on underrun */
- wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);
-
-
- /* packet going out now */
- lp->tstate = ACTIVE;
- break;
- case DEFER:
- /* we have deferred prev xmit attempt
- * See Intel Microcommunications Handbook, p2-308
- */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) {
- lp->tstate = DEFER;
- tdelay(lp, 100);
- /* Defer until dcd transition or 100mS timeout */
- wrtscc(lp->cardbase, CTL + lp->base, R15, CTSIE | DCDIE);
- restore_flags(flags);
- return;
- }
- if (random() > lp->persist) {
- lp->tstate = DEFER;
- tdelay(lp, lp->slotime);
- restore_flags(flags);
- return;
- }
- /* Assert RTS early minimize collision window */
- wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);
- rts(lp, ON); /* Transmitter on */
- lp->tstate = ST_TXDELAY;
- tdelay(lp, lp->txdelay);
- restore_flags(flags);
- return;
- } /* switch(lp->tstate) */
-
- restore_flags(flags);
-} /* a_exint() */
-
-/* Receive interrupt handler for the A channel
- */
-static void a_rxint(struct net_device *dev, struct pi_local *lp)
-{
- unsigned long flags;
- int cmd;
- int bytecount;
- char rse;
- struct sk_buff *skb;
- int sksize, pkt_len;
- struct mbuf *cur_buf;
- unsigned char *cfix;
-
- save_flags(flags);
- cli(); /* disable interrupts */
- cmd = lp->base + CTL;
-
- rse = rdscc(lp->cardbase, cmd, R1); /* Get special condition bits from R1 */
- if (rse & Rx_OVR)
- lp->rstate = RXERROR;
-
- if (rse & END_FR) {
- /* If end of frame */
- /* figure length of frame from 8237 */
- clear_dma_ff(lp->dmachan);
- bytecount = lp->bufsiz - get_dma_residue(lp->dmachan);
-
- if ((rse & CRC_ERR) || (lp->rstate > ACTIVE) || (bytecount < 10)) {
- if ((bytecount >= 10) && (rse & CRC_ERR)) {
- lp->stats.rx_crc_errors++;
- }
- if (lp->rstate == RXERROR) {
- lp->stats.rx_errors++;
- lp->stats.rx_over_errors++;
- }
- /* Reset buffer pointers */
- lp->rstate = ACTIVE;
- setup_rx_dma(lp);
- } else {
- /* Here we have a valid frame */
- /* Toss 2 crc bytes , add one for KISS */
- pkt_len = lp->rcvbuf->cnt = bytecount - 2 + 1;
-
- /* Get buffer for next frame */
- cur_buf = lp->rcvbuf;
- switchbuffers(lp);
- setup_rx_dma(lp);
-
-
- /* Malloc up new buffer. */
- sksize = pkt_len;
-
- skb = dev_alloc_skb(sksize);
- if (skb == NULL) {
- printk(KERN_ERR "PI: %s: Memory squeeze, dropping packet.\n", dev->name);
- lp->stats.rx_dropped++;
- restore_flags(flags);
- return;
- }
- skb->dev = dev;
-
- /* KISS kludge - prefix with a 0 byte */
- cfix=skb_put(skb,pkt_len);
- *cfix++=0;
- /* 'skb->data' points to the start of sk_buff data area. */
- memcpy(cfix, (char *) cur_buf->data,
- pkt_len - 1);
- skb->protocol=htons(ETH_P_AX25);
- skb->mac.raw=skb->data;
- netif_rx(skb);
- lp->stats.rx_packets++;
- } /* end good frame */
- } /* end EOF check */
- wrtscc(lp->cardbase, lp->base + CTL, R0, ERR_RES); /* error reset */
- restore_flags(flags);
-}
-
-static void b_rxint(struct net_device *dev, struct pi_local *lp)
-{
- unsigned long flags;
- int cmd;
- char rse;
- struct sk_buff *skb;
- int sksize;
- int pkt_len;
- unsigned char *cfix;
-
- save_flags(flags);
- cli(); /* disable interrupts */
- cmd = CTL + lp->base;
-
- rse = rdscc(lp->cardbase, cmd, R1); /* get status byte from R1 */
-
- if ((rdscc(lp->cardbase, cmd, R0)) & Rx_CH_AV) {
- /* there is a char to be stored
- * read special condition bits before reading the data char
- */
- if (rse & Rx_OVR) {
- /* Rx overrun - toss buffer */
- /* reset buffer pointers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
-
- lp->rstate = RXERROR; /* set error flag */
- lp->stats.rx_errors++;
- lp->stats.rx_over_errors++;
- } else if (lp->rcvbuf->cnt >= lp->bufsiz) {
- /* Too large -- toss buffer */
- /* reset buffer pointers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- lp->rstate = TOOBIG;/* when set, chars are not stored */
- }
- /* ok, we can store the received character now */
- if (lp->rstate == ACTIVE) { /* If no errors... */
- *lp->rcp++ = rdscc(lp->cardbase, cmd, R8); /* char to rcv buff */
- lp->rcvbuf->cnt++; /* bump count */
- } else {
- /* got to empty FIFO */
- (void) rdscc(lp->cardbase, cmd, R8);
- wrtscc(lp->cardbase, cmd, R0, ERR_RES); /* reset err latch */
- lp->rstate = ACTIVE;
- }
- }
- if (rse & END_FR) {
- /* END OF FRAME -- Make sure Rx was active */
- if (lp->rcvbuf->cnt > 0) {
- if ((rse & CRC_ERR) || (lp->rstate > ACTIVE) || (lp->rcvbuf->cnt < 10)) {
- if ((lp->rcvbuf->cnt >= 10) && (rse & CRC_ERR)) {
- lp->stats.rx_crc_errors++;
- }
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- } else {
- /* Here we have a valid frame */
- pkt_len = lp->rcvbuf->cnt -= 2; /* Toss 2 crc bytes */
- pkt_len += 1; /* Make room for KISS control byte */
-
- /* Malloc up new buffer. */
- sksize = pkt_len;
- skb = dev_alloc_skb(sksize);
- if (skb == NULL) {
- printk(KERN_ERR "PI: %s: Memory squeeze, dropping packet.\n", dev->name);
- lp->stats.rx_dropped++;
- restore_flags(flags);
- return;
- }
- skb->dev = dev;
-
- /* KISS kludge - prefix with a 0 byte */
- cfix=skb_put(skb,pkt_len);
- *cfix++=0;
- /* 'skb->data' points to the start of sk_buff data area. */
- memcpy(cfix, lp->rcvbuf->data, pkt_len - 1);
- skb->protocol=ntohs(ETH_P_AX25);
- skb->mac.raw=skb->data;
- netif_rx(skb);
- lp->stats.rx_packets++;
- /* packet queued - initialize buffer for next frame */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
-
- } /* end good frame queued */
- } /* end check for active receive upon EOF */
- lp->rstate = ACTIVE; /* and clear error status */
- } /* end EOF check */
- restore_flags(flags);
-}
-
-
-static void b_txint(struct pi_local *lp)
-{
- unsigned long flags;
- int cmd;
- unsigned char c;
-
- save_flags(flags);
- cli();
- cmd = CTL + lp->base;
-
- switch (lp->tstate) {
- case CRCOUT:
- lp->tstate = FLAGOUT;
- tdelay(lp, lp->squeldelay);
- restore_flags(flags);
- return;
- case IDLE:
- /* Transmitter idle. Find a frame for transmission */
- if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL) {
- /* Nothing to send - return to receive mode
- * Tx OFF now - flag should have gone
- */
- rts(lp, OFF);
-
- restore_flags(flags);
- return;
- }
- lp->txptr = lp->sndbuf->data;
- lp->txptr++; /* Ignore KISS control byte */
- lp->txcnt = (int) lp->sndbuf->len - 1;
- /* If a buffer to send, we drop thru here */
- case DEFER: /* we may have deferred prev xmit attempt */
- /* Check DCD - debounce it */
- /* See Intel Microcommunications Handbook, p2-308 */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) {
- lp->tstate = DEFER;
- tdelay(lp, 100);
- /* defer until DCD transition or timeout */
- wrtscc(lp->cardbase, cmd, R15, CTSIE | DCDIE);
- restore_flags(flags);
- return;
- }
- if (random() > lp->persist) {
- lp->tstate = DEFER;
- tdelay(lp, lp->slotime);
- restore_flags(flags);
- return;
- }
- rts(lp, ON); /* Transmitter on */
- lp->tstate = ST_TXDELAY;
- tdelay(lp, lp->txdelay);
- restore_flags(flags);
- return;
-
- case ACTIVE:
- /* Here we are actively sending a frame */
- if (lp->txcnt--) {
- c = *lp->txptr++;
- /* next char is gone */
- wrtscc(lp->cardbase, cmd, R8, c);
- /* stuffing a char satisfies Interrupt condition */
- } else {
- /* No more to send */
- kfree_skb(lp->sndbuf);
- lp->sndbuf = NULL;
- if ((rdscc(lp->cardbase, cmd, R0) & 0x40)) {
- /* Did we underrun? */
- /* unexpected underrun */
- lp->stats.tx_errors++;
- lp->stats.tx_fifo_errors++;
- wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);
- lp->tstate = FLAGOUT;
- tdelay(lp, lp->squeldelay);
- restore_flags(flags);
- return;
- }
- lp->tstate = UNDERRUN; /* Now we expect to underrun */
- /* Send flags on underrun */
- if (lp->speed) { /* If internally clocked */
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);
- } else {
- wrtscc(lp->cardbase, cmd, R10, CRCPS);
- }
- wrtscc(lp->cardbase, cmd, R0, RES_Tx_P); /* reset Tx Int Pend */
- }
- restore_flags(flags);
- return; /* back to wait for interrupt */
- } /* end switch */
- restore_flags(flags);
-}
-
-/* Pi SIO External/Status interrupts (for the B channel)
- * This can be caused by a receiver abort, or a Tx UNDERRUN/EOM.
- * Receiver automatically goes to Hunt on an abort.
- *
- * If the Tx Underrun interrupt hits, change state and
- * issue a reset command for it, and return.
- */
-static void b_exint(struct pi_local *lp)
-{
- unsigned long flags;
- char st;
- int cmd;
- char c;
-
- cmd = CTL + lp->base;
- save_flags(flags);
- cli(); /* disable interrupts */
- st = rdscc(lp->cardbase, cmd, R0); /* Fetch status */
- /* reset external status latch */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
-
-
- switch (lp->tstate) {
- case ACTIVE: /* Unexpected underrun */
- kfree_skb(lp->sndbuf);
- lp->sndbuf = NULL;
- wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);
- lp->tstate = FLAGOUT;
- lp->stats.tx_errors++;
- lp->stats.tx_fifo_errors++;
- tdelay(lp, lp->squeldelay);
- restore_flags(flags);
- return;
- case UNDERRUN:
- lp->tstate = CRCOUT;
- restore_flags(flags);
- return;
- case FLAGOUT:
- /* Find a frame for transmission */
- if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL) {
- /* Nothing to send - return to receive mode
- * Tx OFF now - flag should have gone
- */
- rts(lp, OFF);
- lp->tstate = IDLE;
- restore_flags(flags);
- return;
- }
- lp->txptr = lp->sndbuf->data;
- lp->txptr++; /* Ignore KISS control byte */
- lp->txcnt = (int) lp->sndbuf->len - 1;
- /* Get first char to send */
- lp->txcnt--;
- c = *lp->txptr++;
- wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC); /* reset for next frame */
-
- /* Send abort on underrun */
- if (lp->speed) { /* If internally clocked */
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI | ABUNDER);
- } else {
- wrtscc(lp->cardbase, cmd, R10, CRCPS | ABUNDER);
- }
-
- wrtscc(lp->cardbase, cmd, R8, c); /* First char out now */
- wrtscc(lp->cardbase, cmd, R0, RES_EOM_L); /* Reset end of message latch */
-
-#ifdef STUFF2
- /* stuff an extra one if we can */
- if (lp->txcnt) {
- lp->txcnt--;
- c = *lp->txptr++;
- /* Wait for tx buffer empty */
- while((rdscc(lp->cardbase, cmd, R0) & 0x04) == 0)
- ;
- wrtscc(lp->cardbase, cmd, R8, c);
- }
-#endif
-
- /* select transmit interrupts to enable */
-
- wrtscc(lp->cardbase, cmd, R15, TxUIE); /* allow Underrun int only */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- wrtscc(lp->cardbase, cmd, R1, TxINT_ENAB | EXT_INT_ENAB); /* Tx/Ext ints */
-
- lp->tstate = ACTIVE; /* char going out now */
- restore_flags(flags);
- return;
-
- case DEFER:
- /* Check DCD - debounce it
- * See Intel Microcommunications Handbook, p2-308
- */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) {
- lp->tstate = DEFER;
- tdelay(lp, 100);
- /* defer until DCD transition or timeout */
- wrtscc(lp->cardbase, cmd, R15, CTSIE | DCDIE);
- restore_flags(flags);
- return;
- }
- if (random() > lp->persist) {
- lp->tstate = DEFER;
- tdelay(lp, lp->slotime);
- restore_flags(flags);
- return;
- }
- rts(lp, ON); /* Transmitter on */
- lp->tstate = ST_TXDELAY;
- tdelay(lp, lp->txdelay);
- restore_flags(flags);
- return;
-
- case ST_TXDELAY:
-
- /* Get first char to send */
- lp->txcnt--;
- c = *lp->txptr++;
- wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC); /* reset for next frame */
-
- /* Send abort on underrun */
- if (lp->speed) { /* If internally clocked */
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI | ABUNDER);
- } else {
- wrtscc(lp->cardbase, cmd, R10, CRCPS | ABUNDER);
- }
-
- wrtscc(lp->cardbase, cmd, R8, c); /* First char out now */
- wrtscc(lp->cardbase, cmd, R0, RES_EOM_L); /* Reset end of message latch */
-
-#ifdef STUFF2
- /* stuff an extra one if we can */
- if (lp->txcnt) {
- lp->txcnt--;
- c = *lp->txptr++;
- /* Wait for tx buffer empty */
- while((rdscc(lp->cardbase, cmd, R0) & 0x04) == 0)
- ;
- wrtscc(lp->cardbase, cmd, R8, c);
- }
-#endif
-
- /* select transmit interrupts to enable */
-
- wrtscc(lp->cardbase, cmd, R15, TxUIE); /* allow Underrun int only */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- /* Tx/Extern ints on */
- wrtscc(lp->cardbase, cmd, R1, TxINT_ENAB | EXT_INT_ENAB);
-
- lp->tstate = ACTIVE; /* char going out now */
- restore_flags(flags);
- return;
- }
-
- /* Receive Mode only
- * This triggers when hunt mode is entered, & since an ABORT
- * automatically enters hunt mode, we use that to clean up
- * any waiting garbage
- */
- if ((lp->rstate == ACTIVE) && (st & BRK_ABRT)) {
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0; /* rewind on DCD transition */
- }
- restore_flags(flags);
-}
-
-/* Probe for a PI card. */
-/* This routine also initializes the timer chip */
-
-static int __init hw_probe(int ioaddr)
-{
- int time = 1000; /* Number of milliseconds for test */
- unsigned long start_time, end_time;
-
- int base, tmr0, tmr1, tmrcmd;
- int a = 1;
- int b = 1;
-
- base = ioaddr & 0x3f0;
- tmr0 = TMR0 + base;
- tmr1 = TMR1 + base;
- tmrcmd = TMRCMD + base;
-
- /* Set up counter chip timer 0 for 500 uS period square wave */
- /* assuming a 3.68 mhz clock for now */
- outb_p(SC0 | LSB_MSB | MODE3, tmrcmd);
- outb_p(922 & 0xFF, tmr0);
- outb_p(922 >> 8, tmr0);
-
- /* Setup timer control word for timer 1*/
- outb_p(SC1 | LSB_MSB | MODE0, tmrcmd);
- outb_p((time << 1) & 0xFF, tmr1);
- outb_p((time >> 7) & 0XFF, tmr1);
-
- /* wait until counter reg is loaded */
- do {
- /* Latch count for reading */
- outb_p(SC1, tmrcmd);
- a = inb_p(tmr1);
- b = inb_p(tmr1);
- } while (b == 0);
- start_time = jiffies;
- while (b != 0) {
- /* Latch count for reading */
- outb_p(SC1, tmrcmd);
- a = inb_p(tmr1);
- b = inb_p(tmr1);
- end_time = jiffies;
- /* Don't wait forever - there may be no card here */
- if ((end_time - start_time) > 200)
- return 0; /* No card found */
- }
- end_time = jiffies;
- /* 87 jiffies, for a 3.68 mhz clock, half that for a double speed clock */
- if ((end_time - start_time) > 65) {
- return (1); /* PI card found */
- } else {
- /* Faster crystal - tmr0 needs adjusting */
- /* Set up counter chip */
- /* 500 uS square wave */
- outb_p(SC0 | LSB_MSB | MODE3, tmrcmd);
- outb_p(1844 & 0xFF, tmr0);
- outb_p(1844 >> 8, tmr0);
- return (2); /* PI2 card found */
- }
-}
-
-static void rts(struct pi_local *lp, int x)
-{
- int tc;
- long br;
- int cmd;
- int dummy;
-
- /* assumes interrupts are off */
- cmd = CTL + lp->base;
-
- /* Reprogram BRG and turn on transmitter to send flags */
- if (x == ON) { /* Turn Tx ON and Receive OFF */
- /* Exints off first to avoid abort int */
- wrtscc(lp->cardbase, cmd, R15, 0);
- wrtscc(lp->cardbase, cmd, R3, Rx8); /* Rx off */
- lp->rstate = IDLE;
- if (cmd & 2) { /* if channel a */
- /* Set up for TX dma */
- wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);
- } else {
- wrtscc(lp->cardbase, cmd, R1, 0); /* No interrupts */
- }
-
- if (!lp->clockmode) {
- if (lp->speed) { /* if internally clocked */
- br = lp->speed; /* get desired speed */
- tc = (lp->xtal / br) - 2; /* calc 1X BRG divisor */
- wrtscc(lp->cardbase, cmd, R12, tc & 0xFF); /* lower byte */
- wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xFF); /* upper byte */
- }
- }
- wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8 | DTR);
- /* Transmitter now on */
- } else { /* Tx OFF and Rx ON */
- lp->tstate = IDLE;
- wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR); /* TX off */
-
- if (!lp->clockmode) {
- if (lp->speed) { /* if internally clocked */
- /* Reprogram BRG for 32x clock for receive DPLL */
- /* BRG off, keep Pclk source */
- wrtscc(lp->cardbase, cmd, R14, BRSRC);
- br = lp->speed; /* get desired speed */
- /* calc 32X BRG divisor */
- tc = ((lp->xtal / 32) / br) - 2;
- wrtscc(lp->cardbase, cmd, R12, tc & 0xFF); /* lower byte */
- wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xFF); /* upper byte */
- /* SEARCH mode, BRG source */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | SEARCH);
- /* Enable the BRG */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | BRENABL);
- }
- }
- /* Flush rx fifo */
- wrtscc(lp->cardbase, cmd, R3, Rx8); /* Make sure rx is off */
- wrtscc(lp->cardbase, cmd, R0, ERR_RES); /* reset err latch */
- dummy = rdscc(lp->cardbase, cmd, R1); /* get status byte from R1 */
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
-
- (void) rdscc(lp->cardbase, cmd, R8);
-
- /* Now, turn on the receiver and hunt for a flag */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | Rx8);
- lp->rstate = ACTIVE; /* Normal state */
-
- if (cmd & 2) { /* if channel a */
- setup_rx_dma(lp);
- } else {
- /* reset buffer pointers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- wrtscc(lp->cardbase, cmd, R1, (INT_ALL_Rx | EXT_INT_ENAB));
- }
- wrtscc(lp->cardbase, cmd, R15, BRKIE); /* allow ABORT int */
- }
-}
-
-static void scc_init(struct net_device *dev)
-{
- unsigned long flags;
- struct pi_local *lp = (struct pi_local *) dev->priv;
-
- int tc;
- long br;
- register int cmd;
-
- /* Initialize 8530 channel for SDLC operation */
-
- cmd = CTL + lp->base;
- save_flags(flags);
- cli();
-
- switch (cmd & CHANA) {
- case CHANA:
- wrtscc(lp->cardbase, cmd, R9, CHRA); /* Reset channel A */
- wrtscc(lp->cardbase, cmd, R2, 0xff); /* Initialize interrupt vector */
- break;
- default:
- wrtscc(lp->cardbase, cmd, R9, CHRB); /* Reset channel B */
- break;
- }
-
- /* Deselect all Rx and Tx interrupts */
- wrtscc(lp->cardbase, cmd, R1, 0);
-
- /* Turn off external interrupts (like CTS/CD) */
- wrtscc(lp->cardbase, cmd, R15, 0);
-
- /* X1 clock, SDLC mode */
- wrtscc(lp->cardbase, cmd, R4, SDLC | X1CLK);
-
- /* Tx/Rx parameters */
- if (lp->speed) { /* Use internal clocking */
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);
- if (!lp->clockmode)
- /* Tx Clk from BRG. Rcv Clk from DPLL, TRxC pin outputs DPLL */
- wrtscc(lp->cardbase, cmd, R11, TCBR | RCDPLL | TRxCDP | TRxCOI);
- else
- /* Tx Clk from DPLL, Rcv Clk from DPLL, TRxC Outputs BRG */
- wrtscc(lp->cardbase, cmd, R11, TCDPLL | RCDPLL | TRxCBR | TRxCOI);
- } else { /* Use external clocking */
- wrtscc(lp->cardbase, cmd, R10, CRCPS);
- /* Tx Clk from Trxcl. Rcv Clk from Rtxcl, TRxC pin is input */
- wrtscc(lp->cardbase, cmd, R11, TCTRxCP);
- }
-
- /* Null out SDLC start address */
- wrtscc(lp->cardbase, cmd, R6, 0);
-
- /* SDLC flag */
- wrtscc(lp->cardbase, cmd, R7, FLAG);
-
- /* Set up the Transmitter but don't enable it
- * DTR, 8 bit TX chars only
- */
- wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR);
-
- /* Receiver initial setup */
- wrtscc(lp->cardbase, cmd, R3, Rx8); /* 8 bits/char */
-
- /* Setting up BRG now - turn it off first */
- wrtscc(lp->cardbase, cmd, R14, BRSRC); /* BRG off, keep Pclk source */
-
- /* set the 32x time constant for the BRG in Receive mode */
-
- if (lp->speed) {
- br = lp->speed; /* get desired speed */
- tc = ((lp->xtal / 32) / br) - 2; /* calc 32X BRG divisor */
- } else {
- tc = 14;
- }
-
- wrtscc(lp->cardbase, cmd, R12, tc & 0xFF); /* lower byte */
- wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xFF); /* upper byte */
-
- /* Following subroutine sets up and ENABLES the receiver */
- rts(lp, OFF); /* TX OFF and RX ON */
-
- if (lp->speed) {
- /* DPLL frm BRG, BRG src PCLK */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | SSBR);
- } else {
- /* DPLL frm rtxc,BRG src PCLK */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | SSRTxC);
- }
- wrtscc(lp->cardbase, cmd, R14, BRSRC | SEARCH); /* SEARCH mode, keep BRG src */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | BRENABL); /* Enable the BRG */
-
- if (!(cmd & 2)) /* if channel b */
- wrtscc(lp->cardbase, cmd, R1, (INT_ALL_Rx | EXT_INT_ENAB));
-
- wrtscc(lp->cardbase, cmd, R15, BRKIE); /* ABORT int */
-
- /* Now, turn on the receiver and hunt for a flag */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | RxCRC_ENAB | Rx8);
-
- restore_flags(flags);
-}
-
-static void chipset_init(struct net_device *dev)
-{
- int cardbase;
- unsigned long flags;
-
- cardbase = dev->base_addr & 0x3f0;
-
- save_flags(flags);
- cli();
- wrtscc(cardbase, dev->base_addr + CTL, R9, FHWRES); /* Hardware reset */
- /* Disable interrupts with master interrupt ctrl reg */
- wrtscc(cardbase, dev->base_addr + CTL, R9, 0);
- restore_flags(flags);
-
-}
-
-
-int __init pi2_init(void)
-{
- int *port;
- int ioaddr = 0;
- int card_type = 0;
- int ports[] = {0x380, 0x300, 0x320, 0x340, 0x360, 0x3a0, 0};
-
- printk(KERN_INFO "PI: V0.8 ALPHA April 23 1995 David Perry (dp@hydra.carleton.ca)\n");
-
- /* Only one card supported for now */
- for (port = &ports[0]; *port && !card_type; port++) {
- ioaddr = *port;
-
- if (check_region(ioaddr, PI_TOTAL_SIZE) == 0) {
- printk(KERN_INFO "PI: Probing for card at address %#3x\n",ioaddr);
- card_type = hw_probe(ioaddr);
- }
- }
-
- switch (card_type) {
- case 1:
- printk(KERN_INFO "PI: Found a PI card at address %#3x\n", ioaddr);
- break;
- case 2:
- printk(KERN_INFO "PI: Found a PI2 card at address %#3x\n", ioaddr);
- break;
- default:
- printk(KERN_ERR "PI: ERROR: No card found\n");
- return -EIO;
- }
-
- /* Link a couple of device structures into the chain */
- /* For the A port */
- /* Allocate space for 4 buffers even though we only need 3,
- because one of them may cross a DMA page boundary and
- be rejected by get_dma_buffer().
- */
- register_netdev(&pi0a);
-
- pi0a.priv = kmalloc(sizeof(struct pi_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA);
-
- pi0a.dma = PI_DMA;
- pi0a.base_addr = ioaddr + 2;
- pi0a.irq = 0;
-
- /* And the B port */
- register_netdev(&pi0b);
- pi0b.base_addr = ioaddr;
- pi0b.irq = 0;
-
- pi0b.priv = kmalloc(sizeof(struct pi_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA);
-
- /* Now initialize them */
- pi_probe(&pi0a, card_type);
- pi_probe(&pi0b, card_type);
-
- pi0b.irq = pi0a.irq; /* IRQ is shared */
-
- return 0;
-}
-
-static int valid_dma_page(unsigned long addr, unsigned long dev_buffsize)
-{
- if (((addr & 0xffff) + dev_buffsize) <= 0x10000)
- return 1;
- else
- return 0;
-}
-
-static int pi_set_mac_address(struct net_device *dev, void *addr)
-{
- struct sockaddr *sa = (struct sockaddr *)addr;
- memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); /* addr is an AX.25 shifted ASCII */
- return 0; /* mac address */
-}
-
-/* Allocate a buffer which does not cross a DMA page boundary */
-static char *
-get_dma_buffer(unsigned long *mem_ptr)
-{
- char *ret;
-
- ret = (char *)*mem_ptr;
-
- if(!valid_dma_page(*mem_ptr, DMA_BUFF_SIZE + sizeof(struct mbuf))){
- *mem_ptr += (DMA_BUFF_SIZE + sizeof(struct mbuf));
- ret = (char *)*mem_ptr;
- }
- *mem_ptr += (DMA_BUFF_SIZE + sizeof(struct mbuf));
- return (ret);
-}
-
-static int pi_probe(struct net_device *dev, int card_type)
-{
- short ioaddr;
- struct pi_local *lp;
- unsigned long flags;
- unsigned long mem_ptr;
-
- ioaddr = dev->base_addr;
-
- /* Initialize the device structure. */
- /* Must be done before chipset_init */
- /* Make certain the data structures used by the PI2 are aligned. */
- dev->priv = (void *) (((int) dev->priv + 7) & ~7);
- lp = (struct pi_local *) dev->priv;
-
- memset(dev->priv, 0, sizeof(struct pi_local));
-
- /* Allocate some buffers which do not cross DMA page boundaries */
- mem_ptr = (unsigned long) dev->priv + sizeof(struct pi_local);
- lp->txdmabuf = get_dma_buffer(&mem_ptr);
- lp->rxdmabuf1 = (struct mbuf *) get_dma_buffer(&mem_ptr);
- lp->rxdmabuf2 = (struct mbuf *) get_dma_buffer(&mem_ptr);
-
- /* Initialize rx buffer */
- lp->rcvbuf = lp->rxdmabuf1;
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
-
- /* Initialize the transmit queue head structure */
- skb_queue_head_init(&lp->sndq);
-
- /* These need to be initialized before scc_init is called. */
- if (card_type == 1)
- lp->xtal = (unsigned long) SINGLE / 2;
- else
- lp->xtal = (unsigned long) DOUBLE / 2;
- lp->base = dev->base_addr;
- lp->cardbase = dev->base_addr & 0x3f0;
- if (dev->base_addr & CHANA) {
- lp->speed = DEF_A_SPEED;
- /* default channel access Params */
- lp->txdelay = DEF_A_TXDELAY;
- lp->persist = DEF_A_PERSIST;
- lp->slotime = DEF_A_SLOTIME;
- lp->squeldelay = DEF_A_SQUELDELAY;
- lp->clockmode = DEF_A_CLOCKMODE;
-
- } else {
- lp->speed = DEF_B_SPEED;
- /* default channel access Params */
- lp->txdelay = DEF_B_TXDELAY;
- lp->persist = DEF_B_PERSIST;
- lp->slotime = DEF_B_SLOTIME;
- lp->squeldelay = DEF_B_SQUELDELAY;
- lp->clockmode = DEF_B_CLOCKMODE;
- }
- lp->bufsiz = DMA_BUFF_SIZE;
- lp->tstate = IDLE;
-
- chipset_init(dev);
-
- if (dev->base_addr & CHANA) { /* Do these things only for the A port */
- /* Note that a single IRQ services 2 devices (A and B channels) */
-
- lp->dmachan = dev->dma;
- if (lp->dmachan < 1 || lp->dmachan > 3)
- printk(KERN_ERR "PI: DMA channel %d out of range\n", lp->dmachan);
-
- /* chipset_init() was already called */
-
- if (dev->irq < 2) {
- autoirq_setup(0);
- save_flags(flags);
- cli();
- wrtscc(lp->cardbase, CTL + lp->base, R1, EXT_INT_ENAB);
- /* enable PI card interrupts */
- wrtscc(lp->cardbase, CTL + lp->base, R9, MIE | NV);
- restore_flags(flags);
- /* request a timer interrupt for 1 mS hence */
- tdelay(lp, 1);
- /* 20 "jiffies" should be plenty of time... */
- dev->irq = autoirq_report(20);
- if (!dev->irq) {
- printk(KERN_ERR "PI: Failed to detect IRQ line.\n");
- }
- save_flags(flags);
- cli();
- wrtscc(lp->cardbase, dev->base_addr + CTL, R9, FHWRES); /* Hardware reset */
- /* Disable interrupts with master interrupt ctrl reg */
- wrtscc(lp->cardbase, dev->base_addr + CTL, R9, 0);
- restore_flags(flags);
- }
-
- printk(KERN_INFO "PI: Autodetected IRQ %d, assuming DMA %d.\n",
- dev->irq, dev->dma);
-
- /* This board has jumpered interrupts. Snarf the interrupt vector
- now. There is no point in waiting since no other device can use
- the interrupt, and this marks the 'irqaction' as busy. */
- {
- int irqval = request_irq(dev->irq, &pi_interrupt,0, "pi2", dev);
- if (irqval) {
- printk(KERN_ERR "PI: unable to get IRQ %d (irqval=%d).\n",
- dev->irq, irqval);
- return -EAGAIN;
- }
- }
-
- /* Grab the region */
- request_region(ioaddr & 0x3f0, PI_TOTAL_SIZE, "pi2" );
-
-
- } /* Only for A port */
- dev->open = pi_open;
- dev->stop = pi_close;
- dev->do_ioctl = pi_ioctl;
- dev->hard_start_xmit = pi_send_packet;
- dev->get_stats = pi_get_stats;
-
- /* Fill in the fields of the device structure */
-
- dev_init_buffers(dev);
-
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax25_encapsulate;
- dev->rebuild_header = ax25_rebuild_header;
-#endif
-
- dev->set_mac_address = pi_set_mac_address;
-
- dev->type = ARPHRD_AX25; /* AF_AX25 device */
- dev->hard_header_len = 73; /* We do digipeaters now */
- dev->mtu = 1500; /* eth_mtu is the default */
- dev->addr_len = 7; /* sizeof an ax.25 address */
- memcpy(dev->broadcast, ax25_bcast, 7);
- memcpy(dev->dev_addr, ax25_test, 7);
-
- /* New-style flags. */
- dev->flags = 0;
- return 0;
-}
-
-/* Open/initialize the board. This is called (in the current kernel)
- sometime after booting when the 'ifconfig' program is run.
-
- This routine should set everything up anew at each open, even
- registers that "should" only need to be set once at boot, so that
- there is non-reboot way to recover if something goes wrong.
- */
-static int pi_open(struct net_device *dev)
-{
- unsigned long flags;
- static first_time = 1;
-
- struct pi_local *lp = (struct pi_local *) dev->priv;
-
- if (dev->base_addr & 2) { /* if A channel */
- if (first_time) {
- if (request_dma(dev->dma,"pi2")) {
- free_irq(dev->irq, dev);
- return -EAGAIN;
- }
- }
- /* Reset the hardware here. */
- chipset_init(dev);
- }
- lp->tstate = IDLE;
-
- if (dev->base_addr & 2) { /* if A channel */
- scc_init(dev); /* Called once for each channel */
- scc_init(dev->next);
- }
- /* master interrupt enable */
- save_flags(flags);
- cli();
- wrtscc(lp->cardbase, CTL + lp->base, R9, MIE | NV);
- restore_flags(flags);
-
- lp->open_time = jiffies;
-
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
- first_time = 0;
-
- MOD_INC_USE_COUNT;
-
- return 0;
-}
-
-static int pi_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
- struct pi_local *lp = (struct pi_local *) dev->priv;
-
- hardware_send_packet(lp, skb);
- dev->trans_start = jiffies;
-
- return 0;
-}
-
-/* The typical workload of the driver:
- Handle the network interface interrupts. */
-static void pi_interrupt(int reg_ptr, void *dev_id, struct pt_regs *regs)
-{
-/* int irq = -(((struct pt_regs *) reg_ptr)->orig_eax + 2);*/
- struct pi_local *lp;
- int st;
- unsigned long flags;
-
-/* dev_b = dev_a->next; Relies on the order defined in Space.c */
-
-#if 0
- if (dev_a == NULL) {
- printk(KERN_ERR "PI: pi_interrupt(): irq %d for unknown device.\n", irq);
- return;
- }
-#endif
- /* Read interrupt status register (only valid from channel A)
- * Process all pending interrupts in while loop
- */
- lp = (struct pi_local *) pi0a.priv; /* Assume channel A */
- while ((st = rdscc(lp->cardbase, pi0a.base_addr | CHANA | CTL, R3)) != 0) {
- if (st & CHBTxIP) {
- /* Channel B Transmit Int Pending */
- lp = (struct pi_local *) pi0b.priv;
- b_txint(lp);
- } else if (st & CHARxIP) {
- /* Channel A Rcv Interrupt Pending */
- lp = (struct pi_local *) pi0a.priv;
- a_rxint(&pi0a, lp);
- } else if (st & CHATxIP) {
- /* Channel A Transmit Int Pending */
- lp = (struct pi_local *) pi0a.priv;
- a_txint(lp);
- } else if (st & CHAEXT) {
- /* Channel A External Status Int */
- lp = (struct pi_local *) pi0a.priv;
- a_exint(lp);
- } else if (st & CHBRxIP) {
- /* Channel B Rcv Interrupt Pending */
- lp = (struct pi_local *) pi0b.priv;
- b_rxint(&pi0b, lp);
- } else if (st & CHBEXT) {
- /* Channel B External Status Int */
- lp = (struct pi_local *) pi0b.priv;
- b_exint(lp);
- }
- /* Reset highest interrupt under service */
- save_flags(flags);
- cli();
- wrtscc(lp->cardbase, lp->base + CTL, R0, RES_H_IUS);
- restore_flags(flags);
- } /* End of while loop on int processing */
- return;
-}
-
-/* The inverse routine to pi_open(). */
-static int pi_close(struct net_device *dev)
-{
- unsigned long flags;
- struct pi_local *lp;
- struct sk_buff *ptr;
-
- save_flags(flags);
- cli();
-
- lp = (struct pi_local *) dev->priv;
- ptr = NULL;
-
- chipset_init(dev); /* reset the scc */
- disable_dma(lp->dmachan);
-
- lp->open_time = 0;
-
- dev->tbusy = 1;
- dev->start = 0;
-
- /* Free any buffers left in the hardware transmit queue */
- while ((ptr = skb_dequeue(&lp->sndq)) != NULL)
- kfree_skb(ptr);
-
- restore_flags(flags);
-
- MOD_DEC_USE_COUNT;
-
- return 0;
-}
-
-static int pi_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
- unsigned long flags;
- struct pi_req rq;
- struct pi_local *lp = (struct pi_local *) dev->priv;
-
- int ret = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct pi_req));
- if (ret)
- return ret;
-
- if(cmd!=SIOCDEVPRIVATE)
- return -EINVAL;
-
- copy_from_user(&rq, ifr->ifr_data, sizeof(struct pi_req));
-
- switch (rq.cmd) {
- case SIOCSPIPARAM:
-
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- save_flags(flags);
- cli();
- lp->txdelay = rq.txdelay;
- lp->persist = rq.persist;
- lp->slotime = rq.slotime;
- lp->squeldelay = rq.squeldelay;
- lp->clockmode = rq.clockmode;
- lp->speed = rq.speed;
- pi_open(&pi0a); /* both channels get reset %%% */
- restore_flags(flags);
- ret = 0;
- break;
-
- case SIOCSPIDMA:
-
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- ret = 0;
- if (dev->base_addr & 2) { /* if A channel */
- if (rq.dmachan < 1 || rq.dmachan > 3)
- return -EINVAL;
- save_flags(flags);
- cli();
- pi_close(dev);
- free_dma(lp->dmachan);
- dev->dma = lp->dmachan = rq.dmachan;
- if (request_dma(lp->dmachan,"pi2"))
- ret = -EAGAIN;
- pi_open(dev);
- restore_flags(flags);
- }
- break;
-
- case SIOCSPIIRQ:
- ret = -EINVAL; /* add this later */
- break;
-
- case SIOCGPIPARAM:
- case SIOCGPIDMA:
- case SIOCGPIIRQ:
-
- rq.speed = lp->speed;
- rq.txdelay = lp->txdelay;
- rq.persist = lp->persist;
- rq.slotime = lp->slotime;
- rq.squeldelay = lp->squeldelay;
- rq.clockmode = lp->clockmode;
- rq.dmachan = lp->dmachan;
- rq.irq = dev->irq;
- copy_to_user(ifr->ifr_data, &rq, sizeof(struct pi_req));
- ret = 0;
- break;
-
- default:
- ret = -EINVAL;
- }
- return ret;
-}
-
-/* Get the current statistics. This may be called with the card open or
- closed. */
-static struct net_device_stats *pi_get_stats(struct net_device *dev)
-{
- struct pi_local *lp = (struct pi_local *) dev->priv;
-
- return &lp->stats;
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-MODULE_AUTHOR("David Perry <dp@hydra.carleton.ca>");
-MODULE_DESCRIPTION("AX.25 driver for the Ottawa PI and PI/2 HDLC cards");
-
-int init_module(void)
-{
- return pi2_init();
-}
-
-void cleanup_module(void)
-{
- free_irq(pi0a.irq, &pi0a); /* IRQs and IO Ports are shared */
- release_region(pi0a.base_addr & 0x3f0, PI_TOTAL_SIZE);
-
- kfree(pi0a.priv);
- pi0a.priv = NULL;
- unregister_netdev(&pi0a);
-
- kfree(pi0b.priv);
- pi0b.priv = NULL;
- unregister_netdev(&pi0b);
-}
-#endif
diff --git a/drivers/net/hamradio/pt.c b/drivers/net/hamradio/pt.c
deleted file mode 100644
index ec9b196bb..000000000
--- a/drivers/net/hamradio/pt.c
+++ /dev/null
@@ -1,1777 +0,0 @@
-#undef PT_DEBUG 1
-/*
- * pt.c: Linux device driver for the Gracilis PackeTwin.
- * Copyright (c) 1995 Craig Small VK2XLZ (vk2xlz@vk2xlz.ampr.org.)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge MA 02139, USA.
- *
- * This driver is largely based upon the PI driver by David Perry.
- *
- * Revision History
- * 23/02/95 cs Started again on driver, last one scrapped
- * 27/02/95 cs Program works, we have chan A only. Tx stays on
- * 28/02/95 cs Fix Tx problem (& TxUIE instead of | )
- * Fix Chan B Tx timer problem, used TMR2 instead of TMR1
- * 03/03/95 cs Painfully found out (after 3 days) SERIAL_CFG is write only
- * created image of it and DMA_CFG
- * 21/06/95 cs Upgraded to suit PI driver 0.8 ALPHA
- * 22/08/95 cs Changed it all around to make it like pi driver
- * 23/08/95 cs It now works, got caught again by TMR2 and we must have
- * auto-enables for daughter boards.
- * 07/10/95 cs Fixed for 1.3.30 (hopefully)
- * 26/11/95 cs Fixed for 1.3.43, ala 29/10 for pi2.c by ac
- * 21/12/95 cs Got rid of those nasty warnings when compiling, for 1.3.48
- * 08/08/96 jsn Convert to use as a module. Removed send_kiss, empty_scc and
- * pt_loopback functions - they were unused.
- * 13/12/96 jsn Fixed to match Linux networking changes.
- */
-
-/*
- * default configuration of the PackeTwin,
- * ie What Craig uses his PT for.
- */
-#define PT_DMA 3
-
-#define DEF_A_SPEED 4800 /* 4800 baud */
-#define DEF_A_TXDELAY 350 /* 350 mS */
-#define DEF_A_PERSIST 64 /* 25% persistence */
-#define DEF_A_SLOTIME 10 /* 10 mS */
-#define DEF_A_SQUELDELAY 30 /* 30 mS */
-#define DEF_A_CLOCKMODE 0 /* Normal clock mode */
-#define DEF_A_NRZI 1 /* NRZI mode */
-
-#define DEF_B_SPEED 0 /* 0 means external clock */
-#define DEF_B_TXDELAY 250 /* 250 mS */
-#define DEF_B_PERSIST 64 /* 25% */
-#define DEF_B_SLOTIME 10 /* 10 mS */
-#define DEF_B_SQUELDELAY 30 /* 30 mS */
-#define DEF_B_CLOCKMODE 0 /* Normal clock mode ?!? */
-#define DEF_B_NRZI 1 /* NRZI mode */
-
-
-#define PARAM_TXDELAY 1
-#define PARAM_PERSIST 2
-#define PARAM_SLOTTIME 3
-#define PARAM_FULLDUP 5
-#define PARAM_HARDWARE 6
-#define PARAM_RETURN 255
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/malloc.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/uaccess.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/timer.h>
-#include <linux/if_arp.h>
-#include <linux/pt.h>
-#include <linux/init.h>
-#include "z8530.h"
-#include <net/ax25.h>
-
-struct mbuf {
- struct mbuf *next;
- int cnt;
- char data[0];
-};
-
-/*
- * The actual PT devices we will use
- */
-static int pt0_preprobe(struct net_device *dev) {return 0;} /* Dummy probe function */
-static struct net_device pt0a = { "pt0a", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pt0_preprobe };
-static struct net_device pt0b = { "pt0b", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pt0_preprobe };
-
-/* Ok, they shouldn't be here, but both channels share them */
-/* The Images of the Serial and DMA config registers */
-static unsigned char pt_sercfg = 0;
-static unsigned char pt_dmacfg = 0;
-
-/* The number of IO ports used by the card */
-#define PT_TOTAL_SIZE 16
-
-/* Index to functions, as function prototypes. */
-
-static int pt_probe(struct net_device *dev);
-static int pt_open(struct net_device *dev);
-static int pt_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void pt_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int pt_close(struct net_device *dev);
-static int pt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-static struct net_device_stats *pt_get_stats(struct net_device *dev);
-static void pt_rts(struct pt_local *lp, int x);
-static void pt_rxisr(struct net_device *dev);
-static void pt_txisr(struct pt_local *lp);
-static void pt_exisr(struct pt_local *lp);
-static void pt_tmrisr(struct pt_local *lp);
-static char *get_dma_buffer(unsigned long *mem_ptr);
-static int valid_dma_page(unsigned long addr, unsigned long dev_buffsize);
-static int hw_probe(int ioaddr);
-static void tdelay(struct pt_local *lp, int time);
-static void chipset_init(struct net_device *dev);
-
-static char ax25_bcast[7] =
-{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static char ax25_test[7] =
-{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
-
-
-static int ext2_secrm_seed = 152;
-
-static inline unsigned char random(void)
-{
- return (unsigned char) (ext2_secrm_seed = ext2_secrm_seed * 60691 + 1);
-}
-
-static inline void wrtscc(int cbase, int ctl, int sccreg, unsigned char val)
-{
- outb_p(sccreg, ctl); /* Select register */
- outb_p(val, ctl); /* Output value */
-}
-
-static inline unsigned char rdscc(int cbase, int ctl, int sccreg)
-{
- unsigned char retval;
-
- outb_p(sccreg, ctl); /* Select register */
- retval = inb_p(ctl);
- return retval;
-}
-
-static void switchbuffers(struct pt_local *lp)
-{
- if (lp->rcvbuf == lp->rxdmabuf1)
- lp->rcvbuf = lp->rxdmabuf2;
- else
- lp->rcvbuf = lp->rxdmabuf1;
-}
-
-static void hardware_send_packet(struct pt_local *lp, struct sk_buff *skb)
-{
- char kickflag;
- unsigned long flags;
- char *ptr;
- struct net_device *dev;
-
- /* First, let's see if this packet is actually a KISS packet */
- ptr = skb->data;
- if (ptr[0] != 0 && skb->len >= 2)
- {
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: Rx KISS... Control = %d, value = %d.\n", ptr[0], (skb->len > 1? ptr[1] : -1));
-#endif
- /* Kludge to get device */
- if ((struct pt_local*)(&pt0b.priv) == lp)
- dev = &pt0b;
- else
- dev = &pt0a;
- switch(ptr[0])
- {
-
- case PARAM_TXDELAY:
- /*TxDelay is in 10mS increments */
- lp->txdelay = ptr[1] * 10;
- break;
- case PARAM_PERSIST:
- lp->persist = ptr[1];
- break;
- case PARAM_SLOTTIME:
- lp->slotime = ptr[1];
- break;
- case PARAM_FULLDUP:
- /* Yeah right, you wish! Fullduplex is a little while to
- * go folks, but this is how you fire it up
- */
- break;
- /* Perhaps we should have txtail here?? */
- } /*switch */
- return;
- }
-
- lp->stats.tx_packets++;
- lp->stats.tx_bytes+=skb->len;
- save_flags(flags);
- cli();
- kickflag = (skb_peek(&lp->sndq) == NULL) && (lp->sndbuf == NULL);
- restore_flags(flags);
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: hardware_send_packet(): kickflag = %d (%d).\n", kickflag, lp->base & CHANA);
-#endif
- skb_queue_tail(&lp->sndq, skb);
- if (kickflag)
- {
- /* Simulate interrupt to transmit */
- if (lp->dmachan)
- pt_txisr(lp);
- else
- {
- save_flags(flags);
- cli();
- if (lp->tstate == IDLE)
- pt_txisr(lp);
- restore_flags(flags);
- }
- }
-} /* hardware_send_packet() */
-
-static void setup_rx_dma(struct pt_local *lp)
-{
- unsigned long flags;
- int cmd;
- unsigned long dma_abs;
- unsigned char dmachan;
-
- save_flags(flags);
- cli();
-
- dma_abs = (unsigned long) (lp->rcvbuf->data);
- dmachan = lp->dmachan;
- cmd = lp->base + CTL;
-
- if(!valid_dma_page(dma_abs, DMA_BUFF_SIZE + sizeof(struct mbuf)))
- panic("PI: RX buffer violates DMA boundary!");
-
- /* Get ready for RX DMA */
- wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | WT_RDY_RT | INT_ERR_Rx | EXT_INT_ENAB);
-
- disable_dma(dmachan);
- clear_dma_ff(dmachan);
-
- /*
- * Set DMA mode register to single transfers, incrementing address,
- * auto init, writes
- */
-
- set_dma_mode(dmachan, DMA_MODE_READ | 0x10);
- set_dma_addr(dmachan, dma_abs);
- set_dma_count(dmachan, lp->bufsiz);
- enable_dma(dmachan);
-
- /*
- * If a packet is already coming in, this line is supposed to
- * avoid receiving a partial packet.
- */
-
- wrtscc(lp->cardbase, cmd, R0, RES_Rx_CRC);
-
- /* Enable RX dma */
- wrtscc(lp->cardbase, cmd, R1,
- WT_RDY_ENAB | WT_FN_RDYFN | WT_RDY_RT | INT_ERR_Rx | EXT_INT_ENAB);
-
- restore_flags(flags);
-}
-
-static void setup_tx_dma(struct pt_local *lp, int length)
-{
- unsigned long dma_abs;
- unsigned long flags;
- unsigned long dmachan;
-
- save_flags(flags);
- cli();
-
- dmachan = lp->dmachan;
- dma_abs = (unsigned long) (lp->txdmabuf);
-
- if(!valid_dma_page(dma_abs, DMA_BUFF_SIZE + sizeof(struct mbuf)))
- panic("PT: TX buffer violates DMA boundary!");
-
- disable_dma(dmachan);
- /* Set DMA mode register to single transfers, incrementing address,
- * no auto init, reads
- */
- set_dma_mode(dmachan, DMA_MODE_WRITE);
- clear_dma_ff(dmachan);
- set_dma_addr(dmachan, dma_abs);
- /* output byte count */
- set_dma_count(dmachan, length);
-
- restore_flags(flags);
-}
-
-/*
- * This sets up all the registers in the SCC for the given channel
- * based upon tsync_hwint()
- */
-static void scc_init(struct net_device *dev)
-{
- unsigned long flags;
- struct pt_local *lp = (struct pt_local*) dev->priv;
- register int cmd = lp->base + CTL;
- int tc, br;
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: scc_init(): (%d).\n", lp->base & CHANA);
-#endif
- save_flags(flags);
- cli();
-
- /* We may put something here to enable_escc */
-
- if (cmd & CHANA)
- {
- wrtscc(lp->cardbase, cmd, R9, CHRA); /* Reset channel A */
- wrtscc(lp->cardbase, cmd, R2, 0xff); /* Initialise interrupt vector */
- }
- else
- wrtscc(lp->cardbase, cmd, R9, CHRB); /* Reset channel B */
-
- /* Deselect all Rx and Tx interrupts */
- wrtscc(lp->cardbase, cmd, R1, 0);
-
- /* Turn off external interrupts (like CTS/CD) */
- wrtscc(lp->cardbase, cmd, R15, 0);
-
- /* X1 clock, SDLC mode */
- wrtscc(lp->cardbase, cmd, R4, SDLC | X1CLK);
-
- /* Preset CRC and set mode */
- if (lp->nrzi)
- /* Preset Tx CRC, put into NRZI mode */
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);
- else
- /* Preset Tx CRC, put into NRZ mode */
- wrtscc(lp->cardbase, cmd, R10, CRCPS);
-
- /* Tx/Rx parameters */
- if (lp->speed) /* Use internal clocking */
- /* Tx Clk from BRG. Rx Clk form DPLL, TRxC pin outputs DPLL */
- wrtscc(lp->cardbase, cmd, R11, TCBR | RCDPLL | TRxCDP | TRxCOI);
- else /* Use external clocking */
- {
- /* Tx Clk from TRxCL. Rx Clk from RTxCL, TRxC pin if input */
- wrtscc(lp->cardbase, cmd, R11, TCTRxCP | RCRTxCP | TRxCBR);
- wrtscc(lp->cardbase,cmd, R14, 0); /* wiz1 */
- }
-
- /* Null out SDLC start address */
- wrtscc(lp->cardbase, cmd, R6, 0);
-
- /* SDLC flag */
- wrtscc(lp->cardbase, cmd, R7, FLAG);
-
- /* Setup Tx but don't enable it */
- wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR);
-
- /* Setup Rx */
- wrtscc(lp->cardbase, cmd, R3, AUTO_ENAB | Rx8);
-
- /* Setup the BRG, turn it off first */
- wrtscc(lp->cardbase, cmd, R14, BRSRC);
-
- /* set the 32x time constant for the BRG in Rx mode */
- if (lp->speed)
- {
- br = lp->speed;
- tc = ((lp->xtal / 32) / (br * 2)) - 2;
- wrtscc(lp->cardbase, cmd, R12, tc & 0xff); /* lower byte */
- wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff); /* upper byte */
- }
-
- /* Turn transmitter off, to setup stuff */
- pt_rts(lp, OFF);
-
- /* External clocking */
- if (lp->speed)
- {
- /* DPLL frm BRG, BRG src PCLK */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | SSBR);
- wrtscc(lp->cardbase, cmd, R14, BRSRC | SEARCH); /* SEARCH mode, keep BRG src */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | BRENABL); /* Enable the BRG */
-
- /* Turn off external clock port */
- if (lp->base & CHANA)
- outb_p( (pt_sercfg &= ~PT_EXTCLKA), (lp->cardbase + SERIAL_CFG) );
- else
- outb_p( (pt_sercfg &= ~PT_EXTCLKB), (lp->cardbase + SERIAL_CFG) );
- }
- else
- {
- /* DPLL frm rtxc,BRG src PCLK */
- /* Turn on external clock port */
- if (lp->base & CHANA)
- outb_p( (pt_sercfg |= PT_EXTCLKA), (lp->cardbase + SERIAL_CFG) );
- else
- outb_p( (pt_sercfg |= PT_EXTCLKB), (lp->cardbase + SERIAL_CFG) );
- }
-
- if (!lp->dmachan)
- wrtscc(lp->cardbase, cmd, R1, (INT_ALL_Rx | EXT_INT_ENAB));
-
- wrtscc(lp->cardbase, cmd, R15, BRKIE); /* ABORT int */
-
- /* Turn on the DTR to tell modem we're alive */
- if (lp->base & CHANA)
- outb_p( (pt_sercfg |= PT_DTRA_ON), (lp->cardbase + SERIAL_CFG) );
- else
- outb_p( (pt_sercfg |= PT_DTRB_ON), (lp->cardbase + SERIAL_CFG) );
-
- /* Now, turn on the receiver and hunt for a flag */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | RxCRC_ENAB | AUTO_ENAB | Rx8 );
-
- restore_flags(flags);
-
-} /* scc_init() */
-
-/* Resets the given channel and whole SCC if both channels off */
-static void chipset_init(struct net_device *dev)
-{
-
- struct pt_local *lp = (struct pt_local*) dev->priv;
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: chipset_init(): pt0a tstate = %d.\n", ((struct pt_local*)pt0a.priv)->tstate);
- printk(KERN_DEBUG "PT: chipset_init(): pt0b tstate = %d.\n", ((struct pt_local*)pt0b.priv)->tstate);
-#endif
- /* Reset SCC if both channels are to be canned */
- if ( ((lp->base & CHANA) && !(pt_sercfg & PT_DTRB_ON)) ||
- (!(lp->base & CHANA) && !(pt_sercfg & PT_DTRA_ON)) )
- {
- wrtscc(lp->cardbase, lp->base + CTL, R9, FHWRES);
- /* Reset int and dma registers */
- outb_p((pt_sercfg = 0), lp->cardbase + SERIAL_CFG);
- outb_p((pt_dmacfg = 0), lp->cardbase + DMA_CFG);
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: chipset_init() Resetting SCC, called by ch (%d).\n", lp->base & CHANA);
-#endif
- }
- /* Reset individual channel */
- if (lp->base & CHANA) {
- wrtscc(lp->cardbase, lp->base + CTL, R9, MIE | DLC | NV | CHRA);
- outb_p( (pt_sercfg &= ~PT_DTRA_ON), lp->cardbase + SERIAL_CFG);
- } else {
- wrtscc(lp->cardbase, lp->base + CTL, R9, MIE | DLC | NV | CHRB);
- outb_p( (pt_sercfg &= ~PT_DTRB_ON), lp->cardbase + SERIAL_CFG);
- }
-} /* chipset_init() */
-
-
-int __init ptwin_init(void)
-{
- int *port;
- int ioaddr = 0;
- int card_type = 0;
- int ports[] =
- { 0x230, 0x240, 0x250, 0x260, 0x270, 0x280, 0x290, 0x2a0,
- 0x2b0, 0x300, 0x330, 0x3f0, 0};
-
- printk(KERN_INFO "PT: 0.41 ALPHA 07 October 1995 Craig Small (csmall@small.dropbear.id.au)\n");
-
- for (port = &ports[0]; *port && !card_type; port++) {
- ioaddr = *port;
-
- if (check_region(ioaddr, PT_TOTAL_SIZE) == 0) {
- printk(KERN_INFO "PT: Probing for card at address %#3x\n", ioaddr);
- card_type = hw_probe(ioaddr);
- }
- }
- if (card_type) {
- printk(KERN_INFO "PT: Found a PT at address %#3x\n",ioaddr);
- } else {
- printk(KERN_ERR "PT: ERROR: No card found.\n");
- return -EIO;
- }
-
- /*
- * Link a couple of device structures into the chain
- *
- * For the A port
- * Allocate space for 4 buffers even though we only need 3,
- * because one of them may cross a DMA page boundary and
- * be rejected by get_dma_buffer().
- */
- register_netdev(&pt0a);
-
- pt0a.priv= kmalloc(sizeof(struct pt_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA);
-
- pt0a.dma = 0; /* wizzer - no dma yet */
- pt0a.base_addr = ioaddr + CHANA;
- pt0a.irq = 0;
-
- /* And B port */
- register_netdev(&pt0b);
-
- pt0b.priv= kmalloc(sizeof(struct pt_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA);
-
- pt0b.base_addr = ioaddr + CHANB;
- pt0b.irq = 0;
-
- /* Now initialise them */
- pt_probe(&pt0a);
- pt_probe(&pt0b);
-
- pt0b.irq = pt0a.irq; /* IRQ is shared */
-
- return 0;
-} /* ptwin_init() */
-
-/*
- * Probe for PT card. Also initialises the timers
- */
-static int __init hw_probe(int ioaddr)
-{
- int time = 1000; /* Number of milliseconds to test */
- int a = 1;
- int b = 1;
- unsigned long start_time, end_time;
-
- inb_p(ioaddr + TMR1CLR);
- inb_p(ioaddr + TMR2CLR);
-
- /* Timer counter channel 0, 1mS period */
- outb_p(SC0 | LSB_MSB | MODE3, ioaddr + TMRCMD);
- outb_p(0x00, ioaddr + TMR0);
- outb_p(0x18, ioaddr + TMR0);
-
- /* Setup timer control word for timer 1 */
- outb_p(SC1 | LSB_MSB | MODE0, ioaddr + TMRCMD);
- outb_p((time << 1) & 0xff, ioaddr + TMR1);
- outb_p((time >> 7) & 0xff, ioaddr + TMR1);
-
- /* wait until counter reg is loaded */
- do {
- /* Latch count for reading */
- outb_p(SC1, ioaddr + TMRCMD);
- a = inb_p(ioaddr + TMR1);
- b = inb_p(ioaddr + TMR1);
- } while (b == 0);
- start_time = jiffies;
- while(b != 0)
- {
- /* Latch count for reading */
- outb_p(SC1, ioaddr + TMRCMD);
- a = inb_p(ioaddr + TMR1);
- b = inb_p(ioaddr + TMR1);
- end_time = jiffies;
- /* Don't wait forever - there may be no card here */
- if ((end_time - start_time) > 200)
- {
- inb_p(ioaddr + TMR1CLR);
- return 0;
- }
- }
-
- /* Now fix the timers up for general operation */
-
- /* Clear the timers */
- inb_p(ioaddr + TMR1CLR);
- inb_p(ioaddr + TMR2CLR);
-
- outb_p(SC1 | LSB_MSB | MODE0, ioaddr + TMRCMD);
- inb_p(ioaddr + TMR1CLR);
-
- outb_p(SC2 | LSB_MSB | MODE0, ioaddr + TMRCMD);
- /* Should this be tmr1 or tmr2? wiz3*/
- inb_p(ioaddr + TMR1CLR);
-
- return 1;
-} /* hw_probe() */
-
-
-static void pt_rts(struct pt_local *lp, int x)
-{
- int tc;
- long br;
- int cmd = lp->base + CTL;
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_rts(): Transmitter status will be %d (%d).\n", x, lp->base & CHANA);
-#endif
- if (x == ON) {
- /* Ex ints off to avoid int */
- wrtscc(lp->cardbase, cmd, R15, 0);
- wrtscc(lp->cardbase, cmd, R3, AUTO_ENAB | Rx8); /* Rx off */
- lp->rstate = IDLE;
-
- if(lp->dmachan)
- {
- /* Setup for Tx DMA */
- wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);
- } else {
- /* No interrupts */
- wrtscc(lp->cardbase, cmd, R1, 0);
- }
-
- if (!lp->clockmode)
- {
- if (lp->speed)
- {
- br = lp->speed;
- tc = (lp->xtal / (br * 2)) - 2;
- wrtscc(lp->cardbase, cmd, R12, tc & 0xff);
- wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff);
- }
- }
- /* Turn on Tx by raising RTS */
- wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8 | DTR);
- /* Transmitter on now */
- } else { /* turning off Tx */
- lp->tstate = IDLE;
-
- /* Turn off Tx by dropping RTS */
- wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR);
- if (!lp->clockmode)
- {
- if (lp->speed) /* internally clocked */
- {
- /* Reprogram BRG from 32x clock for Rx DPLL */
- /* BRG off, keep PClk source */
- wrtscc(lp->cardbase, cmd, R14, BRSRC);
- br = lp->speed;
- tc = ((lp->xtal / 32) / (br * 2)) - 2;
- wrtscc(lp->cardbase, cmd, R12, tc & 0xff);
- wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff);
-
- /* SEARCH mode, BRG source */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | SEARCH);
- /* Enable the BRG */
- wrtscc(lp->cardbase, cmd, R14, BRSRC | BRENABL);
- }
- }
- /* Flush Rx fifo */
- /* Turn Rx off */
- wrtscc(lp->cardbase, cmd, R3, AUTO_ENAB | Rx8);
-
- /* Reset error latch */
- wrtscc(lp->cardbase, cmd, R0, ERR_RES);
-
- /* get status byte from R1 */
- (void) rdscc(lp->cardbase, cmd, R1);
-
- /* Read and dump data in queue */
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
-
- /* Now, turn on Rx and hunt for a flag */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | AUTO_ENAB | Rx8 );
-
- lp->rstate = ACTIVE;
-
- if (lp->dmachan)
- {
- setup_rx_dma(lp);
- } else {
- /* Reset buffer pointers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- /* Allow aborts to interrupt us */
- wrtscc(lp->cardbase, cmd, R1, INT_ALL_Rx | EXT_INT_ENAB);
-
- }
- wrtscc(lp->cardbase, cmd, R15, BRKIE );
- }
-} /* pt_rts() */
-
-
-static int valid_dma_page(unsigned long addr, unsigned long dev_bufsize)
-{
- if (((addr & 0xffff) + dev_bufsize) <= 0x10000)
- return 1;
- else
- return 0;
-}
-
-static int pt_set_mac_address(struct net_device *dev, void *addr)
-{
- struct sockaddr *sa = (struct sockaddr *)addr;
- memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); /* addr is an AX.25 shifted ASCII */
- return 0; /* mac address */
-}
-
-
-/* Allocate a buffer which does not cross a DMA page boundary */
-static char * get_dma_buffer(unsigned long *mem_ptr)
-{
- char *ret;
-
- ret = (char *) *mem_ptr;
-
- if (!valid_dma_page(*mem_ptr, DMA_BUFF_SIZE + sizeof(struct mbuf))) {
- *mem_ptr += (DMA_BUFF_SIZE + sizeof(struct mbuf));
- ret = (char *) *mem_ptr;
- }
- *mem_ptr += (DMA_BUFF_SIZE + sizeof(struct mbuf));
- return (ret);
-} /* get_dma_buffer() */
-
-
-/*
- * Sets up all the structures for the PT device
- */
-static int pt_probe(struct net_device *dev)
-{
- short ioaddr;
- struct pt_local *lp;
- unsigned long flags;
- unsigned long mem_ptr;
-
- ioaddr = dev->base_addr;
-
- /*
- * Initialise the device structure.
- * Must be done before chipset_init()
- * Make sure data structures used by the PT are aligned
- */
- dev->priv = (void *) (((int) dev->priv + 7) & ~7);
- lp = (struct pt_local*) dev->priv;
-
- memset(dev->priv, 0, sizeof(struct pt_local));
-
- /* Allocate some buffers which do not cross DMA boundaries */
- mem_ptr = (unsigned long) dev->priv + sizeof(struct pt_local);
- lp->txdmabuf = get_dma_buffer(&mem_ptr);
- lp->rxdmabuf1 = (struct mbuf *) get_dma_buffer(&mem_ptr);
- lp->rxdmabuf2 = (struct mbuf *) get_dma_buffer(&mem_ptr);
-
- /* Initialise the Rx buffer */
- lp->rcvbuf = lp->rxdmabuf1;
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
-
- /* Initialise the transmit queue head structure */
- skb_queue_head_init(&lp->sndq);
-
- lp->base = dev->base_addr;
- lp->cardbase = dev->base_addr & 0x3f0;
-
- /* These need to be initialised before scc_init() is called.
- */
- lp->xtal = XTAL;
-
- if (dev->base_addr & CHANA) {
- lp->speed = DEF_A_SPEED;
- lp->txdelay = DEF_A_TXDELAY;
- lp->persist = DEF_A_PERSIST;
- lp->slotime = DEF_A_SLOTIME;
- lp->squeldelay = DEF_A_SQUELDELAY;
- lp->clockmode = DEF_A_CLOCKMODE;
- lp->nrzi = DEF_A_NRZI;
- } else {
- lp->speed = DEF_B_SPEED;
- lp->txdelay = DEF_B_TXDELAY;
- lp->persist = DEF_B_PERSIST;
- lp->slotime = DEF_B_SLOTIME;
- lp->squeldelay = DEF_B_SQUELDELAY;
- lp->clockmode = DEF_B_CLOCKMODE;
- lp->nrzi = DEF_B_NRZI;
- }
- lp->bufsiz = DMA_BUFF_SIZE;
- lp->tstate = IDLE;
-
- chipset_init(dev);
-
- if (dev->base_addr & CHANA) {
- /* Note that a single IRQ services 2 devices (A and B channels)
- */
-
- /*
- * We disable the dma for a while, we have to get ints working
- * properly first!!
- */
- lp->dmachan = 0;
-
- if (dev->irq < 2) {
- autoirq_setup(0);
-
- /* Turn on PT interrupts */
- save_flags(flags);
- cli();
- outb_p( pt_sercfg |= PT_EI, lp->cardbase + INT_CFG);
- restore_flags(flags);
-
- /* Set a timer interrupt */
- tdelay(lp, 1);
- dev->irq = autoirq_report(20);
-
- /* Turn off PT interrupts */
- save_flags(flags);
- cli();
- outb_p( (pt_sercfg &= ~ PT_EI), lp->cardbase + INT_CFG);
- restore_flags(flags);
-
- if (!dev->irq) {
- printk(KERN_ERR "PT: ERROR: Failed to detect IRQ line, assuming IRQ7.\n");
- }
- }
-
- printk(KERN_INFO "PT: Autodetected IRQ %d, assuming DMA %d\n", dev->irq, dev->dma);
-
- /* This board has jumpered interrupts. Snarf the interrupt vector
- * now. There is no point in waiting since no other device can use
- * the interrupt, and this marks the 'irqaction' as busy.
- */
- {
- int irqval = request_irq(dev->irq, &pt_interrupt,0, "pt", dev);
- if (irqval) {
- printk(KERN_ERR "PT: ERROR: Unable to get IRQ %d (irqval = %d).\n",
- dev->irq, irqval);
- return -EAGAIN;
- }
- }
-
- /* Grab the region */
- request_region(ioaddr & 0x3f0, PT_TOTAL_SIZE, "pt" );
- } /* A port */
- dev->open = pt_open;
- dev->stop = pt_close;
- dev->do_ioctl = pt_ioctl;
- dev->hard_start_xmit = pt_send_packet;
- dev->get_stats = pt_get_stats;
-
- /* Fill in the fields of the device structure */
- dev_init_buffers(dev);
-
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax25_encapsulate;
- dev->rebuild_header = ax25_rebuild_header;
-#endif
-
- dev->set_mac_address = pt_set_mac_address;
-
- dev->type = ARPHRD_AX25; /* AF_AX25 device */
- dev->hard_header_len = 73; /* We do digipeaters now */
- dev->mtu = 1500; /* eth_mtu is default */
- dev->addr_len = 7; /* sizeof an ax.25 address */
- memcpy(dev->broadcast, ax25_bcast, 7);
- memcpy(dev->dev_addr, ax25_test, 7);
-
- /* New style flags */
- dev->flags = 0;
-
- return 0;
-} /* pt_probe() */
-
-
-/* Open/initialise the board. This is called (in the current kernel)
- * sometime after booting when the 'ifconfig' program is run.
- *
- * This routine should set everything up anew at each open, even
- * registers that 'should' only be set once at boot, so that there is
- * a non-reboot way to recover if something goes wrong.
- * derived from last half of tsync_attach()
- */
-static int pt_open(struct net_device *dev)
-{
- unsigned long flags;
- struct pt_local *lp = dev->priv;
- static first_time = 1;
-
- if (dev->base_addr & CHANA)
- {
- if (first_time)
- {
- if (request_dma(dev->dma, "pt"))
- {
- free_irq(dev->irq, dev);
- return -EAGAIN;
- }
- }
-
- /* Reset hardware */
- chipset_init(dev);
- }
- lp->tstate = IDLE;
-
- if (dev->base_addr & CHANA)
- {
- scc_init(dev);
- scc_init(dev->next);
- }
- /* Save a copy of register RR0 for comparing with later on */
- /* We always put 0 in zero count */
- lp->saved_RR0 = rdscc(lp->cardbase, lp->base + CTL, R0) & ~ZCOUNT;
-
- /* master interrupt enable */
- save_flags(flags);
- cli();
- wrtscc(lp->cardbase, lp->base + CTL, R9, MIE | NV);
- outb_p( pt_sercfg |= PT_EI, lp->cardbase + INT_CFG);
- restore_flags(flags);
-
- lp->open_time = jiffies;
-
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
- first_time = 0;
-
- MOD_INC_USE_COUNT;
-
- return 0;
-} /* pt_open() */
-
-static int pt_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
- struct pt_local *lp = (struct pt_local *) dev->priv;
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_send_packet(): (%d)\n", lp->base & CHANA);
-#endif
- hardware_send_packet(lp, skb);
- dev->trans_start = jiffies;
-
- return 0;
-}
-
-
-
-/* The inverse routine to pt_open() */
-static int pt_close(struct net_device *dev)
-{
- unsigned long flags;
- struct pt_local *lp = dev->priv;
- struct sk_buff *ptr = NULL;
- int cmd;
-
- cmd = lp->base + CTL;
-
- save_flags(flags);
- cli();
-
- /* Reset SCC or channel */
- chipset_init(dev);
- disable_dma(lp->dmachan);
-
- lp->open_time = 0;
- dev->tbusy = 1;
- dev->start = 0;
-
- /* Free any buffers left in the hardware transmit queue */
- while ((ptr = skb_dequeue(&lp->sndq)) != NULL)
- kfree_skb(ptr);
-
- restore_flags(flags);
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_close(): Closing down channel (%d).\n", lp->base & CHANA);
-#endif
-
- MOD_DEC_USE_COUNT;
-
- return 0;
-} /* pt_close() */
-
-
-static int pt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
- unsigned long flags;
- struct pt_req rq;
- struct pt_local *lp = (struct pt_local *) dev->priv;
-
- int ret = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct pt_req));
- if (ret)
- return ret;
-
- if (cmd != SIOCDEVPRIVATE)
- return -EINVAL;
-
- copy_from_user(&rq, ifr->ifr_data, sizeof(struct pt_req));
-
- switch (rq.cmd) {
- case SIOCSPIPARAM:
-
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- save_flags(flags);
- cli();
- lp->txdelay = rq.txdelay;
- lp->persist = rq.persist;
- lp->slotime = rq.slotime;
- lp->squeldelay = rq.squeldelay;
- lp->clockmode = rq.clockmode;
- lp->speed = rq.speed;
- pt_open(&pt0a);
- restore_flags(flags);
- ret = 0;
- break;
-
- case SIOCSPIDMA:
-
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- ret = 0;
- if (dev->base_addr & CHANA) { /* if A channel */
- if (rq.dmachan < 1 || rq.dmachan > 3)
- return -EINVAL;
- save_flags(flags);
- cli();
- pt_close(dev);
- free_dma(lp->dmachan);
- dev->dma = lp->dmachan = rq.dmachan;
- if (request_dma(lp->dmachan,"pt"))
- ret = -EAGAIN;
- pt_open(dev);
- restore_flags(flags);
- }
- break;
-
- case SIOCSPIIRQ:
- ret = -EINVAL; /* add this later */
- break;
-
- case SIOCGPIPARAM:
- case SIOCGPIDMA:
- case SIOCGPIIRQ:
-
- rq.speed = lp->speed;
- rq.txdelay = lp->txdelay;
- rq.persist = lp->persist;
- rq.slotime = lp->slotime;
- rq.squeldelay = lp->squeldelay;
- rq.clockmode = lp->clockmode;
- rq.dmachan = lp->dmachan;
- rq.irq = dev->irq;
- copy_to_user(ifr->ifr_data, &rq, sizeof(struct pt_req));
- ret = 0;
- break;
-
- default:
- ret = -EINVAL;
- }
- return ret;
-}
-
-/*
- * Get the current statistics.
- * This may be called with the card open or closed.
- */
-
-static struct net_device_stats *pt_get_stats(struct net_device *dev)
-{
- struct pt_local *lp = (struct pt_local *) dev->priv;
- return &lp->stats;
-}
-
-
-/*
- * Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c"
- * version-control: t
- * kept-new-versions: 5
- * tab-width: 4
- * End:
- */
-
-
-static void tdelay(struct pt_local *lp, int time)
-{
- /* For some reason, we turn off the Tx interrupts here! */
- if (!lp->dmachan)
- wrtscc(lp->cardbase, lp->base + CTL, R1, INT_ALL_Rx | EXT_INT_ENAB);
-
- if (lp->base & CHANA)
- {
- outb_p(time & 0xff, lp->cardbase + TMR1);
- outb_p((time >> 8)&0xff, lp->cardbase + TMR1);
- }
- else
- {
- outb_p(time & 0xff, lp->cardbase + TMR2);
- outb_p((time >> 8)&0xff, lp->cardbase + TMR2);
- }
-} /* tdelay */
-
-
-static void pt_txisr(struct pt_local *lp)
-{
- unsigned long flags;
- int cmd;
- unsigned char c;
-
- save_flags(flags);
- cli();
- cmd = lp->base + CTL;
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_txisr(): tstate = %d (%d).\n", lp->tstate, lp->base & CHANA);
-#endif
-
- switch (lp->tstate)
- {
- case CRCOUT:
- lp->tstate = FLAGOUT;
- tdelay(lp, lp->squeldelay);
- restore_flags(flags);
- return;
-
- case IDLE:
- /* Transmitter idle. Find a frame for transmission */
- if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL)
- {
- /* Nothing to send - return to receive mode
- * Tx off now - flag should have gone
- */
- pt_rts(lp, OFF);
-
- restore_flags(flags);
- return;
- }
- if (!lp->dmachan)
- {
- lp->txptr = lp->sndbuf->data;
- lp->txptr++; /* Ignore KISS control byte */
- lp->txcnt = (int) lp->sndbuf->len - 1;
- }
- /* If a buffer to send, drop though here */
-
- case DEFER:
- /* Check DCD - debounce it */
- /* See Intel Microcommunications Handbook p2-308 */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0)
- {
- lp->tstate = DEFER;
- tdelay(lp, 100);
- /* DEFER until DCD transition or timeout */
- wrtscc(lp->cardbase, cmd, R15, DCDIE);
- restore_flags(flags);
- return;
- }
- if (random() > lp->persist)
- {
- lp->tstate = DEFER;
- tdelay(lp, lp->slotime);
- restore_flags(flags);
- return;
- }
- pt_rts(lp, ON); /* Tx on */
- if (lp->dmachan)
- wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);
- lp->tstate = ST_TXDELAY;
- tdelay(lp, lp->txdelay);
- restore_flags(flags);
- return;
-
- case ACTIVE:
- /* Here we are actively sending a frame */
- if (lp->txcnt--)
- {
- /* XLZ - checkout Gracilis PT code to see if the while
- * loop is better or not.
- */
- c = *lp->txptr++;
- /* next char is gone */
- wrtscc(lp->cardbase, cmd, R8, c);
- /* stuffing a char satisfies interrupt condition */
- } else {
- /* No more to send */
- kfree_skb(lp->sndbuf);
- lp->sndbuf = NULL;
- if ((rdscc(lp->cardbase, cmd, R0) & TxEOM))
- {
- /* Did we underrun */
- lp->stats.tx_errors++;
- lp->stats.tx_fifo_errors++;
- wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);
- lp->tstate = FLAGOUT;
- tdelay(lp, lp->squeldelay);
- restore_flags(flags);
- return;
- }
- lp->tstate = UNDERRUN;
- /* Send flags on underrun */
- if (lp->nrzi)
- {
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);
- } else {
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZ);
- }
- /* Reset Tx interrupt pending */
- wrtscc(lp->cardbase, cmd, R0, RES_Tx_P);
- }
- restore_flags(flags);
- return;
- default:
- printk(KERN_ERR "PT: pt_txisr(): Invalid tstate (%d) for chan %s.\n", lp->tstate, (cmd & CHANA? "A": "B") );
- pt_rts(lp, OFF);
- lp->tstate = IDLE;
- break;
- } /*switch */
- restore_flags(flags);
-}
-
-static void pt_rxisr(struct net_device *dev)
-{
- struct pt_local *lp = (struct pt_local*) dev->priv;
- int cmd = lp->base + CTL;
- int bytecount;
- unsigned long flags;
- char rse;
- struct sk_buff *skb;
- int sksize, pkt_len;
- struct mbuf *cur_buf = NULL;
- unsigned char *cfix;
-
- save_flags(flags);
- cli();
-
- /* Get status byte from R1 */
- rse = rdscc(lp->cardbase, cmd, R1);
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_rxisr(): R1 = %#3x. (%d)\n", rse, lp->base & CHANA);
-#endif
-
- if (lp->dmachan && (rse & Rx_OVR))
- lp->rstate = RXERROR;
-
- if (rdscc(lp->cardbase, cmd, R0) & Rx_CH_AV && !lp->dmachan)
- {
- /* There is a char to be stored
- * Read special condition bits before reading the data char
- */
- if (rse & Rx_OVR)
- {
- /* Rx overrun - toss buffer */
- /* wind back the pointers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- lp->rstate = RXERROR;
- lp->stats.rx_errors++;
- lp->stats.rx_fifo_errors++;
- } else if (lp->rcvbuf->cnt >= lp->bufsiz)
- {
- /* Too large packet
- * wind back Rx buffer pointers
- */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- lp->rstate = TOOBIG;
- }
- /* ok, we can store the Rx char if no errors */
- if (lp->rstate == ACTIVE)
- {
- *lp->rcp++ = rdscc(lp->cardbase, cmd, R8);
- lp->rcvbuf->cnt++;
- } else {
- /* we got an error, dump the FIFO */
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
-
- /* Reset error latch */
- wrtscc(lp->cardbase, cmd, R0, ERR_RES);
- lp->rstate = ACTIVE;
-
- /* Resync the SCC */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
-
- }
- }
-
- if (rse & END_FR)
- {
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_rxisr() Got end of a %u byte frame.\n", lp->rcvbuf->cnt);
-#endif
- if (lp->dmachan)
- {
- clear_dma_ff(lp->dmachan);
- bytecount = lp->bufsiz - get_dma_residue(lp->dmachan);
- } else {
- bytecount = lp->rcvbuf->cnt;
- }
-
- /* END OF FRAME - Make sure Rx was active */
- if (lp->rcvbuf->cnt > 0 || lp->dmachan)
- {
- if ((rse & CRC_ERR) || (lp->rstate > ACTIVE) || (bytecount < 10))
- {
- if ((bytecount >= 10) && (rse & CRC_ERR))
- {
- lp->stats.rx_crc_errors++;
- }
- if (lp->dmachan)
- {
- if (lp->rstate == RXERROR)
- {
- lp->stats.rx_errors++;
- lp->stats.rx_over_errors++;
- }
- lp->rstate = ACTIVE;
- setup_rx_dma(lp);
- } else {
- /* wind back Rx buffer pointers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
-
- /* Re-sync the SCC */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
-
- }
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_rxisr() %s error.\n", (rse & CRC_ERR)? "CRC" : "state");
-#endif
- } else {
- /* We have a valid frame */
- if (lp->dmachan)
- {
- pkt_len = lp->rcvbuf->cnt = bytecount - 2 +1;
- /* Get buffer for next frame */
- cur_buf = lp->rcvbuf;
- switchbuffers(lp);
- setup_rx_dma(lp);
- } else {
- pkt_len = lp->rcvbuf->cnt -= 2; /* Toss 2 CRC bytes */
- pkt_len += 1; /* make room for KISS control byte */
- }
-
- /* Malloc up new buffer */
- sksize = pkt_len;
- skb = dev_alloc_skb(sksize);
- if (skb == NULL)
- {
- printk(KERN_ERR "PT: %s: Memory squeeze, dropping packet.\n", dev->name);
- lp->stats.rx_dropped++;
- restore_flags(flags);
- return;
- }
- skb->dev = dev;
-
- /* KISS kludge = prefix with a 0 byte */
- cfix=skb_put(skb,pkt_len);
- *cfix++=0;
- /* skb->data points to the start of sk_buff area */
- if (lp->dmachan)
- memcpy(cfix, (char*)cur_buf->data, pkt_len - 1);
- else
- memcpy(cfix, lp->rcvbuf->data, pkt_len - 1);
- skb->protocol = ntohs(ETH_P_AX25);
- skb->mac.raw=skb->data;
- lp->stats.rx_bytes+=skb->len;
- netif_rx(skb);
- lp->stats.rx_packets++;
- if (!lp->dmachan)
- {
- /* packet queued - wind back buffer for next frame */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- }
- } /* good frame */
- } /* check active Rx */
- /* Clear error status */
- lp->rstate = ACTIVE;
- /* Reset error latch */
- } /* end EOF check */
- wrtscc(lp->cardbase, cmd, R0, ERR_RES);
- restore_flags(flags);
-} /* pt_rxisr() */
-
-/*
- * This handles the two timer interrupts.
- * This is a real bugger, cause you have to rip it out of the pi's
- * external status code. They use the CTS line or something.
- */
-static void pt_tmrisr(struct pt_local *lp)
-{
- unsigned long flags;
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_tmrisr(): tstate = %d (%d).\n", lp->tstate, lp->base & CHANA);
-#endif
-
- save_flags(flags);
- cli();
-
-
- switch (lp->tstate)
- {
- /* Most of this stuff is in pt_exisr() */
- case FLAGOUT:
- case ST_TXDELAY:
- case DEFER:
-/* case ACTIVE:
- case UNDERRUN:*/
- pt_exisr(lp);
- break;
-
- default:
- if (lp->base & CHANA)
- printk(KERN_ERR "PT: pt_tmrisr(): Invalid tstate %d for Channel A\n", lp->tstate);
- else
- printk(KERN_ERR "PT: pt_tmrisr(): Invalid tstate %d for Channel B\n", lp->tstate);
- break;
- } /* end switch */
- restore_flags(flags);
-} /* pt_tmrisr() */
-
-
-/*
- * This routine is called by the kernel when there is an interrupt for the
- * PT.
- */
-static void pt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- /* It's a tad dodgy here, but we assume pt0a until proven otherwise */
- struct net_device *dev = &pt0a;
- struct pt_local *lp = dev->priv;
- unsigned char intreg;
- unsigned char st;
- register int cbase = dev->base_addr & 0x3f0;
- unsigned long flags;
-
- /* Read the PT's interrupt register, this is not the SCC one! */
- intreg = inb_p(cbase + INT_REG);
- while(( intreg & 0x07) != 0x07) {
- /* Read interrupt register pending from Channel A */
- while ((st = rdscc(cbase, cbase + CHANA + CTL, R3)) != 0)
- {
- /* Read interrupt vector from R2, channel B */
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_interrupt(): R3 = %#3x", st);
-#endif
-/* st = rdscc(lp->cardbase, cbase + CHANB + CTL, R2) & 0x0e;*/
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PI: R2 = %#3x.\n", st);
-#endif
- if (st & CHARxIP) {
- /* Channel A Rx */
- lp = (struct pt_local*)pt0a.priv;
- pt_rxisr(&pt0a);
- } else if (st & CHATxIP) {
- /* Channel A Tx */
- lp = (struct pt_local*)pt0a.priv;
- pt_txisr(lp);
- } else if (st & CHAEXT) {
- /* Channel A External Status */
- lp = (struct pt_local*)pt0a.priv;
- pt_exisr(lp);
- } else if (st & CHBRxIP) {
- /* Channel B Rx */
- lp= (struct pt_local*)pt0b.priv;
- pt_rxisr(&pt0b);
- } else if (st & CHBTxIP) {
- /* Channel B Tx */
- lp = (struct pt_local*)pt0b.priv;
- pt_txisr(lp);
- } else if (st & CHBEXT) {
- /* Channel B External Status */
- lp = (struct pt_local*)pt0b.priv;
- pt_exisr(lp);
- }
- /* Reset highest interrupt under service */
- save_flags(flags);
- cli();
- wrtscc(lp->cardbase, lp->base + CTL, R0, RES_H_IUS);
- restore_flags(flags);
- } /* end of SCC ints */
-
- if (!(intreg & PT_TMR1_MSK))
- {
- /* Clear timer 1 */
- inb_p(cbase + TMR1CLR);
-
- pt_tmrisr( (struct pt_local*)pt0a.priv);
- }
-
- if (!(intreg & PT_TMR2_MSK))
- {
- /* Clear timer 2 */
- inb_p(cbase + TMR2CLR);
-
- pt_tmrisr( (struct pt_local*)pt0b.priv);
- }
-
- /* Get the next PT interrupt vector */
- intreg = inb_p(cbase + INT_REG);
- } /* while (intreg) */
-} /* pt_interrupt() */
-
-
-static void pt_exisr(struct pt_local *lp)
-{
- unsigned long flags;
- int cmd = lp->base + CTL;
- unsigned char st;
- char c;
- int length;
-
- save_flags(flags);
- cli();
-
- /* Get external status */
- st = rdscc(lp->cardbase, cmd, R0);
-
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: exisr(): R0 = %#3x tstate = %d (%d).\n", st, lp->tstate, lp->base & CHANA);
-#endif
- /* Reset external status latch */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
-
- if ((lp->rstate >= ACTIVE) && (st & BRK_ABRT) && lp->dmachan)
- {
- setup_rx_dma(lp);
- lp->rstate = ACTIVE;
- }
-
- switch (lp->tstate)
- {
- case ACTIVE: /* Unexpected underrun */
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: exisr(): unexpected underrun detected.\n");
-#endif
- kfree_skb(lp->sndbuf);
- lp->sndbuf = NULL;
- if (!lp->dmachan)
- {
- wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);
- lp->stats.tx_errors++;
- lp->stats.tx_fifo_errors++;
- }
- lp->tstate = FLAGOUT;
- tdelay(lp, lp->squeldelay);
- restore_flags(flags);
- return;
- case UNDERRUN:
- lp->tstate = CRCOUT;
- restore_flags(flags);
- return;
- case FLAGOUT:
- /* squeldelay has timed out */
- /* Find a frame for transmission */
- if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL)
- {
- /* Nothing to send - return to Rx mode */
- pt_rts(lp, OFF);
- lp->tstate = IDLE;
- restore_flags(flags);
- return;
- }
- if (!lp->dmachan)
- {
- lp->txptr = lp->sndbuf->data;
- lp->txptr++; /* Ignore KISS control byte */
- lp->txcnt = (int) lp->sndbuf->len - 1;
- }
- /* Fall through if we have a packet */
-
- case ST_TXDELAY:
- if (lp->dmachan)
- {
- /* Disable DMA chan */
- disable_dma(lp->dmachan);
-
- /* Set up for TX dma */
- wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);
-
- length = lp->sndbuf->len - 1;
- memcpy(lp->txdmabuf, &lp->sndbuf->data[1], length);
-
- /* Setup DMA controller for Tx */
- setup_tx_dma(lp, length);
-
- enable_dma(lp->dmachan);
-
- /* Reset CRC, Txint pending */
- wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC | RES_Tx_P);
-
- /* Allow underrun only */
- wrtscc(lp->cardbase, cmd, R15, TxUIE);
-
- /* Enable TX DMA */
- wrtscc(lp->cardbase, cmd, R1, WT_RDY_ENAB | WT_FN_RDYFN | EXT_INT_ENAB);
-
- /* Send CRC on underrun */
- wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);
-
- lp->tstate = ACTIVE;
- break;
- }
- /* Get first char to send */
- lp->txcnt--;
- c = *lp->txptr++;
- /* Reset CRC for next frame */
- wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC);
-
- /* send abort on underrun */
- if (lp->nrzi)
- {
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI | ABUNDER);
- } else {
- wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZ | ABUNDER);
- }
- /* send first char */
- wrtscc(lp->cardbase, cmd, R8, c);
-
- /* Reset end of message latch */
- wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);
-
- /* stuff an extra one in */
-/* while ((rdscc(lp->cardbase, cmd, R0) & Tx_BUF_EMP) && lp->txcnt)
- {
- lp->txcnt--;
- c = *lp->txptr++;
- wrtscc(lp->cardbase, cmd, R8, c);
- }*/
-
- /* select Tx interrupts to enable */
- /* Allow underrun int only */
- wrtscc(lp->cardbase, cmd, R15, TxUIE);
-
- /* Reset external interrupts */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
-
- /* Tx and Rx ints enabled */
- wrtscc(lp->cardbase, cmd, R1, TxINT_ENAB | EXT_INT_ENAB);
-
- lp->tstate = ACTIVE;
- restore_flags(flags);
- return;
-
- /* slotime has timed out */
- case DEFER:
- /* Check DCD - debounce it
- * see Intel Microcommunications Handbook, p2-308
- */
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
- if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0)
- {
- lp->tstate = DEFER;
- tdelay(lp, 100);
- /* DEFER until DCD transition or timeout */
- wrtscc(lp->cardbase, cmd, R15, DCDIE);
- restore_flags(flags);
- return;
- }
- if (random() > lp->persist)
- {
- lp->tstate = DEFER;
- tdelay(lp, lp->slotime);
- restore_flags(flags);
- return;
- }
- if (lp->dmachan)
- wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);
- pt_rts(lp, ON); /* Tx on */
- lp->tstate = ST_TXDELAY;
- tdelay(lp, lp->txdelay);
- restore_flags(flags);
- return;
-
- /* Only for int driven parts */
- if (lp->dmachan)
- {
- restore_flags(flags);
- return;
- }
-
- } /* end switch */
- /*
- * Rx mode only
- * This triggers when hunt mode is entered, & since an ABORT
- * automatically enters hunt mode, we use that to clean up
- * any waiting garbage
- */
- if ((lp->rstate == ACTIVE) && (st & BRK_ABRT) )
- {
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: exisr(): abort detected.\n");
-#endif
- /* read and dump all of SCC Rx FIFO */
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
- (void) rdscc(lp->cardbase, cmd, R8);
-
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
-
- /* Re-sync the SCC */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
-
- }
-
- /* Check for DCD transitions */
- if ( (st & DCD) != (lp->saved_RR0 & DCD))
- {
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_exisr(): DCD is now %s.\n", (st & DCD)? "ON" : "OFF" );
-#endif
- if (st & DCD)
- {
- /* Check that we don't already have some data */
- if (lp->rcvbuf->cnt > 0)
- {
-#ifdef PT_DEBUG
- printk(KERN_DEBUG "PT: pt_exisr() dumping %u bytes from buffer.\n", lp->rcvbuf->cnt);
-#endif
- /* wind back buffers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
- }
- } else { /* DCD off */
-
- /* read and dump al SCC FIFO */
- (void)rdscc(lp->cardbase, cmd, R8);
- (void)rdscc(lp->cardbase, cmd, R8);
- (void)rdscc(lp->cardbase, cmd, R8);
-
- /* wind back buffers */
- lp->rcp = lp->rcvbuf->data;
- lp->rcvbuf->cnt = 0;
-
- /* Re-sync the SCC */
- wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
- }
-
- }
- /* Update the saved version of register RR) */
- lp->saved_RR0 = st &~ ZCOUNT;
- restore_flags(flags);
-
-} /* pt_exisr() */
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-MODULE_AUTHOR("Craig Small VK2XLZ <vk2xlz@vk2xlz.ampr.org>");
-MODULE_DESCRIPTION("AX.25 driver for the Gracillis PacketTwin HDLC card");
-
-int init_module(void)
-{
- return ptwin_init();
-}
-
-void cleanup_module(void)
-{
- free_irq(pt0a.irq, &pt0a); /* IRQs and IO Ports are shared */
- release_region(pt0a.base_addr & 0x3f0, PT_TOTAL_SIZE);
-
- kfree(pt0a.priv);
- pt0a.priv = NULL;
- unregister_netdev(&pt0a);
-
- kfree(pt0b.priv);
- pt0b.priv = NULL;
- unregister_netdev(&pt0b);
-}
-#endif
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 2ea55b0f1..d65fddc41 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1,7 +1,6 @@
#define RCS_ID "$Id: scc.c,v 1.75 1998/11/04 15:15:01 jreuter Exp jreuter $"
#define VERSION "3.0"
-#define BANNER "AX.25: Z8530 SCC driver version "VERSION".dl1bke\n"
/*
* Please use z8530drv-utils-3.0 with this version.
@@ -142,8 +141,6 @@
#define SCC_MAXCHIPS 4 /* number of max. supported chips */
#define SCC_BUFSIZE 384 /* must not exceed 4096 */
-#undef SCC_DISABLE_ALL_INTS /* use cli()/sti() in ISR instead of */
- /* enable_irq()/disable_irq() */
#undef SCC_DEBUG
#define SCC_DEFAULT_CLOCK 4915200
@@ -187,12 +184,7 @@
#include <linux/kernel.h>
#include <linux/proc_fs.h>
-#ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
-#endif
-
-int scc_init(void);
+static const char banner[] __initdata = KERN_INFO "AX.25: Z8530 SCC driver version "VERSION".dl1bke\n";
static void t_dwait(unsigned long);
static void t_txdelay(unsigned long);
@@ -220,7 +212,6 @@ static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb);
static int scc_net_tx(struct sk_buff *skb, struct net_device *dev);
static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
static int scc_net_set_mac_address(struct net_device *dev, void *addr);
-static int scc_net_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len);
static struct net_device_stats * scc_net_get_stats(struct net_device *dev);
static unsigned char *SCC_DriverName = "scc";
@@ -235,9 +226,9 @@ static struct scc_ctrl {
int irq;
} SCC_ctrl[SCC_MAXCHIPS+1];
-static unsigned char Driver_Initialized = 0;
-static int Nchips = 0;
-static io_port Vector_Latch = 0;
+static unsigned char Driver_Initialized;
+static int Nchips;
+static io_port Vector_Latch;
/* ******************************************************************** */
@@ -298,18 +289,6 @@ static inline void cl(struct scc_channel *scc, unsigned char reg, unsigned char
OutReg(scc->ctrl, reg, (scc->wreg[reg] &= ~val));
}
-#ifdef SCC_DISABLE_ALL_INTS
-static inline void scc_cli(int irq)
-{ cli(); }
-static inline void scc_sti(int irq)
-{ sti(); }
-#else
-static inline void scc_cli(int irq)
-{ disable_irq(irq); }
-static inline void scc_sti(int irq)
-{ enable_irq(irq); }
-#endif
-
/* ******************************************************************** */
/* * Some useful macros * */
/* ******************************************************************** */
@@ -1427,7 +1406,6 @@ static unsigned long scc_get_param(struct scc_channel *scc, unsigned int cmd)
}
#undef CAST
-#undef SVAL
/* ******************************************************************* */
/* * Send calibration pattern * */
@@ -1572,12 +1550,12 @@ static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int addev
dev->priv = (void *) scc;
dev->init = scc_net_init;
- if ((addev? register_netdevice(dev) : register_netdev(dev)) != 0)
- {
+ if ((addev? register_netdevice(dev) : register_netdev(dev)) != 0) {
kfree(dev);
return -EIO;
}
+ SET_MODULE_OWNER(dev);
return 0;
}
@@ -1604,7 +1582,7 @@ static int scc_net_init(struct net_device *dev)
dev->stop = scc_net_close;
dev->hard_start_xmit = scc_net_tx;
- dev->hard_header = scc_net_header;
+ dev->hard_header = ax25_encapsulate;
dev->rebuild_header = ax25_rebuild_header;
dev->set_mac_address = scc_net_set_mac_address;
dev->get_stats = scc_net_get_stats;
@@ -1633,8 +1611,6 @@ static int scc_net_open(struct net_device *dev)
if (!scc->init)
return -EINVAL;
- MOD_INC_USE_COUNT;
-
scc->tx_buff = NULL;
skb_queue_head_init(&scc->tx_queue);
@@ -1667,7 +1643,6 @@ static int scc_net_close(struct net_device *dev)
scc_discard_buffers(scc);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -1675,8 +1650,7 @@ static int scc_net_close(struct net_device *dev)
static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb)
{
- if (skb->len == 0)
- {
+ if (skb->len == 0) {
dev_kfree_skb_irq(skb);
return;
}
@@ -1700,8 +1674,7 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev)
unsigned long flags;
char kisscmd;
- if (skb->len > scc->stat.bufsize || skb->len < 2)
- {
+ if (skb->len > scc->stat.bufsize || skb->len < 2) {
scc->dev_stat.tx_dropped++; /* bogus frame */
dev_kfree_skb(skb);
return 0;
@@ -1713,8 +1686,7 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev)
kisscmd = *skb->data & 0x1f;
skb_pull(skb, 1);
- if (kisscmd)
- {
+ if (kisscmd) {
scc_set_param(scc, kisscmd, *skb->data);
dev_kfree_skb(skb);
return 0;
@@ -1723,8 +1695,7 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev)
save_flags(flags);
cli();
- if (skb_queue_len(&scc->tx_queue) > scc->dev->tx_queue_len)
- {
+ if (skb_queue_len(&scc->tx_queue) > scc->dev->tx_queue_len) {
struct sk_buff *skb_del;
skb_del = skb_dequeue(&scc->tx_queue);
dev_kfree_skb(skb_del);
@@ -1739,8 +1710,7 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev)
* algorithm for normal halfduplex operation.
*/
- if(scc->stat.tx_state == TXS_IDLE || scc->stat.tx_state == TXS_IDLE2)
- {
+ if(scc->stat.tx_state == TXS_IDLE || scc->stat.tx_state == TXS_IDLE2) {
scc->stat.tx_state = TXS_BUSY;
if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
scc_start_tx_timer(scc, t_dwait, scc->kiss.waittime);
@@ -1804,8 +1774,12 @@ static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Ivec[hwcfg.irq].used = 1;
}
- if (hwcfg.vector_latch)
- Vector_Latch = hwcfg.vector_latch;
+ if (hwcfg.vector_latch) {
+ if (!request_region(Vector_Latch, 1, "scc vector latch"))
+ printk(KERN_WARNING "z8530drv: warning, cannot reserve vector latch port 0x%x\n, disabled.", hwcfg.vector_latch);
+ else
+ Vector_Latch = hwcfg.vector_latch;
+ }
if (hwcfg.clock == 0)
hwcfg.clock = SCC_DEFAULT_CLOCK;
@@ -2001,14 +1975,6 @@ static int scc_net_set_mac_address(struct net_device *dev, void *addr)
return 0;
}
-/* ----> "hard" header <---- */
-
-static int scc_net_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, void *daddr, void *saddr, unsigned len)
-{
- return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
-}
-
/* ----> get statistics <---- */
static struct net_device_stats *scc_net_get_stats(struct net_device *dev)
@@ -2133,41 +2099,18 @@ done:
return len;
}
-#ifdef CONFIG_PROC_FS
-#define scc_net_procfs_init() proc_net_create("z8530drv",0,scc_net_get_info)
-#define scc_net_procfs_remove() proc_net_remove("z8530drv")
-#else
-#define scc_net_procfs_init()
-#define scc_net_procfs_remove()
-#endif
-
-
+
/* ******************************************************************** */
/* * Init SCC driver * */
/* ******************************************************************** */
static int __init scc_init_driver (void)
{
- int chip, chan, k, result;
+ int result;
char devname[10];
- printk(KERN_INFO BANNER);
-
- memset(&SCC_ctrl, 0, sizeof(SCC_ctrl));
+ printk(banner);
- /* pre-init channel information */
-
- for (chip = 0; chip < SCC_MAXCHIPS; chip++)
- {
- memset((char *) &SCC_Info[2*chip ], 0, sizeof(struct scc_channel));
- memset((char *) &SCC_Info[2*chip+1], 0, sizeof(struct scc_channel));
-
- for (chan = 0; chan < 2; chan++)
- SCC_Info[2*chip+chan].magic = SCC_MAGIC;
- }
-
- for (k = 0; k < 16; k++) Ivec[k].used = 0;
-
sprintf(devname,"%s0", SCC_DriverName);
result = scc_net_setup(SCC_Info, devname, 0);
@@ -2177,7 +2120,7 @@ static int __init scc_init_driver (void)
return result;
}
- scc_net_procfs_init();
+ proc_net_create("z8530drv", 0, scc_net_get_info);
return 0;
}
@@ -2193,7 +2136,10 @@ static void __exit scc_cleanup_driver(void)
cli();
if (Nchips == 0)
+ {
unregister_netdev(SCC_Info[0].dev);
+ kfree(SCC_Info[0].dev);
+ }
for (k = 0; k < Nchips; k++)
if ( (ctrl = SCC_ctrl[k].chan_A) )
@@ -2206,24 +2152,27 @@ static void __exit scc_cleanup_driver(void)
for (k = 0; k < Nchips*2; k++)
{
scc = &SCC_Info[k];
- if (scc)
+ if (scc->ctrl)
{
release_region(scc->ctrl, 1);
release_region(scc->data, 1);
- if (scc->dev)
- {
- unregister_netdev(scc->dev);
- kfree(scc->dev);
- }
+ }
+ if (scc->dev)
+ {
+ unregister_netdev(scc->dev);
+ kfree(scc->dev);
}
}
for (k=0; k < 16 ; k++)
if (Ivec[k].used) free_irq(k, NULL);
+ if (Vector_Latch)
+ release_region(Vector_Latch, 1);
+
restore_flags(flags);
- scc_net_procfs_remove();
+ proc_net_remove("z8530drv");
}
MODULE_AUTHOR("Joerg Reuter <jreuter@yaina.de>");
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c
index a840222af..c50444ad0 100644
--- a/drivers/net/hydra.c
+++ b/drivers/net/hydra.c
@@ -1,24 +1,16 @@
-/* Linux/68k Hydra Amiganet board driver v2.1 BETA */
-/* copyleft by Topi Kanerva (topi@susanna.oulu.fi) */
-/* also some code & lots of fixes by Timo Rossi (trossi@cc.jyu.fi) */
-
-/* The code is mostly based on the linux/68k Ariadne driver */
-/* copyrighted by Geert Uytterhoeven (geert@linux-m68k.org) */
-/* and Peter De Schrijver (Peter.DeSchrijver@linux.cc.kuleuven.ac.be) */
+/* New Hydra driver using generic 8390 core */
+/* Based on old hydra driver by Topi Kanerva (topi@susanna.oulu.fi) */
/* This file is subject to the terms and conditions of the GNU General */
/* Public License. See the file COPYING in the main directory of the */
/* Linux distribution for more details. */
+/* Peter De Schrijver (p2@mind.be) */
+/* Oldenburg 2000 */
+
/* The Amiganet is a Zorro-II board made by Hydra Systems. It contains a */
/* NS8390 NIC (network interface controller) clone, 16 or 64K on-board RAM */
/* and 10BASE-2 (thin coax) and AUI connectors. */
-/* */
-/* Changes */
-/* Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/06/2000 */
-/* - check init_etherdev in hydra_probe */
-/* - dev->priv is already zeroed by init_etherdev */
-
#include <linux/module.h>
#include <linux/kernel.h>
@@ -42,649 +34,229 @@
#include <asm/amigahw.h>
#include <linux/zorro.h>
-#include "hydra.h"
-
-
-#define HYDRA_DEBUG
-#undef HAVE_MULTICAST
-
-#define HYDRA_VERSION "v2.1 BETA"
-
-#undef HYDRA_DEBUG /* define this for (lots of) debugging information */
+#include "8390.h"
-#if 0 /* currently hardwired to one transmit buffer */
- #define TX_RING_SIZE 5
- #define RX_RING_SIZE 16
-#else
- #define TX_RING_SIZE 1
- #define RX_RING_SIZE 8
-#endif
+#define NE_BASE (dev->base_addr)
+#define NE_CMD (0x00*2)
-#define ETHER_MIN_LEN 64
-#define ETHER_MAX_LEN 1518
-#define ETHER_ADDR_LEN 6
+#define NE_EN0_ISR (0x07*2)
+#define NE_EN0_DCFG (0x0e*2)
+#define NE_EN0_RSARLO (0x08*2)
+#define NE_EN0_RSARHI (0x09*2)
+#define NE_EN0_RCNTLO (0x0a*2)
+#define NE_EN0_RXCR (0x0c*2)
+#define NE_EN0_TXCR (0x0d*2)
+#define NE_EN0_RCNTHI (0x0b*2)
+#define NE_EN0_IMR (0x0f*2)
-/*
- * let's define here nice macros for writing and reading NIC registers
- *
- * the CIA accesses here are uses to make sure the minimum time
- * requirement between NIC chip selects is met.
- */
-#define WRITE_REG(reg, val) (ciaa.pra, ((u8)(*(nicbase+(reg))=val)))
-#define READ_REG(reg) (ciaa.pra, ((u8)(*(nicbase+(reg)))))
+#define NESM_START_PG 0x0 /* First page of TX buffer */
+#define NESM_STOP_PG 0x40 /* Last page +1 of RX ring */
-/* mask value for the interrupts we use */
-#define NIC_INTS (ISR_PRX | ISR_PTX | ISR_RXE | ISR_TXE | ISR_OVW | ISR_CNT)
+#define HYDRA_NIC_BASE 0xffe1
+#define HYDRA_ADDRPROM 0xffc0
+#define HYDRA_VERSION "v3.0alpha"
-/* only broadcasts, no promiscuous mode for now */
-#define NIC_RCRBITS (0)
+#define WORDSWAP(a) ((((a)>>8)&0xff) | ((a)<<8))
-/*
- * Private Device Data
- */
-struct hydra_private
-{
- u16 tx_page_start;
- u16 rx_page_start;
- u16 rx_page_stop;
- u16 next_pkt;
- struct net_device_stats stats;
-};
+#ifdef MODULE
+static struct net_device *root_hydra_dev = NULL;
+#endif
+static int __init hydra_probe(void);
+static int hydra_init(unsigned long board);
static int hydra_open(struct net_device *dev);
-static int hydra_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void hydra_interrupt(int irq, void *data, struct pt_regs *fp);
-static void __inline__ hydra_rx(struct net_device *dev, struct hydra_private *priv, volatile u8 *nicbase);
static int hydra_close(struct net_device *dev);
-static struct net_device_stats *hydra_get_stats(struct net_device *dev);
-#ifdef HAVE_MULTICAST
-static void set_multicast_list(struct net_device *dev, int num_addrs, void *addrs);
-#endif
-
-
-/* this is now coherent with the C version below, */
-/* compile the source with -D__USE_ASM__ if you */
-/* want it - it'll only be some 10% faster though */
-
-#if defined (__GNUC__) && defined (__mc68000__) && defined (USE_ASM)
-
-static __inline__ void *memcpyw(u16 *dest, u16 *src, int len)
+static void hydra_reset_8390(struct net_device *dev);
+static void hydra_get_8390_hdr(struct net_device *dev,
+ struct e8390_pkt_hdr *hdr, int ring_page);
+static void hydra_block_input(struct net_device *dev, int count,
+ struct sk_buff *skb, int ring_offset);
+static void hydra_block_output(struct net_device *dev, int count,
+ const unsigned char *buf, int start_page);
+static void __exit hydra_cleanup(void);
+
+static int __init hydra_probe(void)
{
- __asm__(" move.l %0,%/a1; move.l %1,%/a0; move.l %2,%/d0 \n\t"
- " cmpi.l #2,%/d0 \n\t"
- "1: bcs.s 2f \n\t"
- " move.w %/a0@+,%/a1@+ \n\t"
- " subq.l #2,%/d0 \n\t"
- " bra.s 1b \n\t"
- "2: cmpi.l #1,%/d0 \n\t"
- " bne.s 3f \n\t"
- " move.w %/a0@,%/d0 \n\t"
- " swap.w %/d0 \n\t"
- " move.b %/d0,%/a1@ \n\t"
- "3: moveq #0,%/d0 \n\t"
- :
- : "g" (dest), "g" (src), "g" (len)
- : "a1", "a0", "d0");
- return;
+ struct zorro_dev *z = NULL;
+ unsigned long board;
+ int err = -ENODEV;
+
+ if (load_8390_module("hydra.c"))
+ return -ENOSYS;
+
+ while ((z = zorro_find_device(ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET, z))) {
+ board = z->resource.start;
+ if (!request_mem_region(board, 0x10000, "Hydra"))
+ continue;
+ if ((err = hydra_init(ZTWO_VADDR(board)))) {
+ release_mem_region(board, 0x10000);
+ return err;
+ }
+ err = 0;
+ }
+
+ if (err == -ENODEV) {
+ printk("No Hydra ethernet card found.\n");
+ unload_8390_module();
+ }
+ return err;
}
-#else
-
-/* hydra memory can only be read or written as words or longwords. */
-/* that will mean that we'll have to write a special memcpy for it. */
-/* this one here relies on the fact that _writes_ to hydra memory */
-/* are guaranteed to be of even length. (reads can be arbitrary) */
-
-/*
- * FIXME: Surely we should be using the OS generic stuff and do
- *
- * memcpy(dest,src,(len+1)&~1);
- *
- * Can a 68K guy with this card check that ? - better yet
- * use a copy/checksum on it.
- */
-
-static void memcpyw(u16 *dest, u16 *src, int len)
+int __init hydra_init(unsigned long board)
{
- if(len & 1)
- len++;
+ struct net_device *dev;
+ unsigned long ioaddr = board+HYDRA_NIC_BASE;
+ const char *name = NULL;
+ int start_page, stop_page;
+ int j;
+
+ static u32 hydra_offsets[16] = {
+ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
+ };
+
+ dev = init_etherdev(0, 0);
+ if (!dev)
+ return -ENOMEM;
+
+ for(j = 0; j < ETHER_ADDR_LEN; j++)
+ dev->dev_addr[j] = *((u8 *)(board + HYDRA_ADDRPROM + 2*j));
+
+ /* We must set the 8390 for word mode. */
+ writeb(0x4b, ioaddr + NE_EN0_DCFG);
+ start_page = NESM_START_PG;
+ stop_page = NESM_STOP_PG;
+
+ dev->base_addr = ioaddr;
+ dev->irq = IRQ_AMIGA_PORTS;
+
+ /* Install the Interrupt handler */
+ if (request_irq(IRQ_AMIGA_PORTS, ei_interrupt, SA_SHIRQ, "Hydra Ethernet",
+ dev))
+ return -EAGAIN;
+
+ /* Allocate dev->priv and fill in 8390 specific dev fields. */
+ if (ethdev_init(dev)) {
+ printk("Unable to get memory for dev->priv.\n");
+ return -ENOMEM;
+ }
- while (len >= 2)
- {
- *(dest++) = *(src++);
- len -= 2;
- }
-}
+ name = "NE2000";
-#endif
+ printk("%s: hydra at 0x%08lx, address %02x:%02x:%02x:%02x:%02x:%02x (hydra.c " HYDRA_VERSION ")\n", dev->name, ZTWO_PADDR(board),
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
-int __init hydra_probe(struct net_device *dev)
-{
- struct zorro_dev *z = NULL;
- int j;
+ ei_status.name = name;
+ ei_status.tx_start_page = start_page;
+ ei_status.stop_page = stop_page;
+ ei_status.word16 = 1;
+ ei_status.bigendian = 1;
-#ifdef HYDRA_DEBUG
- printk("hydra_probe(%x)\n", dev);
-#endif
+ ei_status.rx_start_page = start_page + TX_PAGES;
- while ((z = zorro_find_device(ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET, z))) {
- unsigned long board = z->resource.start;
- unsigned long base_addr = board+HYDRA_NIC_BASE;
-
- if (!request_mem_region(base_addr, 0x20, "NS8390"))
- continue;
- if (!request_mem_region(board, 0x4000, "RAM")) {
- release_mem_region(base_addr, 0x20);
- continue;
- }
-
- dev = init_etherdev(NULL, sizeof(struct hydra_private));
-
- if (!dev) {
- release_mem_region(base_addr, 0x20);
- release_mem_region(board, 0x4000);
- continue;
- }
- SET_MODULE_OWNER(dev);
-
- for(j = 0; j < ETHER_ADDR_LEN; j++)
- dev->dev_addr[j] = *((u8 *)ZTWO_VADDR(board + HYDRA_ADDRPROM + 2*j));
-
- printk("%s: hydra at 0x%08x, address %02x:%02x:%02x:%02x:%02x:%02x (hydra.c " HYDRA_VERSION ")\n",
- dev->name, (int)board, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
- dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
-
- dev->base_addr = ZTWO_VADDR(base_addr);
- dev->mem_start = ZTWO_VADDR(board);
- dev->mem_end = dev->mem_start+0x4000;
-
- dev->open = &hydra_open;
- dev->stop = &hydra_close;
- dev->hard_start_xmit = &hydra_start_xmit;
- dev->get_stats = &hydra_get_stats;
-#ifdef HAVE_MULTICAST
- dev->set_multicast_list = &set_multicast_list;
+ ei_status.reset_8390 = &hydra_reset_8390;
+ ei_status.block_input = &hydra_block_input;
+ ei_status.block_output = &hydra_block_output;
+ ei_status.get_8390_hdr = &hydra_get_8390_hdr;
+ ei_status.reg_offset = hydra_offsets;
+ dev->open = &hydra_open;
+ dev->stop = &hydra_close;
+#ifdef MODULE
+ ei_status.priv = (unsigned long)root_hydra_dev;
+ root_hydra_dev = dev;
#endif
-
- /*
- * Cannot yet do multicast
- */
- dev->flags&=~IFF_MULTICAST;
- return(0);
- }
- return(-ENODEV);
+ NS8390_init(dev, 0);
+ return 0;
}
-
static int hydra_open(struct net_device *dev)
{
- struct hydra_private *priv = (struct hydra_private *)dev->priv;
- volatile u8 *nicbase = (u8 *)dev->base_addr;
- int i;
-
-#ifdef HYDRA_DEBUG
- printk("hydra_open(0x%x)\n", dev);
-#endif
-
- /* first, initialize the private structure */
- priv->tx_page_start = 0; /* these are 256 byte buffers for NS8390 */
- priv->rx_page_start = 6;
- priv->rx_page_stop = 62; /* these values are hard coded for now */
-
- /* Reset the NS8390 NIC */
- WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_STOP);
-
- /* be sure that the NIC is in stopped state */
- while(!(READ_REG(NIC_ISR) & ISR_RST));
-
- /* word transfer, big endian bytes, loopback, FIFO threshold 4 bytes */
- WRITE_REG(NIC_DCR, DCR_WTS | DCR_BOS | DCR_LS | DCR_FT0);
-
- /* clear remote byte count registers */
- WRITE_REG(NIC_RBCR0, 0);
- WRITE_REG(NIC_RBCR1, 0);
-
- /* accept packets addressed to this card and also broadcast packets */
- WRITE_REG(NIC_RCR, NIC_RCRBITS);
-
- /* enable loopback mode 1 */
- WRITE_REG(NIC_TCR, TCR_LB1);
-
- /* initialize receive buffer ring */
- WRITE_REG(NIC_PSTART, priv->rx_page_start);
- WRITE_REG(NIC_PSTOP, priv->rx_page_stop);
- WRITE_REG(NIC_BNDRY, priv->rx_page_start);
-
- /* clear interrupts */
- WRITE_REG(NIC_ISR, 0xff);
-
- /* enable interrupts */
- WRITE_REG(NIC_IMR, NIC_INTS);
-
- /* set the ethernet hardware address */
- WRITE_REG(NIC_CR, CR_PAGE1 | CR_NODMA | CR_STOP); /* goto page 1 */
-
- WRITE_REG(NIC_PAR0, dev->dev_addr[0]);
- WRITE_REG(NIC_PAR1, dev->dev_addr[1]);
- WRITE_REG(NIC_PAR2, dev->dev_addr[2]);
- WRITE_REG(NIC_PAR3, dev->dev_addr[3]);
- WRITE_REG(NIC_PAR4, dev->dev_addr[4]);
- WRITE_REG(NIC_PAR5, dev->dev_addr[5]);
-
- /* clear multicast hash table */
- for(i = 0; i < 8; i++)
- WRITE_REG(NIC_MAR0 + 2*i, 0);
-
- priv->next_pkt = priv->rx_page_start+1; /* init our s/w variable */
- WRITE_REG(NIC_CURR, priv->next_pkt); /* set the next buf for current */
-
- /* goto page 0, start NIC */
- WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_START);
-
- /* take interface out of loopback */
- WRITE_REG(NIC_TCR, 0);
-
- netif_start_queue(dev);
-
- i = request_irq(IRQ_AMIGA_PORTS, hydra_interrupt, SA_SHIRQ,
- dev->name, dev);
- if (i) return i;
-
- return(0);
+ ei_open(dev);
+ MOD_INC_USE_COUNT;
+ return 0;
}
-
static int hydra_close(struct net_device *dev)
{
- struct hydra_private *priv = (struct hydra_private *)dev->priv;
- volatile u8 *nicbase = (u8 *)dev->base_addr;
- int n = 5000;
-
- netif_stop_queue(dev);
-
-#ifdef HYDRA_DEBUG
- printk("%s: Shutting down ethercard\n", dev->name);
- printk("%s: %d packets missed\n", dev->name, priv->stats.rx_missed_errors);
-#endif
-
- WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_STOP);
-
- /* wait for NIC to stop (what a nice timeout..) */
- while(((READ_REG(NIC_ISR) & ISR_RST) == 0) && --n);
-
- free_irq(IRQ_AMIGA_PORTS, dev);
-
- return(0);
+ if (ei_debug > 1)
+ printk("%s: Shutting down ethercard.\n", dev->name);
+ ei_close(dev);
+ MOD_DEC_USE_COUNT;
+ return 0;
}
-
-static void hydra_interrupt(int irq, void *data, struct pt_regs *fp)
-{
- volatile u8 *nicbase;
-
- struct net_device *dev = (struct net_device *) data;
- struct hydra_private *priv;
- u16 intbits;
-
- if(dev == NULL)
- {
- printk("hydra_interrupt(): irq for unknown device\n");
- return;
- }
-
- /* this is not likely a problem - i think */
- if(dev->interrupt)
- printk("%s: re-entering the interrupt handler\n", dev->name);
-
- dev->interrupt = 1;
-
- priv = (struct hydra_private *) dev->priv;
- nicbase = (u8 *)dev->base_addr;
-
- /* select page 0 */
- WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA);
-
- intbits = READ_REG(NIC_ISR) & NIC_INTS;
- if(intbits == 0)
- {
- dev->interrupt = 0;
- return;
- }
-
- /* acknowledge all interrupts, by clearing the interrupt flag */
- WRITE_REG(NIC_ISR, intbits);
-
- if((intbits & ISR_PTX) && !(intbits & ISR_TXE))
- {
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
-
- if((intbits & ISR_PRX) && !(intbits & ISR_RXE))/* packet received OK */
- hydra_rx(dev, priv, nicbase);
-
- if(intbits & ISR_TXE)
- priv->stats.tx_errors++;
-
- if(intbits & ISR_RXE)
- priv->stats.rx_errors++;
-
- if(intbits & ISR_CNT)
- {
- /*
- * read the tally counters and (currently) ignore the values
- * might be useful because of bugs of some versions of the 8390 NIC
- */
-#ifdef HYDRA_DEBUG
- printk("hydra_interrupt(): ISR_CNT\n");
-#endif
- (void)READ_REG(NIC_CNTR0);
- (void)READ_REG(NIC_CNTR1);
- (void)READ_REG(NIC_CNTR2);
- }
-
- if(intbits & ISR_OVW)
- {
-#ifdef HYDRA_DEBUG
- WRITE_REG(NIC_CR, CR_PAGE1 | CR_START | CR_NODMA);
-/* another one just too much for me to comprehend - basically this could */
-/* only occur because of invalid access to hydra ram, thus invalidating */
-/* the interrupt bits read - in average usage these do not occur at all */
- printk("hydra_interrupt(): overwrite warning, NIC_ISR %02x, NIC_CURR %02x\n",
- intbits, READ_REG(NIC_CURR));
- WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA);
-#endif
-
-
- /* overwrite warning occurred, stop NIC & check the BOUNDARY pointer */
- /* FIXME - real overwrite handling needed !! */
-
- printk("hydra_interrupt(): overwrite warning, resetting NIC\n");
- WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_STOP);
- while(!(READ_REG(NIC_ISR) & ISR_RST));
- /* wait for NIC to reset */
- WRITE_REG(NIC_DCR, DCR_WTS | DCR_BOS | DCR_LS | DCR_FT0);
- WRITE_REG(NIC_RBCR0, 0);
- WRITE_REG(NIC_RBCR1, 0);
- WRITE_REG(NIC_RCR, NIC_RCRBITS);
- WRITE_REG(NIC_TCR, TCR_LB1);
- WRITE_REG(NIC_PSTART, priv->rx_page_start);
- WRITE_REG(NIC_PSTOP, priv->rx_page_stop);
- WRITE_REG(NIC_BNDRY, priv->rx_page_start);
- WRITE_REG(NIC_ISR, 0xff);
- WRITE_REG(NIC_IMR, NIC_INTS);
- /* currently this _won't_ reset my hydra, even though it is */
- /* basically the same code as in the board init - any ideas? */
-
- priv->next_pkt = priv->rx_page_start+1; /* init our s/w variable */
- WRITE_REG(NIC_CURR, priv->next_pkt); /* set the next buf for current */
-
- WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_START);
-
- WRITE_REG(NIC_TCR, 0);
- }
-
- dev->interrupt = 0;
- return;
- }
-
-
-/*
- * packet transmit routine
- */
-
-static int hydra_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static void hydra_reset_8390(struct net_device *dev)
{
- struct hydra_private *priv = (struct hydra_private *)dev->priv;
- volatile u8 *nicbase = (u8 *)dev->base_addr;
- int len, len1;
-
- /* Transmitter timeout, serious problems. */
-
- if(dev->tbusy)
- {
- int tickssofar = jiffies - dev->trans_start;
- if(tickssofar < 20)
- return(1);
- WRITE_REG(NIC_CR, CR_STOP);
- printk("%s: transmit timed out, status %4.4x, resetting.\n", dev->name, 0);
- priv->stats.tx_errors++;
- dev->tbusy = 0;
- dev->trans_start = jiffies;
- return(0);
- }
-
- len=skb->len;
-
- /* fill in a tx ring entry */
-
-#ifdef HYDRA_DEBUG
- printk("TX pkt type 0x%04x from ", ((u16 *)skb->data)[6]);
- {
- int i;
- u8 *ptr = &((u8 *)skb->data)[6];
- for (i = 0; i < 6; i++)
- printk("%02x", ptr[i]);
- }
- printk(" to ");
- {
- int i;
- u8 *ptr = (u8 *)skb->data;
- for (i = 0; i < 6; i++)
- printk("%02x", ptr[i]);
- }
- printk(" data 0x%08x len %d\n", (int)skb->data, len);
-#endif
-
- /*
- * make sure that the packet size is at least the minimum
- * allowed ethernet packet length.
- * (FIXME: Should also clear the unused space...)
- * note: minimum packet length is 64, including CRC
- */
- len1 = len;
-
- if(len < (ETHER_MIN_LEN-4))
- len = (ETHER_MIN_LEN-1);
-
- /* make sure we've got an even number of bytes to copy to hydra's mem */
- if(len & 1) len++;
-
- if((u32)(dev->mem_start + (priv->tx_page_start << 8)) < 0x80000000)
- printk("weirdness: memcpyw(txbuf, skbdata, len): txbuf = 0x%x\n", (u_int)(dev->mem_start+(priv->tx_page_start<<8)));
-
- /* copy the packet data to the transmit buffer
- in the ethernet card RAM */
- memcpyw((u16 *)(dev->mem_start + (priv->tx_page_start << 8)),
- (u16 *)skb->data, len);
- /* clear the unused space */
- for(; len1<len; len1++)
- (u16)*((u8 *)dev->mem_start + (priv->tx_page_start<<8) + len1)
- = 0;
- dev_kfree_skb(skb);
-
- priv->stats.tx_packets++;
-
- cli();
- /* make sure we are on the correct page */
- WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_START);
-
- /* here we configure the transmit page start register etc */
- /* notice that this code is hardwired to one transmit buffer */
- WRITE_REG(NIC_TPSR, priv->tx_page_start);
- WRITE_REG(NIC_TBCR0, len & 0xff);
- WRITE_REG(NIC_TBCR1, len >> 8);
-
- /* commit the packet to the wire */
- WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA | CR_TXP);
- sti();
-
- dev->trans_start = jiffies;
-
- return(0);
+ printk("Hydra hw reset not there\n");
}
-
-static void __inline__ hydra_rx(struct net_device *dev, struct hydra_private *priv, volatile u8 *nicbase)
+static void hydra_get_8390_hdr(struct net_device *dev,
+ struct e8390_pkt_hdr *hdr, int ring_page)
{
- volatile u16 *board_ram_ptr;
- struct sk_buff *skb;
- int hdr_next_pkt, pkt_len, len1, boundary;
-
-
- /* remove packet(s) from the ring and commit them to TCP layer */
- WRITE_REG(NIC_CR, CR_PAGE1 | CR_NODMA | CR_START); /* page 1 */
- while(priv->next_pkt != READ_REG(NIC_CURR)) /* should read this only once? */
- {
- board_ram_ptr = (u16 *)(dev->mem_start + (priv->next_pkt << 8));
-
-#ifdef HYDRA_DEBUG
- printk("next_pkt = 0x%x, board_ram_ptr = 0x%x\n", priv->next_pkt, board_ram_ptr);
-#endif
-
- /* the following must be done with two steps, or
- GCC optimizes it to a byte access to Hydra memory,
- which doesn't work... */
- hdr_next_pkt = board_ram_ptr[0];
- hdr_next_pkt >>= 8;
-
- pkt_len = board_ram_ptr[1];
- pkt_len = ((pkt_len >> 8) | ((pkt_len & 0xff) << 8));
-
-#ifdef HYDRA_DEBUG
- printk("hydra_interrupt(): hdr_next_pkt = 0x%02x, len = %d\n", hdr_next_pkt, pkt_len);
-#endif
-
- if(pkt_len >= ETHER_MIN_LEN && pkt_len <= ETHER_MAX_LEN)
- {
- /* note that board_ram_ptr is u16 */
- /* CRC is not included in the packet length */
-
- pkt_len -= 4;
- skb = dev_alloc_skb(pkt_len+2);
- if(skb == NULL)
- {
- printk(KERN_INFO "%s: memory squeeze, dropping packet.\n", dev->name);
- priv->stats.rx_dropped++;
- }
- else
- {
- skb->dev = dev;
- skb_reserve(skb, 2);
- if(hdr_next_pkt < priv->next_pkt && hdr_next_pkt != priv->rx_page_start)
- {
- /* here, the packet is wrapped */
- len1 = ((priv->rx_page_stop - priv->next_pkt)<<8)-4;
-
- memcpyw((u16 *)skb_put(skb, len1), (u16 *)(board_ram_ptr+2), len1);
- memcpyw((u16 *)skb_put(skb, pkt_len-len1), (u16 *)(dev->mem_start+(priv->rx_page_start<<8)), pkt_len-len1);
-
-#ifdef HYDRA_DEBUG
- printk("wrapped packet: %d/%d bytes\n", len1, pkt_len-len1);
-#endif
- } /* ... here, packet is not wrapped */
- else
- memcpyw((u16 *) skb_put(skb, pkt_len), (u16 *)(board_ram_ptr+2), pkt_len);
- }
- }
- else
- {
- WRITE_REG(NIC_CR, CR_PAGE1 | CR_START | CR_NODMA);
- printk("hydra_interrupt(): invalid packet len: %d, NIC_CURR = %02x\n", pkt_len, READ_REG(NIC_CURR));
-/*
-this is the error i kept getting until i switched to 0.9.10. it still doesn't
-mean that the bug would have gone away - so be alarmed. the packet is likely
-being fetched from a wrong memory location - but why - dunno
-
-note-for-v2.1: not really problem anymore. hasn't been for a long time.
-*/
-
- WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA);
- /* should probably reset the NIC here ?? */
-
- hydra_open(dev); /* FIXME - i shouldn't really be doing this. */
- return;
- }
-
- /* now, update the next_pkt pointer */
- if(hdr_next_pkt < priv->rx_page_stop)
- priv->next_pkt = hdr_next_pkt;
- else
- printk("hydra_interrupt(): invalid next_pkt pointer %d\n", hdr_next_pkt);
-
- /* update the boundary pointer */
- boundary = priv->next_pkt - 1;
- if(boundary < priv->rx_page_start)
- boundary = priv->rx_page_stop - 1;
-
- /* set NIC to page 0 to update the NIC_BNDRY register */
- WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA);
- WRITE_REG(NIC_BNDRY, boundary);
-
- /* select page1 to access the NIC_CURR register */
- WRITE_REG(NIC_CR, CR_PAGE1 | CR_START | CR_NODMA);
-
-
- skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
- priv->stats.rx_packets++;
-
- }
- return;
+ int nic_base = dev->base_addr;
+ short *ptrs;
+ unsigned long hdr_start= (nic_base-HYDRA_NIC_BASE) +
+ ((ring_page - NESM_START_PG)<<8);
+ ptrs = (short *)hdr;
+
+ *(ptrs++) = readw(hdr_start);
+ *((short *)hdr) = WORDSWAP(*((short *)hdr));
+ hdr_start += 2;
+ *(ptrs++) = readw(hdr_start);
+ *((short *)hdr+1) = WORDSWAP(*((short *)hdr+1));
}
-
-static struct net_device_stats *hydra_get_stats(struct net_device *dev)
+static void hydra_block_input(struct net_device *dev, int count,
+ struct sk_buff *skb, int ring_offset)
{
- struct hydra_private *priv = (struct hydra_private *)dev->priv;
-#if 0
- u8 *board = (u8 *)dev->mem_start;
+ unsigned long nic_base = dev->base_addr;
+ unsigned long mem_base = nic_base - HYDRA_NIC_BASE;
+ unsigned long xfer_start = mem_base + ring_offset - (NESM_START_PG<<8);
- short saved_addr;
-#endif
-/* currently does nothing :) i'll finish this later */
+ if (count&1)
+ count++;
- return(&priv->stats);
-}
+ if (xfer_start+count > mem_base + (NESM_STOP_PG<<8)) {
+ int semi_count = (mem_base + (NESM_STOP_PG<<8)) - xfer_start;
-#ifdef HAVE_MULTICAST
-static void set_multicast_list(struct net_device *dev, int num_addrs, void *addrs)
-{
- struct hydra_private *priv = (struct hydra_private *)dev->priv;
- u8 *board = (u8 *)dev->mem_start;
+ memcpy_fromio(skb->data,xfer_start,semi_count);
+ count -= semi_count;
+ memcpy_fromio(skb->data+semi_count, mem_base, count);
+ } else
+ memcpy_fromio(skb->data, xfer_start,count);
- /* yes, this code is also waiting for someone to complete.. :) */
- /* (personally i don't care about multicasts at all :) */
- return;
}
-#endif
-
-
-#ifdef MODULE
-static struct net_device hydra_dev;
-int init_module(void)
+static void hydra_block_output(struct net_device *dev, int count,
+ const unsigned char *buf, int start_page)
{
- int err;
+ unsigned long nic_base = dev->base_addr;
+ unsigned long mem_base = nic_base - HYDRA_NIC_BASE;
- hydra_dev.init = hydra_probe;
- if ((err = register_netdev(&hydra_dev))) {
- if (err == -EIO)
- printk("No Hydra board found. Module not loaded.\n");
- return(err);
- }
- return(0);
+ if (count&1)
+ count++;
+
+ memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count);
}
-void cleanup_module(void)
+static void __exit hydra_cleanup(void)
{
- struct hydra_private *priv = (struct hydra_private *)hydra_dev.priv;
+#ifdef MODULE
+ struct net_device *dev, *next;
- unregister_netdev(&hydra_dev);
- release_mem_region(ZTWO_PADDR(hydra_dev.base_addr), 0x20);
- release_mem_region(ZTWO_PADDR(hydra_dev.mem_start), 0x4000);
- kfree(priv);
+ while ((dev = root_hydra_dev)) {
+ next = (struct net_device *)(ei_status.priv);
+ unregister_netdev(dev);
+ free_irq(IRQ_AMIGA_PORTS, dev);
+ release_mem_region(ZTWO_PADDR(dev->base_addr)-HYDRA_NIC_BASE, 0x10000);
+ kfree(dev);
+ root_hydra_dev = next;
+ }
+ unload_8390_module();
+#endif
}
-#endif /* MODULE */
+module_init(hydra_probe);
+module_exit(hydra_cleanup);
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index ee8d6be16..3ee2a207b 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -50,7 +50,6 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/pci_ids.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
diff --git a/drivers/net/irda/toshoboe.c b/drivers/net/irda/toshoboe.c
index 04d91c232..8d181e872 100644
--- a/drivers/net/irda/toshoboe.c
+++ b/drivers/net/irda/toshoboe.c
@@ -896,7 +896,7 @@ toshoboe_gotosleep (struct toshoboe_cb *self)
/*FIXME: can't sleep here wait one second */
while ((i--) && (self->txpending))
- udelay (100000);
+ mdelay (100);
toshoboe_stopchip (self);
toshoboe_disablebm (self);
diff --git a/drivers/net/mvme147.c b/drivers/net/mvme147.c
index 1d2d4c47b..17959bc2d 100644
--- a/drivers/net/mvme147.c
+++ b/drivers/net/mvme147.c
@@ -63,7 +63,7 @@ static unsigned short m147lance_readrdp(struct m147lance_private *lp);
typedef void (*writerap_t)(void *, unsigned short);
typedef void (*writerdp_t)(void *, unsigned short);
-typedef void (*readrdp_t)(void *);
+typedef unsigned short (*readrdp_t)(void *);
#ifdef MODULE
static struct m147lance_private *root_m147lance_dev = NULL;
@@ -79,7 +79,7 @@ int __init mvme147lance_probe(struct net_device *dev)
u_long address;
if (!MACH_IS_MVME147 || called)
- return(-ENODEV);
+ return -ENODEV;
called++;
SET_MODULE_OWNER(dev);
@@ -96,6 +96,7 @@ int __init mvme147lance_probe(struct net_device *dev)
dev->hard_start_xmit = &lance_start_xmit;
dev->get_stats = &lance_get_stats;
dev->set_multicast_list = &lance_set_multicast;
+ dev->tx_timeout = &lance_tx_timeout;
dev->dma = 0;
addr=(u_long *)ETHERNET_ADDRESS;
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 5292c4a35..1c9be476e 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -540,6 +540,8 @@ static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, i
outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
ei_status.dmaing &= ~0x01;
+
+ le16_to_cpus(&hdr->count);
}
/* Block input and output, similar to the Crynwr packet driver. If you
diff --git a/drivers/net/pcmcia/wavelan_cs.c b/drivers/net/pcmcia/wavelan_cs.c
index e75b59cf3..f435466a0 100644
--- a/drivers/net/pcmcia/wavelan_cs.c
+++ b/drivers/net/pcmcia/wavelan_cs.c
@@ -132,7 +132,7 @@ hacr_write_slow(u_long base,
{
hacr_write(base, hacr);
/* delay might only be needed sometimes */
- udelay(1000L);
+ mdelay(1L);
} /* hacr_write_slow */
/*------------------------------------------------------------------*/
@@ -190,7 +190,7 @@ psa_write(device * dev,
* sequence to write is. This hack seem to work for me... */
count = 0;
while((readb(verify) != PSA_COMP_PCMCIA_915) && (count++ < 100))
- udelay(1000);
+ mdelay(1);
}
/* Put the host interface back in standard state */
@@ -479,7 +479,7 @@ fee_write(u_long base, /* i/o port of the card */
mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WRITE);
/* Wavelan doc says : wait at least 10 ms for EEBUSY = 0 */
- udelay(10000);
+ mdelay(10);
fee_wait(base, 10, 100);
}
@@ -3612,7 +3612,7 @@ wv_hw_config(device * dev)
/* reset the LAN controller (i82593) */
outb(OP0_RESET, LCCR(base));
- udelay(1000L); /* A bit crude ! */
+ mdelay(1); /* A bit crude ! */
/* Initialize the LAN controler */
if((wv_82593_config(dev) == FALSE) ||
diff --git a/drivers/net/rcpci45.c b/drivers/net/rcpci45.c
index 20eeedfb2..81c286256 100644
--- a/drivers/net/rcpci45.c
+++ b/drivers/net/rcpci45.c
@@ -157,7 +157,7 @@ static struct pci_device_id rcpci45_pci_table[] __devinitdata = {
{ RC_PCI45_VENDOR_ID, RC_PCI45_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0, }
};
-MODULE_DEVICE_TABLE(pci, rcpci_pci_table);
+MODULE_DEVICE_TABLE(pci, rcpci45_pci_table);
static void rcpci45_remove_one(struct pci_dev *pdev)
{
diff --git a/drivers/net/setup.c b/drivers/net/setup.c
index 823836cbb..63b493bbd 100644
--- a/drivers/net/setup.c
+++ b/drivers/net/setup.c
@@ -9,13 +9,11 @@
#include <linux/init.h>
#include <linux/netlink.h>
-extern int mkiss_init_ctrl_dev(void);
extern int slip_init_ctrl_dev(void);
extern int strip_init_ctrl_dev(void);
extern int x25_asy_init_ctrl_dev(void);
extern int dmascc_init(void);
-extern int yam_init(void);
extern int awc4500_pci_probe(void);
extern int awc4500_isa_probe(void);
@@ -102,13 +100,6 @@ struct net_probe pci_probes[] __initdata = {
#endif
#endif
-/*
- * Amateur Radio Drivers
- */
-
-#ifdef CONFIG_YAM
- {yam_init, 0},
-#endif /* CONFIG_YAM */
/*
* Token Ring Drivers
@@ -149,9 +140,6 @@ static void __init network_ldisc_init(void)
#if defined(CONFIG_X25_ASY)
x25_asy_init_ctrl_dev();
#endif
-#if defined(CONFIG_MKISS)
- mkiss_init_ctrl_dev();
-#endif
#if defined(CONFIG_STRIP)
strip_init_ctrl_dev();
#endif
diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c
index aa3019098..b8203f33a 100644
--- a/drivers/net/tulip/media.c
+++ b/drivers/net/tulip/media.c
@@ -263,6 +263,24 @@ void tulip_select_media(struct net_device *dev, int startup)
tulip_mdio_write(dev, tp->phys[phy_num], 4, to_advertise);
break;
}
+ case 5: case 6: {
+ u16 setup[5];
+ u32 csr13val, csr14val, csr15dir, csr15val;
+ for (i = 0; i < 5; i++)
+ setup[i] = get_u16(&p[i*2 + 1]);
+
+ if (startup && mtable->has_reset) {
+ struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];
+ unsigned char *rst = rleaf->leafdata;
+ if (tulip_debug > 1)
+ printk(KERN_DEBUG "%s: Resetting the transceiver.\n",
+ dev->name);
+ for (i = 0; i < rst[0]; i++)
+ outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15);
+ }
+
+ break;
+ }
default:
printk(KERN_DEBUG "%s: Invalid media table selection %d.\n",
dev->name, mleaf->type);
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 40fc7921d..765cd6c7c 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -28,7 +28,7 @@
#include <asm/unaligned.h>
static char version[] __devinitdata =
- "Linux Tulip driver version 0.9.12 (December 17, 2000)\n";
+ "Linux Tulip driver version 0.9.13 (January 2, 2001)\n";
/* A few user-configurable values. */
@@ -1044,11 +1044,52 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
if (tulip_debug > 0 && did_version++ == 0)
printk (KERN_INFO "%s", version);
+ /*
+ * Lan media wire a tulip chip to a wan interface. Needs a very
+ * different driver (lmc driver)
+ */
+
if( pdev->subsystem_vendor == 0x1376 ){
printk (KERN_ERR PFX "skipping LMC card.\n");
return -ENODEV;
}
-
+
+ /*
+ * Early DM9100's need software CRC and the DMFE driver
+ */
+
+ if (pdev->vendor == 0x1282 && pdev->device == 0x9100)
+ {
+ u32 dev_rev;
+ /* Read Chip revision */
+ pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev);
+ if(dev_rev < 0x02000030)
+ {
+ printk(KERN_ERR PFX "skipping early DM9100 with Crc bug (use dmfe)\n");
+ return -ENODEV;
+ }
+ }
+
+ /*
+ * Looks for early PCI chipsets where people report hangs
+ * without the workarounds being on.
+ */
+
+ /* Intel Saturn. Switch to 8 long words burst, 8 long word cache aligned
+ Aries might need this too. The Saturn errata are not pretty reading but
+ thankfully its an old 486 chipset.
+ */
+
+ if (pci_find_device(PCI_VENDOR_ID_INTEL, 0x0483, NULL))
+ csr0 = 0x00A04800;
+ /* The dreaded SiS496 486 chipset. Same workaround as above. */
+ if (pci_find_device(PCI_VENDOR_ID_SI, 0x0496, NULL))
+ csr0 = 0x00A04800;
+
+ /*
+ * And back to business
+ */
+
ioaddr = pci_resource_start (pdev, 0);
irq = pdev->irq;