/*
- * $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/io.h>
#include <asm/irq.h>
#include <asm/dma.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#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)
int flags;
int count; /* count of opens */
int line;
- unsigned short close_delay;
- unsigned short closing_wait; /* time to wait before closing */
+ unsigned int close_delay;
+ unsigned int closing_wait; /* time to wait before closing */
struct mgsl_icount icount;
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
#define TEPR 0x65
/* DMA Controller Register macros */
-#define DAR 0x80
#define DARL 0x80
#define DARH 0x81
#define DARB 0x82
#define CRCE BIT2
-#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
-
/*
* Global linked list of SyncLink devices
*/
static int maxframe[MAX_DEVICES] = {0,};
static int dosyncppp[MAX_DEVICES] = {0,};
-MODULE_PARM(break_on_load,"i");
-MODULE_PARM(ttymajor,"i");
-MODULE_PARM(debug_level,"i");
-MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICES) "i");
-MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i");
+module_param(break_on_load, bool, 0);
+module_param(ttymajor, int, 0);
+module_param(debug_level, int, 0);
+module_param_array(maxframe, int, NULL, 0);
+module_param_array(dosyncppp, int, NULL, 0);
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);
/* 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 */
static void hangup(struct tty_struct *tty);
static void set_termios(struct tty_struct *tty, struct termios *old_termios);
-static int write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static int write(struct tty_struct *tty, const unsigned char *buf, int count);
static void put_char(struct tty_struct *tty, unsigned char ch);
static void send_xchar(struct tty_struct *tty, char ch);
static void wait_until_sent(struct tty_struct *tty, int timeout);
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 */
-static int get_stats(SLMP_INFO *info, struct mgsl_icount *user_icount);
-static int get_params(SLMP_INFO *info, MGSL_PARAMS *params);
-static int set_params(SLMP_INFO *info, MGSL_PARAMS *params);
-static int get_txidle(SLMP_INFO *info, int*idle_mode);
+static int get_stats(SLMP_INFO *info, struct mgsl_icount __user *user_icount);
+static int get_params(SLMP_INFO *info, MGSL_PARAMS __user *params);
+static int set_params(SLMP_INFO *info, MGSL_PARAMS __user *params);
+static int get_txidle(SLMP_INFO *info, int __user *idle_mode);
static int set_txidle(SLMP_INFO *info, int idle_mode);
static int tx_enable(SLMP_INFO *info, int enable);
static int tx_abort(SLMP_INFO *info);
static int rx_enable(SLMP_INFO *info, int enable);
static int map_status(int signals);
static int modem_input_wait(SLMP_INFO *info,int arg);
-static int wait_mgsl_event(SLMP_INFO *info, int *mask_ptr);
+static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr);
static int tiocmget(struct tty_struct *tty, struct file *file);
static int tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
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;
* This allows remote debugging of dynamically loadable modules.
*/
static void* synclinkmp_get_text_ptr(void);
-static void* synclinkmp_get_text_ptr() {return synclinkmp_get_text_ptr;}
+static void* synclinkmp_get_text_ptr(void) {return synclinkmp_get_text_ptr;}
static inline int sanity_check(SLMP_INFO *info,
char *name, const char *routine)
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.
cleanup:
if (retval) {
if (tty->count == 1)
- info->tty = 0; /* tty layer will release tty struct */
+ info->tty = NULL; /* tty layer will release tty struct */
if(info->count)
info->count--;
}
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);
tty->closing = 0;
- info->tty = 0;
+ info->tty = NULL;
if (info->blocked_open) {
if (info->close_delay) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(info->close_delay);
+ msleep_interruptible(jiffies_to_msecs(info->close_delay));
}
wake_up_interruptible(&info->open_wait);
}
info->count = 0;
info->flags &= ~ASYNC_NORMAL_ACTIVE;
- info->tty = 0;
+ info->tty = NULL;
wake_up_interruptible(&info->open_wait);
}
* Arguments:
*
* tty pointer to tty information structure
- * from_user flag: 1 = from user process
* buf pointer to buffer containing send data
* count size of send data in bytes
*
* Return Value: number of characters written
*/
-static int write(struct tty_struct *tty, int from_user,
+static int write(struct tty_struct *tty,
const unsigned char *buf, int count)
{
- int c, ret = 0, err;
+ int c, ret = 0;
SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
unsigned long flags;
tx_load_dma_buffer(info, info->tx_buf, info->tx_count);
goto start;
}
- if (!from_user) {
- ret = info->tx_count = count;
- tx_load_dma_buffer(info, buf, count);
- goto start;
- }
+ ret = info->tx_count = count;
+ tx_load_dma_buffer(info, buf, count);
+ goto start;
}
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;
- if (from_user) {
- COPY_FROM_USER(err, info->tx_buf + info->tx_put, buf, c);
- if (err) {
- if (!ret)
- ret = -EFAULT;
- break;
- }
- } else
- memcpy(info->tx_buf + info->tx_put, buf, c);
+ memcpy(info->tx_buf + info->tx_put, buf, c);
spin_lock_irqsave(&info->lock,flags);
info->tx_put += c;
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) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(char_time);
+ msleep_interruptible(jiffies_to_msecs(char_time));
if (signal_pending(current))
break;
if (timeout && time_after(jiffies, orig_jiffies + timeout))
//TODO: determine if there is something similar to USC16C32
// TXSTATUS_ALL_SENT status
while ( info->tx_active && info->tx_enabled) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(char_time);
+ msleep_interruptible(jiffies_to_msecs(char_time));
if (signal_pending(current))
break;
if (timeout && time_after(jiffies, orig_jiffies + timeout))
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
SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
int error;
struct mgsl_icount cnow; /* kernel counter temps */
- struct serial_icounter_struct *p_cuser; /* user space */
+ struct serial_icounter_struct __user *p_cuser; /* user space */
unsigned long flags;
+ void __user *argp = (void __user *)arg;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s ioctl() cmd=%08X\n", __FILE__,__LINE__,
switch (cmd) {
case MGSL_IOCGPARAMS:
- return get_params(info,(MGSL_PARAMS *)arg);
+ return get_params(info, argp);
case MGSL_IOCSPARAMS:
- return set_params(info,(MGSL_PARAMS *)arg);
+ return set_params(info, argp);
case MGSL_IOCGTXIDLE:
- return get_txidle(info,(int*)arg);
+ return get_txidle(info, argp);
case MGSL_IOCSTXIDLE:
- return set_txidle(info,(int)arg);
+ return set_txidle(info, (int)arg);
case MGSL_IOCTXENABLE:
- return tx_enable(info,(int)arg);
+ return tx_enable(info, (int)arg);
case MGSL_IOCRXENABLE:
- return rx_enable(info,(int)arg);
+ return rx_enable(info, (int)arg);
case MGSL_IOCTXABORT:
return tx_abort(info);
case MGSL_IOCGSTATS:
- return get_stats(info,(struct mgsl_icount*)arg);
+ return get_stats(info, argp);
case MGSL_IOCWAITEVENT:
- return wait_mgsl_event(info,(int*)arg);
+ return wait_mgsl_event(info, argp);
case MGSL_IOCLOOPTXDONE:
return 0; // TODO: Not supported, need to document
/* Wait for modem input (DCD,RI,DSR,CTS) change
spin_lock_irqsave(&info->lock,flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->lock,flags);
- p_cuser = (struct serial_icounter_struct *) arg;
+ p_cuser = argp;
PUT_USER(error,cnow.cts, &p_cuser->cts);
if (error) return error;
PUT_USER(error,cnow.dsr, &p_cuser->dsr);
spin_unlock_irqrestore(&info->lock,flags);
}
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-
-/* 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;
-}
+#ifdef CONFIG_HDLC
-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;
}
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);
}
-static void sppp_rx_done(SLMP_INFO *info, char *buf, int size)
+/**
+ * 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);
+}
+
+/**
+ * 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->protocol = hdlc_type_trans(skb, info->netdev);
+
+ 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.
__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);
}
}
{
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",
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)
set_signals(info);
}
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
if (info->netcount)
- sppp_tx_done(info);
+ hdlcdev_tx_done(info);
else
#endif
{
*/
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",
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;
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 */
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)
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)
{
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)
if (info->tx_buf) {
kfree(info->tx_buf);
- info->tx_buf = 0;
+ info->tx_buf = NULL;
}
spin_lock_irqsave(&info->lock,flags);
program_hw(info);
}
-static int get_stats(SLMP_INFO * info, struct mgsl_icount *user_icount)
+static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount)
{
int err;
return 0;
}
-static int get_params(SLMP_INFO * info, MGSL_PARAMS *user_params)
+static int get_params(SLMP_INFO * info, MGSL_PARAMS __user *user_params)
{
int err;
if (debug_level >= DEBUG_LEVEL_INFO)
return 0;
}
-static int set_params(SLMP_INFO * info, MGSL_PARAMS *new_params)
+static int set_params(SLMP_INFO * info, MGSL_PARAMS __user *new_params)
{
unsigned long flags;
MGSL_PARAMS tmp_params;
return 0;
}
-static int get_txidle(SLMP_INFO * info, int*idle_mode)
+static int get_txidle(SLMP_INFO * info, int __user *idle_mode)
{
int err;
/* wait for specified event to occur
*/
-static int wait_mgsl_event(SLMP_INFO * info, int * mask_ptr)
+static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
{
unsigned long flags;
int s;
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);
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);
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
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
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;
}
}
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 ) {
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;
}
if (info->memory_base){
iounmap(info->memory_base);
- info->memory_base = 0;
+ info->memory_base = NULL;
}
if (info->sca_base) {
iounmap(info->sca_base - info->sca_offset);
- info->sca_base=0;
+ info->sca_base=NULL;
}
if (info->statctrl_base) {
iounmap(info->statctrl_base - info->statctrl_offset);
- info->statctrl_base=0;
+ info->statctrl_base=NULL;
}
if (info->lcr_base){
iounmap(info->lcr_base - info->lcr_offset);
- info->lcr_base = 0;
+ info->lcr_base = NULL;
}
if ( debug_level >= DEBUG_LEVEL_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
}
static void synclinkmp_cleanup(void)
{
- unsigned long flags;
int rc;
SLMP_INFO *info;
SLMP_INFO *tmp;
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;
}
}
+ 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 */
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 {
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
}
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)
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 );
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. */
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];
timeout=100;
while( timeout-- && !info->irq_occurred ) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(jiffies_from_ms(10));
+ msleep_interruptible(10);
}
spin_lock_irqsave(&info->lock,flags);
u32 speed = info->params.clock_speed;
info->params.clock_speed = 3686400;
- info->tty = 0;
+ info->tty = NULL;
/* assume failure */
info->init_error = DiagStatus_DmaFailure;
/* wait for receive complete */
/* Set a timeout for waiting for interrupt. */
for ( timeout = 100; timeout; --timeout ) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(jiffies_from_ms(10));
+ msleep_interruptible(10);
if (rx_get_frame(info)) {
rc = TRUE;
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);
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);
}