vserver 1.9.3
[linux-2.6.git] / drivers / char / synclinkmp.c
index 1361ea0..5648ed3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: synclinkmp.c,v 4.22 2004/06/03 14:50:10 paulkf Exp $
+ * $Id: synclinkmp.c,v 4.29 2004/08/27 20:06:41 paulkf Exp $
  *
  * Device driver for Microgate SyncLink Multiport
  * high speed multiprotocol serial adapter.
 #include <asm/types.h>
 #include <linux/termios.h>
 #include <linux/workqueue.h>
+#include <linux/hdlc.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)
@@ -284,12 +281,11 @@ typedef struct _synclinkmp_info {
        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
+
 } SLMP_INFO;
 
 #define MGSL_MAGIC 0x5401
@@ -361,12 +357,7 @@ typedef struct _synclinkmp_info {
 #define TMCS   0x64
 #define TEPR   0x65
 
-/*
- *  FIXME: DAR here clashed with asm-ppc/reg.h and asm-sh/.../dma.h
- */
-#undef DAR
 /* DMA Controller Register macros */
-#define DAR    0x80
 #define DARL   0x80
 #define DARH   0x81
 #define DARB   0x82
@@ -462,8 +453,6 @@ typedef struct _synclinkmp_info {
 #define CRCE   BIT2
 
 
-#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
-
 /*
  * Global linked list of SyncLink devices
  */
@@ -498,7 +487,7 @@ MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICES) "i");
 MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i");
 
 static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 4.22 $";
+static char *driver_version = "$Revision: 4.29 $";
 
 static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
 static void synclinkmp_remove_one(struct pci_dev *dev);
@@ -524,10 +513,6 @@ static struct tty_driver *serial_driver;
 /* number of characters left in xmit buffer before we ask for more */
 #define WAKEUP_CHARS 256
 
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
 
 /* tty callbacks */
 
@@ -553,20 +538,12 @@ static void throttle(struct tty_struct * tty);
 static void unthrottle(struct tty_struct * tty);
 static void set_break(struct tty_struct *tty, int break_state);
 
-/* sppp support and callbacks */
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-static void sppp_init(SLMP_INFO *info);
-static void sppp_delete(SLMP_INFO *info);
-static void sppp_rx_done(SLMP_INFO *info, char *buf, int size);
-static void sppp_tx_done(SLMP_INFO *info);
-
-static int  sppp_cb_open(struct net_device *d);
-static int  sppp_cb_close(struct net_device *d);
-static int  sppp_cb_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-static int  sppp_cb_tx(struct sk_buff *skb, struct net_device *dev);
-static void sppp_cb_tx_timeout(struct net_device *dev);
-static struct net_device_stats *sppp_cb_net_stats(struct net_device *dev);
+#ifdef CONFIG_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(SLMP_INFO *info);
+static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size);
+static int  hdlcdev_init(SLMP_INFO *info);
+static void hdlcdev_exit(SLMP_INFO *info);
 #endif
 
 /* ioctl handlers */
@@ -668,7 +645,7 @@ static unsigned char tx_active_fifo_level = 16;     // tx request FIFO activation le
 static unsigned char tx_negate_fifo_level = 32;        // tx request FIFO negation level in bytes
 
 static u32 misc_ctrl_value = 0x007e4040;
-static u32 lcr1_brdr_value = 0x0080002d;
+static u32 lcr1_brdr_value = 0x00800029;
 
 static u32 read_ahead_count = 8;
 
@@ -722,6 +699,29 @@ static inline int sanity_check(SLMP_INFO *info,
        return 0;
 }
 
+/**
+ * line discipline callback wrappers
+ *
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+ * ldisc_receive_buf  - pass receive data to line discipline
+ */
+
+static void ldisc_receive_buf(struct tty_struct *tty,
+                             const __u8 *data, char *flags, int count)
+{
+       struct tty_ldisc *ld;
+       if (!tty)
+               return;
+       ld = tty_ldisc_ref(tty);
+       if (ld) {
+               if (ld->receive_buf)
+                       ld->receive_buf(tty, data, flags, count);
+               tty_ldisc_deref(ld);
+       }
+}
+
 /* tty callbacks */
 
 /* Called when a port is opened.  Init and enable port.
@@ -800,7 +800,7 @@ static int open(struct tty_struct *tty, struct file *filp)
 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--;
        }
@@ -869,8 +869,7 @@ static void close(struct tty_struct *tty, struct file *filp)
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
 
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+       tty_ldisc_flush(tty);
 
        shutdown(info);
 
@@ -1017,8 +1016,8 @@ static int write(struct tty_struct *tty, int from_user,
        }
 
        for (;;) {
-               c = MIN(count,
-                       MIN(info->max_frame_size - info->tx_count - 1,
+               c = min_t(int, count,
+                       min(info->max_frame_size - info->tx_count - 1,
                            info->max_frame_size - info->tx_put));
                if (c <= 0)
                        break;
@@ -1161,7 +1160,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
                char_time = 1;
 
        if (timeout)
-               char_time = MIN(char_time, timeout);
+               char_time = min_t(unsigned long, char_time, timeout);
 
        if ( info->params.mode == MGSL_MODE_HDLC ) {
                while (info->tx_active) {
@@ -1275,9 +1274,7 @@ static void flush_buffer(struct tty_struct *tty)
        spin_unlock_irqrestore(&info->lock,flags);
 
        wake_up_interruptible(&tty->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
+       tty_wakeup(tty);
 }
 
 /* throttle (stop) transmitter
@@ -1627,79 +1624,125 @@ static void set_break(struct tty_struct *tty, int break_state)
        spin_unlock_irqrestore(&info->lock,flags);
 }
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
 
-/* syncppp support and callbacks */
-
-static void cb_setup(struct net_device *dev)
-{
-       dev->open = sppp_cb_open;
-       dev->stop = sppp_cb_close;
-       dev->hard_start_xmit = sppp_cb_tx;
-       dev->do_ioctl = sppp_cb_ioctl;
-       dev->get_stats = sppp_cb_net_stats;
-       dev->tx_timeout = sppp_cb_tx_timeout;
-       dev->watchdog_timeo = 10*HZ;
-}
-
-static void sppp_init(SLMP_INFO *info)
+/**
+ * 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 int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+                         unsigned short parity)
 {
-       struct net_device *d;
+       SLMP_INFO *info = dev_to_port(dev);
+       unsigned char  new_encoding;
+       unsigned short new_crctype;
 
-       sprintf(info->netname,"mgslm%dp%d",info->adapter_num,info->port_num);
+       /* return error if TTY interface open */
+       if (info->count)
+               return -EBUSY;
 
-       d = alloc_netdev(0, info->netname, cb_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->irq = info->irq_level;
-       d->priv = info;
+       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;
+       }
 
-       sppp_attach(&info->pppdev);
-       cb_setup(d);
+       info->params.encoding = new_encoding;
+       info->params.crc_type = new_crctype;;
 
-       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;
-       }
+       /* if network interface up, reprogram hardware */
+       if (info->netcount)
+               program_hw(info);
 
-       if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("sppp_init(%s)\n",info->netname);
+       return 0;
 }
 
-static void sppp_delete(SLMP_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)
 {
+       SLMP_INFO *info = dev_to_port(dev);
+       struct net_device_stats *stats = hdlc_stats(dev);
+       unsigned long flags;
+
        if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("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 */
+       info->tx_count = skb->len;
+       tx_load_dma_buffer(info, skb->data, 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;
 }
 
-static int sppp_cb_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)
 {
-       SLMP_INFO *info = d->priv;
-       int err;
+       SLMP_INFO *info = dev_to_port(dev);
+       int rc;
        unsigned long flags;
 
        if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("sppp_cb_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_cb_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;
        }
@@ -1707,141 +1750,300 @@ static int sppp_cb_open(struct net_device *d)
        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;
        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;
 }
 
-static void sppp_cb_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)
 {
-       SLMP_INFO *info = dev->priv;
+       SLMP_INFO *info = dev_to_port(dev);
        unsigned long flags;
 
        if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("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;
 }
 
-static int sppp_cb_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)
 {
-       SLMP_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;
+       SLMP_INFO *info = dev_to_port(dev);
+       unsigned int flags;
 
        if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("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;
-       tx_load_dma_buffer(info, skb->data, skb->len);
-       info->netstats.tx_packets++;
-       info->netstats.tx_bytes += skb->len;
-       dev_kfree_skb(skb);
+       if (cmd != SIOCWANDEV)
+               return hdlc_ioctl(dev, ifr, cmd);
 
-       dev->trans_start = jiffies;
+       switch(ifr->ifr_settings.type) {
+       case IF_GET_IFACE: /* return current sync_serial_settings */
 
-       spin_lock_irqsave(&info->lock,flags);
-       if (!info->tx_active)
-               tx_start(info);
-       spin_unlock_irqrestore(&info->lock,flags);
+               ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+               if (ifr->ifr_settings.size < size) {
+                       ifr->ifr_settings.size = size; /* data size wanted */
+                       return -ENOBUFS;
+               }
 
-       return 0;
+               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;
+               }
+
+               new_line.clock_rate = info->params.clock_speed;
+               new_line.loopback   = info->params.loopback ? 1: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)
+                       program_hw(info);
+               return 0;
+
+       default:
+               return hdlc_ioctl(dev, ifr, cmd);
+       }
 }
 
-static int sppp_cb_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)
 {
-       SLMP_INFO *info = d->priv;
+       SLMP_INFO *info = dev_to_port(dev);
+       struct net_device_stats *stats = hdlc_stats(dev);
        unsigned long flags;
 
        if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("sppp_cb_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++;
 
-       /* allow syncppp to do close processing */
-       sppp_close(d);
-       netif_stop_queue(d);
+       spin_lock_irqsave(&info->lock,flags);
+       tx_stop(info);
+       spin_unlock_irqrestore(&info->lock,flags);
 
-       spin_lock_irqsave(&info->netlock, flags);
-       info->netcount=0;
-       spin_unlock_irqrestore(&info->netlock, flags);
-       return 0;
+       netif_wake_queue(dev);
+}
+
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_tx_done(SLMP_INFO *info)
+{
+       if (netif_queue_stopped(info->netdev))
+               netif_wake_queue(info->netdev);
 }
 
-static void sppp_rx_done(SLMP_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(SLMP_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("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;
-}
 
-static void sppp_tx_done(SLMP_INFO *info)
-{
-       if (netif_queue_stopped(info->netdev))
-           netif_wake_queue(info->netdev);
+       info->netdev->last_rx = jiffies;
 }
 
-static struct net_device_stats *sppp_cb_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(SLMP_INFO *info)
 {
-       SLMP_INFO *info = dev->priv;
-       if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("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->mem_start = info->phys_sca_base;
+       dev->mem_end   = info->phys_sca_base + SCA_BASE_SIZE - 1;
+       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;
 }
 
-static int sppp_cb_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(SLMP_INFO *info)
 {
-       SLMP_INFO *info = dev->priv;
-       if (debug_level >= DEBUG_LEVEL_INFO)
-               printk("%s(%d):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 */
 
 
 /* Return next bottom half action to perform.
@@ -1941,13 +2143,7 @@ void bh_transmit(SLMP_INFO *info)
                        __FILE__,__LINE__,info->device_name);
 
        if (tty) {
-               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                   tty->ldisc.write_wakeup) {
-                       if ( debug_level >= DEBUG_LEVEL_BH )
-                               printk( "%s(%d):%s calling ldisc.write_wakeup\n",
-                                       __FILE__,__LINE__,info->device_name);
-                       (tty->ldisc.write_wakeup)(tty);
-               }
+               tty_wakeup(tty);
                wake_up_interruptible(&tty->write_wait);
        }
 }
@@ -1994,16 +2190,15 @@ void isr_rxint(SLMP_INFO * info)
 {
        struct tty_struct *tty = info->tty;
        struct  mgsl_icount *icount = &info->icount;
-       unsigned char status = read_reg(info, SR1);
-       unsigned char status2 = read_reg(info, SR2);
+       unsigned char status = read_reg(info, SR1) & info->ie1_value & (FLGD + IDLD + CDCD + BRKD);
+       unsigned char status2 = read_reg(info, SR2) & info->ie2_value & OVRN;
 
        /* clear status bits */
-       if ( status & (FLGD + IDLD + CDCD + BRKD) )
-               write_reg(info, SR1, 
-                               (unsigned char)(status & (FLGD + IDLD + CDCD + BRKD)));
+       if (status)
+               write_reg(info, SR1, status);
 
-       if ( status2 & OVRN )
-               write_reg(info, SR2, (unsigned char)(status2 & OVRN));
+       if (status2)
+               write_reg(info, SR2, status2);
        
        if ( debug_level >= DEBUG_LEVEL_ISR )
                printk("%s(%d):%s isr_rxint status=%02X %02x\n",
@@ -2140,15 +2335,22 @@ void isr_txeom(SLMP_INFO * info, unsigned char status)
                printk("%s(%d):%s isr_txeom status=%02x\n",
                        __FILE__,__LINE__,info->device_name,status);
 
-       /* disable and clear MSCI interrupts */
-       info->ie1_value &= ~(IDLE + UDRN);
-       write_reg(info, IE1, info->ie1_value);
-       write_reg(info, SR1, (unsigned char)(UDRN + IDLE));
-
        write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */
        write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */
        write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */
 
+       if (status & UDRN) {
+               write_reg(info, CMD, TXRESET);
+               write_reg(info, CMD, TXENABLE);
+       } else
+               write_reg(info, CMD, TXBUFCLR);
+
+       /* disable and clear tx interrupts */
+       info->ie0_value &= ~TXRDYE;
+       info->ie1_value &= ~(IDLE + UDRN);
+       write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
+       write_reg(info, SR1, (unsigned char)(UDRN + IDLE));
+
        if ( info->tx_active ) {
                if (info->params.mode != MGSL_MODE_ASYNC) {
                        if (status & UDRN)
@@ -2168,9 +2370,9 @@ void isr_txeom(SLMP_INFO * info, unsigned char status)
                        set_signals(info);
                }
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
                if (info->netcount)
-                       sppp_tx_done(info);
+                       hdlcdev_tx_done(info);
                else
 #endif
                {
@@ -2189,10 +2391,10 @@ void isr_txeom(SLMP_INFO * info, unsigned char status)
  */
 void isr_txint(SLMP_INFO * info)
 {
-       unsigned char status = read_reg(info, SR1);
+       unsigned char status = read_reg(info, SR1) & info->ie1_value & (UDRN + IDLE + CCTS);
 
        /* clear status bits */
-       write_reg(info, SR1, (unsigned char)(status & (UDRN + IDLE + CCTS)));
+       write_reg(info, SR1, status);
 
        if ( debug_level >= DEBUG_LEVEL_ISR )
                printk("%s(%d):%s isr_txint status=%02x\n",
@@ -2221,6 +2423,14 @@ void isr_txrdy(SLMP_INFO * info)
                printk("%s(%d):%s isr_txrdy() tx_count=%d\n",
                        __FILE__,__LINE__,info->device_name,info->tx_count);
 
+       if (info->params.mode != MGSL_MODE_ASYNC) {
+               /* disable TXRDY IRQ, enable IDLE IRQ */
+               info->ie0_value &= ~TXRDYE;
+               info->ie1_value |= IDLE;
+               write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
+               return;
+       }
+
        if (info->tty && (info->tty->stopped || info->tty->hw_stopped)) {
                tx_stop(info);
                return;
@@ -2275,13 +2485,6 @@ void isr_rxdmaerror(SLMP_INFO * info)
 
 void isr_txdmaok(SLMP_INFO * info)
 {
-       /* BIT7 = EOT (end of transfer, used for async mode)
-        * BIT6 = EOM (end of message/frame, used for sync mode)
-        *
-        * We don't look at DMA status because only EOT is enabled
-        * and we always clear and disable all tx DMA IRQs.
-        */
-//     unsigned char dma_status = read_reg(info,TXDMA + DSR) & 0xc0;
        unsigned char status_reg1 = read_reg(info, SR1);
 
        write_reg(info, TXDMA + DIR, 0x00);     /* disable Tx DMA IRQs */
@@ -2292,19 +2495,10 @@ void isr_txdmaok(SLMP_INFO * info)
                printk("%s(%d):%s isr_txdmaok(), status=%02x\n",
                        __FILE__,__LINE__,info->device_name,status_reg1);
 
-       /* If transmitter already idle, do end of frame processing,
-        * otherwise enable interrupt for tx IDLE.
-        */
-       if (status_reg1 & IDLE)
-               isr_txeom(info, IDLE);
-       else {
-               /* disable and clear underrun IRQ, enable IDLE interrupt */
-               info->ie1_value |= IDLE;
-               info->ie1_value &= ~UDRN;
-               write_reg(info, IE1, info->ie1_value);
-
-               write_reg(info, SR1, UDRN);
-       }
+       /* program TXRDY as FIFO empty flag, enable TXRDY IRQ */
+       write_reg16(info, TRC0, 0);
+       info->ie0_value |= TXRDYE;
+       write_reg(info, IE0, info->ie0_value);
 }
 
 void isr_txdmaerror(SLMP_INFO * info)
@@ -2358,12 +2552,12 @@ void isr_io_pin( SLMP_INFO *info, u16 status )
                        icount->dcd++;
                        if (status & 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(status & SerialSignal_DCD, info->netdev);
+#endif
                }
                if (status & MISCSTATUS_CTS_LATCHED)
                {
@@ -2577,7 +2771,7 @@ static int startup(SLMP_INFO * info)
 
        change_params(info);
 
-       info->status_timer.expires = jiffies + jiffies_from_ms(10);
+       info->status_timer.expires = jiffies + msecs_to_jiffies(10);
        add_timer(&info->status_timer);
 
        if (info->tty)
@@ -2988,7 +3182,7 @@ static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
                unsigned char oldval = info->ie1_value;
                unsigned char newval = oldval +
                         (mask & MgslEvent_ExitHuntMode ? FLGD:0) +
-                        (mask & MgslEvent_IdleReceived ? IDLE:0);
+                        (mask & MgslEvent_IdleReceived ? IDLD:0);
                if ( oldval != newval ) {
                        info->ie1_value = newval;
                        write_reg(info, IE1, info->ie1_value);
@@ -3055,7 +3249,7 @@ static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
                spin_lock_irqsave(&info->lock,flags);
                if (!waitqueue_active(&info->event_wait_q)) {
                        /* disable enable exit hunt mode/idle rcvd IRQs */
-                       info->ie1_value &= ~(FLGD|IDLE);
+                       info->ie1_value &= ~(FLGD|IDLD);
                        write_reg(info, IE1, info->ie1_value);
                }
                spin_unlock_irqrestore(&info->lock,flags);
@@ -3449,9 +3643,10 @@ void free_tmp_rx_buf(SLMP_INFO *info)
 
 int claim_resources(SLMP_INFO *info)
 {
-       if (request_mem_region(info->phys_memory_base,0x40000,"synclinkmp") == NULL) {
+       if (request_mem_region(info->phys_memory_base,SCA_MEM_SIZE,"synclinkmp") == NULL) {
                printk( "%s(%d):%s mem addr conflict, Addr=%08X\n",
                        __FILE__,__LINE__,info->device_name, info->phys_memory_base);
+               info->init_error = DiagStatus_AddressConflict;
                goto errout;
        }
        else
@@ -3460,22 +3655,25 @@ int claim_resources(SLMP_INFO *info)
        if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclinkmp") == NULL) {
                printk( "%s(%d):%s lcr mem addr conflict, Addr=%08X\n",
                        __FILE__,__LINE__,info->device_name, info->phys_lcr_base);
+               info->init_error = DiagStatus_AddressConflict;
                goto errout;
        }
        else
                info->lcr_mem_requested = 1;
 
-       if (request_mem_region(info->phys_sca_base + info->sca_offset,512,"synclinkmp") == NULL) {
+       if (request_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE,"synclinkmp") == NULL) {
                printk( "%s(%d):%s sca mem addr conflict, Addr=%08X\n",
                        __FILE__,__LINE__,info->device_name, info->phys_sca_base);
+               info->init_error = DiagStatus_AddressConflict;
                goto errout;
        }
        else
                info->sca_base_requested = 1;
 
-       if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,16,"synclinkmp") == NULL) {
+       if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE,"synclinkmp") == NULL) {
                printk( "%s(%d):%s stat/ctrl mem addr conflict, Addr=%08X\n",
                        __FILE__,__LINE__,info->device_name, info->phys_statctrl_base);
+               info->init_error = DiagStatus_AddressConflict;
                goto errout;
        }
        else
@@ -3485,33 +3683,41 @@ int claim_resources(SLMP_INFO *info)
        if (!info->memory_base) {
                printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n",
                        __FILE__,__LINE__,info->device_name, info->phys_memory_base );
+               info->init_error = DiagStatus_CantAssignPciResources;
                goto errout;
        }
 
-       if ( !memory_test(info) ) {
-               printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n",
-                       __FILE__,__LINE__,info->device_name, info->phys_memory_base );
-               goto errout;
-       }
-
-       info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE) + info->lcr_offset;
+       info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE);
        if (!info->lcr_base) {
                printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n",
                        __FILE__,__LINE__,info->device_name, info->phys_lcr_base );
+               info->init_error = DiagStatus_CantAssignPciResources;
                goto errout;
        }
+       info->lcr_base += info->lcr_offset;
 
-       info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE) + info->sca_offset;
+       info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE);
        if (!info->sca_base) {
                printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n",
                        __FILE__,__LINE__,info->device_name, info->phys_sca_base );
+               info->init_error = DiagStatus_CantAssignPciResources;
                goto errout;
        }
+       info->sca_base += info->sca_offset;
 
-       info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE) + info->statctrl_offset;
+       info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE);
        if (!info->statctrl_base) {
                printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n",
                        __FILE__,__LINE__,info->device_name, info->phys_statctrl_base );
+               info->init_error = DiagStatus_CantAssignPciResources;
+               goto errout;
+       }
+       info->statctrl_base += info->statctrl_offset;
+
+       if ( !memory_test(info) ) {
+               printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n",
+                       __FILE__,__LINE__,info->device_name, info->phys_memory_base );
+               info->init_error = DiagStatus_MemoryError;
                goto errout;
        }
 
@@ -3534,7 +3740,7 @@ void release_resources(SLMP_INFO *info)
        }
 
        if ( info->shared_mem_requested ) {
-               release_mem_region(info->phys_memory_base,0x40000);
+               release_mem_region(info->phys_memory_base,SCA_MEM_SIZE);
                info->shared_mem_requested = 0;
        }
        if ( info->lcr_mem_requested ) {
@@ -3542,11 +3748,11 @@ void release_resources(SLMP_INFO *info)
                info->lcr_mem_requested = 0;
        }
        if ( info->sca_base_requested ) {
-               release_mem_region(info->phys_sca_base + info->sca_offset,512);
+               release_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE);
                info->sca_base_requested = 0;
        }
        if ( info->sca_statctrl_requested ) {
-               release_mem_region(info->phys_statctrl_base + info->statctrl_offset,16);
+               release_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE);
                info->sca_statctrl_requested = 0;
        }
 
@@ -3616,9 +3822,8 @@ void add_device(SLMP_INFO *info)
                info->irq_level,
                info->max_frame_size );
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-       if (info->dosyncppp)
-               sppp_init(info);
+#ifdef CONFIG_HDLC
+       hdlcdev_init(info);
 #endif
 }
 
@@ -3788,7 +3993,6 @@ static struct tty_operations ops = {
 
 static void synclinkmp_cleanup(void)
 {
-       unsigned long flags;
        int rc;
        SLMP_INFO *info;
        SLMP_INFO *tmp;
@@ -3802,34 +4006,24 @@ static void synclinkmp_cleanup(void)
                put_tty_driver(serial_driver);
        }
 
+       /* reset devices */
        info = synclinkmp_device_list;
        while(info) {
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-               if (info->dosyncppp)
-                       sppp_delete(info);
-#endif
                reset_port(info);
-               if ( info->port_num == 0 ) {
-                       if ( info->irq_requested ) {
-                               free_irq(info->irq_level, info);
-                               info->irq_requested = 0;
-                       }
-               }
                info = info->next_device;
        }
 
-       /* port 0 of each adapter originally claimed
-        * all resources, release those now
-        */
+       /* release devices */
        info = synclinkmp_device_list;
        while(info) {
+#ifdef CONFIG_HDLC
+               hdlcdev_exit(info);
+#endif
                free_dma_bufs(info);
                free_tmp_rx_buf(info);
                if ( info->port_num == 0 ) {
-                       spin_lock_irqsave(&info->lock,flags);
-                       reset_adapter(info);
-                       write_reg(info, LPR, 1);                /* set low power mode */
-                       spin_unlock_irqrestore(&info->lock,flags);
+                       if (info->sca_base)
+                               write_reg(info, LPR, 1); /* set low power mode */
                        release_resources(info);
                }
                tmp = info;
@@ -4112,6 +4306,9 @@ void tx_start(SLMP_INFO *info)
                                }
                        }
 
+                       write_reg16(info, TRC0,
+                               (unsigned short)(((tx_negate_fifo_level-1)<<8) + tx_active_fifo_level));
+
                        write_reg(info, TXDMA + DSR, 0);                /* disable DMA channel */
                        write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */
        
@@ -4123,17 +4320,16 @@ void tx_start(SLMP_INFO *info)
                        write_reg16(info, TXDMA + EDA,
                                info->tx_buf_list_ex[info->last_tx_buf].phys_entry);
        
-                       /* clear IDLE and UDRN status bit */
-                       info->ie1_value &= ~(IDLE + UDRN);
-                       if (info->params.mode != MGSL_MODE_ASYNC)
-                               info->ie1_value |= UDRN;                /* HDLC, IRQ on underrun */
-                       write_reg(info, IE1, info->ie1_value);  /* enable MSCI interrupts */
+                       /* enable underrun IRQ */
+                       info->ie1_value &= ~IDLE;
+                       info->ie1_value |= UDRN;
+                       write_reg(info, IE1, info->ie1_value);
                        write_reg(info, SR1, (unsigned char)(IDLE + UDRN));
        
                        write_reg(info, TXDMA + DIR, 0x40);             /* enable Tx DMA interrupts (EOM) */
                        write_reg(info, TXDMA + DSR, 0xf2);             /* clear Tx DMA IRQs, enable Tx DMA */
        
-                       info->tx_timer.expires = jiffies + jiffies_from_ms(5000);
+                       info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
                        add_timer(&info->tx_timer);
                }
                else {
@@ -4823,10 +5019,12 @@ CheckAgain:
                        info->icount.rxcrc++;
 
                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
        }
 
@@ -4836,7 +5034,7 @@ CheckAgain:
 
        if ( debug_level >= DEBUG_LEVEL_DATA )
                trace_block(info,info->rx_buf_list_ex[StartIndex].virt_addr,
-                       MIN(framesize,SCABUFSIZE),0);
+                       min_t(int, framesize,SCABUFSIZE),0);
 
        if (framesize) {
                if (framesize > info->max_frame_size)
@@ -4851,7 +5049,7 @@ CheckAgain:
                        info->icount.rxok++;
 
                        while(copy_count) {
-                               int partial_count = MIN(copy_count,SCABUFSIZE);
+                               int partial_count = min(copy_count,SCABUFSIZE);
                                memcpy( ptmp,
                                        info->rx_buf_list_ex[index].virt_addr,
                                        partial_count );
@@ -4862,22 +5060,13 @@ CheckAgain:
                                        index = 0;
                        }
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-                       if (info->netcount) {
-                               /* pass frame to syncppp device */
-                               sppp_rx_done(info,info->tmp_rx_buf,framesize);
-                       }
+#ifdef CONFIG_HDLC
+                       if (info->netcount)
+                               hdlcdev_rx(info,info->tmp_rx_buf,framesize);
                        else
 #endif
-                       {
-                               if ( tty && tty->ldisc.receive_buf ) {
-                                       /* Call the line discipline receive callback directly. */
-                                       tty->ldisc.receive_buf(tty,
-                                               info->tmp_rx_buf,
-                                               info->flag_buf,
-                                               framesize);
-                               }
-                       }
+                               ldisc_receive_buf(tty,info->tmp_rx_buf,
+                                                 info->flag_buf, framesize);
                }
        }
        /* Free the buffers used by this frame. */
@@ -4910,14 +5099,14 @@ void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count)
        SCADESC_EX *desc_ex;
 
        if ( debug_level >= DEBUG_LEVEL_DATA )
-               trace_block(info,buf, MIN(count,SCABUFSIZE), 1);
+               trace_block(info,buf, min_t(int, count,SCABUFSIZE), 1);
 
        /* Copy source buffer to one or more DMA buffers, starting with
         * the first transmit dma buffer.
         */
        for(i=0;;)
        {
-               copy_count = MIN(count,SCABUFSIZE);
+               copy_count = min_t(unsigned short,count,SCABUFSIZE);
 
                desc = &info->tx_buf_list[i];
                desc_ex = &info->tx_buf_list_ex[i];
@@ -5021,7 +5210,7 @@ int irq_test(SLMP_INFO *info)
        timeout=100;
        while( timeout-- && !info->irq_occurred ) {
                set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(jiffies_from_ms(10));
+               schedule_timeout(msecs_to_jiffies(10));
        }
 
        spin_lock_irqsave(&info->lock,flags);
@@ -5172,7 +5361,7 @@ int loopback_test(SLMP_INFO *info)
        /* Set a timeout for waiting for interrupt. */
        for ( timeout = 100; timeout; --timeout ) {
                set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(jiffies_from_ms(10));
+               schedule_timeout(msecs_to_jiffies(10));
 
                if (rx_get_frame(info)) {
                        rc = TRUE;
@@ -5384,9 +5573,9 @@ void tx_timeout(unsigned long context)
 
        spin_unlock_irqrestore(&info->lock,flags);
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
        if (info->netcount)
-               sppp_tx_done(info);
+               hdlcdev_tx_done(info);
        else
 #endif
                bh_transmit(info);
@@ -5428,7 +5617,7 @@ void status_timeout(unsigned long context)
 
        info->status_timer.data = (unsigned long)info;
        info->status_timer.function = status_timeout;
-       info->status_timer.expires = jiffies + jiffies_from_ms(10);
+       info->status_timer.expires = jiffies + msecs_to_jiffies(10);
        add_timer(&info->status_timer);
 }