summaryrefslogtreecommitdiffstats
path: root/drivers/net/hamradio
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2001-01-11 04:02:40 +0000
committerRalf Baechle <ralf@linux-mips.org>2001-01-11 04:02:40 +0000
commite47f00743fc4776491344f2c618cc8dc2c23bcbc (patch)
tree13e03a113a82a184c51c19c209867cfd3a59b3b9 /drivers/net/hamradio
parentb2ad5f821b1381492d792ca10b1eb7a107b48f14 (diff)
Merge with Linux 2.4.0.
Diffstat (limited to 'drivers/net/hamradio')
-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
7 files changed, 321 insertions, 3989 deletions
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>");