From: Paul Fulghum <paulkf@microgate.com>
To: linux-kernel <linux-kernel@vger.kernel.org>
Cc: Andrew Morton <akpm@osdl.org>
Subject: [PATCH] 2.6.8 synclink_cs.c replace syncppp with genhdlc
Date: 16 Aug 2004 10:11:00 -0500 [thread overview]
Message-ID: <1092669058.2012.11.camel@deimos.microgate.com> (raw)
Replace syncppp interface with generic HDLC interface.
Generic HDLC provides superset of syncppp function.
Signed-off-by: Paul Fulghum <paulkf@microgate.com>
--
Paul Fulghum
paulkf@microgate.com
--- linux-2.6.8/drivers/char/pcmcia/synclink_cs.c 2004-08-11 15:28:14.000000000 -0500
+++ linux-2.6.8-mg1/drivers/char/pcmcia/synclink_cs.c 2004-08-12 09:04:45.000000000 -0500
@@ -1,7 +1,7 @@
/*
* linux/drivers/char/pcmcia/synclink_cs.c
*
- * $Id: synclink_cs.c,v 4.22 2004/06/01 20:27:46 paulkf Exp $
+ * $Id: synclink_cs.c,v 4.26 2004/08/11 19:30:02 paulkf Exp $
*
* Device driver for Microgate SyncLink PC Card
* multiprotocol serial adapter.
@@ -68,6 +68,7 @@
#include <asm/types.h>
#include <linux/termios.h>
#include <linux/workqueue.h>
+#include <linux/hdlc.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
@@ -76,12 +77,8 @@
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
-#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE
-#define CONFIG_SYNCLINK_SYNCPPP 1
-#endif
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#include <net/syncppp.h>
+#ifdef CONFIG_HDLC_MODULE
+#define CONFIG_HDLC 1
#endif
#define GET_USER(error,value,addr) error = get_user(value,addr)
@@ -239,12 +236,11 @@
int netcount;
int dosyncppp;
spinlock_t netlock;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
- struct ppp_device pppdev;
- char netname[10];
+
+#ifdef CONFIG_HDLC
struct net_device *netdev;
- struct net_device_stats netstats;
#endif
+
} MGSLPC_INFO;
#define MGSLPC_MAGIC 0x5402
@@ -257,12 +253,12 @@
#define CHA 0x00 /* channel A offset */
#define CHB 0x40 /* channel B offset */
-
+
/*
* FIXME: PPC has PVR defined in asm/reg.h. For now we just undef it.
*/
#undef PVR
-
+
#define RXFIFO 0
#define TXFIFO 0
#define STAR 0x20
@@ -398,18 +394,12 @@
static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg);
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-/* SPPP/HDLC stuff */
-static void mgslpc_sppp_init(MGSLPC_INFO *info);
-static void mgslpc_sppp_delete(MGSLPC_INFO *info);
-static int mgslpc_sppp_open(struct net_device *d);
-static int mgslpc_sppp_close(struct net_device *d);
-static void mgslpc_sppp_tx_timeout(struct net_device *d);
-static int mgslpc_sppp_tx(struct sk_buff *skb, struct net_device *d);
-static void mgslpc_sppp_rx_done(MGSLPC_INFO *info, char *buf, int size);
-static void mgslpc_sppp_tx_done(MGSLPC_INFO *info);
-static int mgslpc_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-struct net_device_stats *mgslpc_net_stats(struct net_device *dev);
+#ifdef CONFIG_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(MGSLPC_INFO *info);
+static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size);
+static int hdlcdev_init(MGSLPC_INFO *info);
+static void hdlcdev_exit(MGSLPC_INFO *info);
#endif
static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit);
@@ -494,7 +484,7 @@
MODULE_LICENSE("GPL");
static char *driver_name = "SyncLink PC Card driver";
-static char *driver_version = "$Revision: 4.22 $";
+static char *driver_version = "$Revision: 4.26 $";
static struct tty_driver *serial_driver;
@@ -1163,9 +1153,9 @@
info->drop_rts_on_tx_done = 0;
}
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
if (info->netcount)
- mgslpc_sppp_tx_done(info);
+ hdlcdev_tx_done(info);
else
#endif
{
@@ -1271,13 +1261,13 @@
info->icount.dcd++;
if (info->serial_signals & SerialSignal_DCD) {
info->input_signal_events.dcd_up++;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
- if (info->netcount)
- sppp_reopen(info->netdev);
-#endif
}
else
info->input_signal_events.dcd_down++;
+#ifdef CONFIG_HDLC
+ if (info->netcount)
+ hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, info->netdev);
+#endif
wake_up_interruptible(&info->status_event_wait_q);
wake_up_interruptible(&info->event_wait_q);
@@ -2876,7 +2866,7 @@
cleanup:
if (retval) {
if (tty->count == 1)
- info->tty = NULL;/* tty layer will release tty struct */
+ info->tty = NULL; /* tty layer will release tty struct */
if(info->count)
info->count--;
}
@@ -2931,7 +2921,7 @@
if (info->icount.rxover)
ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover);
if (info->icount.rxcrc)
- ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxcrc);
+ ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc);
} else {
ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d",
info->icount.tx, info->icount.rx);
@@ -3070,12 +3060,8 @@
printk( "SyncLink PC Card %s:IO=%04X IRQ=%d\n",
info->device_name, info->io_base, info->irq_level);
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#ifdef MODULE
- if (info->dosyncppp)
-#endif
- mgslpc_sppp_init(info);
+#ifdef CONFIG_HDLC
+ hdlcdev_init(info);
#endif
}
@@ -3090,9 +3076,8 @@
last->next_device = info->next_device;
else
mgslpc_device_list = info->next_device;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
- if (info->dosyncppp)
- mgslpc_sppp_delete(info);
+#ifdef CONFIG_HDLC
+ hdlcdev_exit(info);
#endif
release_resources(info);
kfree(info);
@@ -4021,9 +4006,12 @@
return_frame = 1;
}
framesize = 0;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
- info->netstats.rx_errors++;
- info->netstats.rx_frame_errors++;
+#ifdef CONFIG_HDLC
+ {
+ struct net_device_stats *stats = hdlc_stats(info->netdev);
+ stats->rx_errors++;
+ stats->rx_frame_errors++;
+ }
#endif
} else
return_frame = 1;
@@ -4052,11 +4040,9 @@
++framesize;
}
-#ifdef CONFIG_SYNCLINK_SYNCPPP
- if (info->netcount) {
- /* pass frame to syncppp device */
- mgslpc_sppp_rx_done(info, buf->data, framesize);
- }
+#ifdef CONFIG_HDLC
+ if (info->netcount)
+ hdlcdev_rx(info, buf->data, framesize);
else
#endif
{
@@ -4215,88 +4201,134 @@
spin_unlock_irqrestore(&info->lock,flags);
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
if (info->netcount)
- mgslpc_sppp_tx_done(info);
+ hdlcdev_tx_done(info);
else
#endif
bh_transmit(info);
}
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-/* syncppp net device routines
+#ifdef CONFIG_HDLC
+
+/**
+ * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
+ * set encoding and frame check sequence (FCS) options
+ *
+ * dev pointer to network device structure
+ * encoding serial encoding setting
+ * parity FCS setting
+ *
+ * returns 0 if success, otherwise error code
*/
-
-static void mgslpc_setup(struct net_device *dev)
+static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+ unsigned short parity)
{
- dev->open = mgslpc_sppp_open;
- dev->stop = mgslpc_sppp_close;
- dev->hard_start_xmit = mgslpc_sppp_tx;
- dev->do_ioctl = mgslpc_sppp_ioctl;
- dev->get_stats = mgslpc_net_stats;
- dev->tx_timeout = mgslpc_sppp_tx_timeout;
- dev->watchdog_timeo = 10*HZ;
-}
+ MGSLPC_INFO *info = dev_to_port(dev);
+ unsigned char new_encoding;
+ unsigned short new_crctype;
-void mgslpc_sppp_init(MGSLPC_INFO *info)
-{
- struct net_device *d;
+ /* return error if TTY interface open */
+ if (info->count)
+ return -EBUSY;
- sprintf(info->netname,"mgslp%d",info->line);
-
- d = alloc_netdev(0, info->netname, mgslpc_setup);
- if (!d) {
- printk(KERN_WARNING "%s: alloc_netdev failed.\n",
- info->netname);
- return;
+ switch (encoding)
+ {
+ case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break;
+ case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
+ case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
+ case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
+ case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
+ default: return -EINVAL;
}
- info->if_ptr = &info->pppdev;
- info->netdev = info->pppdev.dev = d;
-
- d->base_addr = info->io_base;
- d->irq = info->irq_level;
- d->priv = info;
-
- sppp_attach(&info->pppdev);
- mgslpc_setup(d);
-
- if (register_netdev(d)) {
- printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);
- sppp_detach(info->netdev);
- info->netdev = NULL;
- info->pppdev.dev = NULL;
- free_netdev(d);
- return;
+ switch (parity)
+ {
+ case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break;
+ case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
+ case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
+ default: return -EINVAL;
}
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgslpc_sppp_init()\n");
+ info->params.encoding = new_encoding;
+ info->params.crc_type = new_crctype;;
+
+ /* if network interface up, reprogram hardware */
+ if (info->netcount)
+ mgslpc_program_hw(info);
+
+ return 0;
}
-void mgslpc_sppp_delete(MGSLPC_INFO *info)
+/**
+ * called by generic HDLC layer to send frame
+ *
+ * skb socket buffer containing HDLC frame
+ * dev pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
{
+ MGSLPC_INFO *info = dev_to_port(dev);
+ struct net_device_stats *stats = hdlc_stats(dev);
+ unsigned long flags;
+
if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgslpc_sppp_delete(%s)\n",info->netname);
- unregister_netdev(info->netdev);
- sppp_detach(info->netdev);
- free_netdev(info->netdev);
- info->netdev = NULL;
- info->pppdev.dev = NULL;
+ printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
+
+ /* stop sending until this frame completes */
+ netif_stop_queue(dev);
+
+ /* copy data to device buffers */
+ memcpy(info->tx_buf, skb->data, skb->len);
+ info->tx_get = 0;
+ info->tx_put = info->tx_count = skb->len;
+
+ /* update network statistics */
+ stats->tx_packets++;
+ stats->tx_bytes += skb->len;
+
+ /* done with socket buffer, so free it */
+ dev_kfree_skb(skb);
+
+ /* save start time for transmit timeout detection */
+ dev->trans_start = jiffies;
+
+ /* start hardware transmitter if necessary */
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_active)
+ tx_start(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ return 0;
}
-int mgslpc_sppp_open(struct net_device *d)
+/**
+ * called by network layer when interface enabled
+ * claim resources and initialize hardware
+ *
+ * dev pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_open(struct net_device *dev)
{
- MGSLPC_INFO *info = d->priv;
- int err;
+ MGSLPC_INFO *info = dev_to_port(dev);
+ int rc;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgslpc_sppp_open(%s)\n",info->netname);
+ printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
+
+ /* generic HDLC layer open processing */
+ if ((rc = hdlc_open(dev)))
+ return rc;
+ /* arbitrate between network and tty opens */
spin_lock_irqsave(&info->netlock, flags);
if (info->count != 0 || info->netcount != 0) {
- printk(KERN_WARNING "%s: sppp_open returning busy\n", info->netname);
+ printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
spin_unlock_irqrestore(&info->netlock, flags);
return -EBUSY;
}
@@ -4304,142 +4336,297 @@
spin_unlock_irqrestore(&info->netlock, flags);
/* claim resources and init adapter */
- if ((err = startup(info)) != 0)
- goto open_fail;
-
- /* allow syncppp module to do open processing */
- if ((err = sppp_open(d)) != 0) {
- shutdown(info);
- goto open_fail;
+ if ((rc = startup(info)) != 0) {
+ spin_lock_irqsave(&info->netlock, flags);
+ info->netcount=0;
+ spin_unlock_irqrestore(&info->netlock, flags);
+ return rc;
}
+ /* assert DTR and RTS, apply hardware settings */
info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
mgslpc_program_hw(info);
- d->trans_start = jiffies;
- netif_start_queue(d);
- return 0;
+ /* enable network layer transmit */
+ dev->trans_start = jiffies;
+ netif_start_queue(dev);
-open_fail:
- spin_lock_irqsave(&info->netlock, flags);
- info->netcount=0;
- spin_unlock_irqrestore(&info->netlock, flags);
- return err;
+ /* inform generic HDLC layer of current DCD status */
+ spin_lock_irqsave(&info->lock, flags);
+ get_signals(info);
+ spin_unlock_irqrestore(&info->lock, flags);
+ hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
+
+ return 0;
}
-void mgslpc_sppp_tx_timeout(struct net_device *dev)
+/**
+ * called by network layer when interface is disabled
+ * shutdown hardware and release resources
+ *
+ * dev pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_close(struct net_device *dev)
{
- MGSLPC_INFO *info = dev->priv;
+ MGSLPC_INFO *info = dev_to_port(dev);
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgslpc_sppp_tx_timeout(%s)\n",info->netname);
+ printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
- info->netstats.tx_errors++;
- info->netstats.tx_aborted_errors++;
+ netif_stop_queue(dev);
- spin_lock_irqsave(&info->lock,flags);
- tx_stop(info);
- spin_unlock_irqrestore(&info->lock,flags);
+ /* shutdown adapter and release resources */
+ shutdown(info);
- netif_wake_queue(dev);
+ hdlc_close(dev);
+
+ spin_lock_irqsave(&info->netlock, flags);
+ info->netcount=0;
+ spin_unlock_irqrestore(&info->netlock, flags);
+
+ return 0;
}
-int mgslpc_sppp_tx(struct sk_buff *skb, struct net_device *dev)
+/**
+ * called by network layer to process IOCTL call to network device
+ *
+ * dev pointer to network device structure
+ * ifr pointer to network interface request structure
+ * cmd IOCTL command code
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- MGSLPC_INFO *info = dev->priv;
- unsigned long flags;
+ const size_t size = sizeof(sync_serial_settings);
+ sync_serial_settings new_line;
+ sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+ MGSLPC_INFO *info = dev_to_port(dev);
+ unsigned int flags;
if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgslpc_sppp_tx(%s)\n",info->netname);
+ printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
- netif_stop_queue(dev);
+ /* return error if TTY interface open */
+ if (info->count)
+ return -EBUSY;
- info->tx_count = skb->len;
+ if (cmd != SIOCWANDEV)
+ return hdlc_ioctl(dev, ifr, cmd);
- memcpy(info->tx_buf, skb->data, skb->len);
- info->tx_get = 0;
- info->tx_put = info->tx_count = skb->len;
+ switch(ifr->ifr_settings.type) {
+ case IF_GET_IFACE: /* return current sync_serial_settings */
- info->netstats.tx_packets++;
- info->netstats.tx_bytes += skb->len;
- dev_kfree_skb(skb);
+ ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+ if (ifr->ifr_settings.size < size) {
+ ifr->ifr_settings.size = size; /* data size wanted */
+ return -ENOBUFS;
+ }
- dev->trans_start = jiffies;
+ flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+ HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |
+ HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+ HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);
+
+ switch (flags){
+ case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
+ case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break;
+ case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break;
+ case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
+ default: new_line.clock_type = CLOCK_DEFAULT;
+ }
- spin_lock_irqsave(&info->lock,flags);
- if (!info->tx_active)
- tx_start(info);
- spin_unlock_irqrestore(&info->lock,flags);
+ new_line.clock_rate = info->params.clock_speed;
+ new_line.loopback = info->params.loopback ? 1:0;
- return 0;
+ if (copy_to_user(line, &new_line, size))
+ return -EFAULT;
+ return 0;
+
+ case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
+
+ if(!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (copy_from_user(&new_line, line, size))
+ return -EFAULT;
+
+ switch (new_line.clock_type)
+ {
+ case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
+ case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
+ case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break;
+ case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break;
+ case CLOCK_DEFAULT: flags = info->params.flags &
+ (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+ HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |
+ HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+ HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break;
+ default: return -EINVAL;
+ }
+
+ if (new_line.loopback != 0 && new_line.loopback != 1)
+ return -EINVAL;
+
+ info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+ HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |
+ HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+ HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);
+ info->params.flags |= flags;
+
+ info->params.loopback = new_line.loopback;
+
+ if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
+ info->params.clock_speed = new_line.clock_rate;
+ else
+ info->params.clock_speed = 0;
+
+ /* if network interface up, reprogram hardware */
+ if (info->netcount)
+ mgslpc_program_hw(info);
+ return 0;
+
+ default:
+ return hdlc_ioctl(dev, ifr, cmd);
+ }
}
-int mgslpc_sppp_close(struct net_device *d)
+/**
+ * called by network layer when transmit timeout is detected
+ *
+ * dev pointer to network device structure
+ */
+static void hdlcdev_tx_timeout(struct net_device *dev)
{
- MGSLPC_INFO *info = d->priv;
+ MGSLPC_INFO *info = dev_to_port(dev);
+ struct net_device_stats *stats = hdlc_stats(dev);
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgslpc_sppp_close(%s)\n",info->netname);
+ printk("hdlcdev_tx_timeout(%s)\n",dev->name);
- /* shutdown adapter and release resources */
- shutdown(info);
+ stats->tx_errors++;
+ stats->tx_aborted_errors++;
+
+ spin_lock_irqsave(&info->lock,flags);
+ tx_stop(info);
+ spin_unlock_irqrestore(&info->lock,flags);
- /* allow syncppp to do close processing */
- sppp_close(d);
- netif_stop_queue(d);
+ netif_wake_queue(dev);
+}
- spin_lock_irqsave(&info->netlock, flags);
- info->netcount=0;
- spin_unlock_irqrestore(&info->netlock, flags);
- return 0;
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info pointer to device instance information
+ */
+static void hdlcdev_tx_done(MGSLPC_INFO *info)
+{
+ if (netif_queue_stopped(info->netdev))
+ netif_wake_queue(info->netdev);
}
-void mgslpc_sppp_rx_done(MGSLPC_INFO *info, char *buf, int size)
+/**
+ * called by device driver when frame received
+ * pass frame to network layer
+ *
+ * info pointer to device instance information
+ * buf pointer to buffer contianing frame data
+ * size count of data bytes in buf
+ */
+static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size)
{
struct sk_buff *skb = dev_alloc_skb(size);
+ struct net_device *dev = info->netdev;
+ struct net_device_stats *stats = hdlc_stats(dev);
+
if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgslpc_sppp_rx_done(%s)\n",info->netname);
+ printk("hdlcdev_rx(%s)\n",dev->name);
+
if (skb == NULL) {
- printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
- info->netname);
- info->netstats.rx_dropped++;
+ printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name);
+ stats->rx_dropped++;
return;
}
memcpy(skb_put(skb, size),buf,size);
- skb->protocol = htons(ETH_P_WAN_PPP);
- skb->dev = info->netdev;
- skb->mac.raw = skb->data;
- info->netstats.rx_packets++;
- info->netstats.rx_bytes += size;
+ skb->dev = info->netdev;
+ skb->mac.raw = skb->data;
+ skb->protocol = hdlc_type_trans(skb, skb->dev);
+
+ stats->rx_packets++;
+ stats->rx_bytes += size;
+
netif_rx(skb);
- info->netdev->trans_start = jiffies;
-}
-void mgslpc_sppp_tx_done(MGSLPC_INFO *info)
-{
- if (netif_queue_stopped(info->netdev))
- netif_wake_queue(info->netdev);
+ info->netdev->last_rx = jiffies;
}
-struct net_device_stats *mgslpc_net_stats(struct net_device *dev)
+/**
+ * called by device driver when adding device instance
+ * do generic HDLC initialization
+ *
+ * info pointer to device instance information
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_init(MGSLPC_INFO *info)
{
- MGSLPC_INFO *info = dev->priv;
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgslpc_net_stats(%s)\n",info->netname);
- return &info->netstats;
+ int rc;
+ struct net_device *dev;
+ hdlc_device *hdlc;
+
+ /* allocate and initialize network and HDLC layer objects */
+
+ if (!(dev = alloc_hdlcdev(info))) {
+ printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
+ return -ENOMEM;
+ }
+
+ /* for network layer reporting purposes only */
+ dev->base_addr = info->io_base;
+ dev->irq = info->irq_level;
+
+ /* network layer callbacks and settings */
+ dev->do_ioctl = hdlcdev_ioctl;
+ dev->open = hdlcdev_open;
+ dev->stop = hdlcdev_close;
+ dev->tx_timeout = hdlcdev_tx_timeout;
+ dev->watchdog_timeo = 10*HZ;
+ dev->tx_queue_len = 50;
+
+ /* generic HDLC layer callbacks and settings */
+ hdlc = dev_to_hdlc(dev);
+ hdlc->attach = hdlcdev_attach;
+ hdlc->xmit = hdlcdev_xmit;
+
+ /* register objects with HDLC layer */
+ if ((rc = register_hdlc_device(dev))) {
+ printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
+ free_netdev(dev);
+ return rc;
+ }
+
+ info->netdev = dev;
+ return 0;
}
-int mgslpc_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+/**
+ * called by device driver when removing device instance
+ * do generic HDLC cleanup
+ *
+ * info pointer to device instance information
+ */
+static void hdlcdev_exit(MGSLPC_INFO *info)
{
- MGSLPC_INFO *info = dev->priv;
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
- info->netname, cmd );
- return sppp_do_ioctl(dev, ifr, cmd);
+ unregister_hdlc_device(info->netdev);
+ free_netdev(info->netdev);
+ info->netdev = NULL;
}
-#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */
+#endif /* CONFIG_HDLC */
+
next reply other threads:[~2004-08-16 15:16 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-08-16 15:11 Paul Fulghum [this message]
2004-08-16 15:21 ` [PATCH] 2.6.8 synclink_cs.c replace syncppp with genhdlc Christoph Hellwig
2004-08-16 15:58 ` Paul Fulghum
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1092669058.2012.11.camel@deimos.microgate.com \
--to=paulkf@microgate.com \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.