aboutsummaryrefslogtreecommitdiff
path: root/drivers/char/synclink_gt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/synclink_gt.c')
-rw-r--r--drivers/char/synclink_gt.c5162
1 files changed, 0 insertions, 5162 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
deleted file mode 100644
index d01fffeac95..00000000000
--- a/drivers/char/synclink_gt.c
+++ /dev/null
@@ -1,5162 +0,0 @@
-/*
- * Device driver for Microgate SyncLink GT serial adapters.
- *
- * written by Paul Fulghum for Microgate Corporation
- * paulkf@microgate.com
- *
- * Microgate and SyncLink are trademarks of Microgate Corporation
- *
- * This code is released under the GNU General Public License (GPL)
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * DEBUG OUTPUT DEFINITIONS
- *
- * uncomment lines below to enable specific types of debug output
- *
- * DBGINFO information - most verbose output
- * DBGERR serious errors
- * DBGBH bottom half service routine debugging
- * DBGISR interrupt service routine debugging
- * DBGDATA output receive and transmit data
- * DBGTBUF output transmit DMA buffers and registers
- * DBGRBUF output receive DMA buffers and registers
- */
-
-#define DBGINFO(fmt) if (debug_level >= DEBUG_LEVEL_INFO) printk fmt
-#define DBGERR(fmt) if (debug_level >= DEBUG_LEVEL_ERROR) printk fmt
-#define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt
-#define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt
-#define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label))
-/*#define DBGTBUF(info) dump_tbufs(info)*/
-/*#define DBGRBUF(info) dump_rbufs(info)*/
-
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/netdevice.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/ioctl.h>
-#include <linux/termios.h>
-#include <linux/bitops.h>
-#include <linux/workqueue.h>
-#include <linux/hdlc.h>
-#include <linux/synclink.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <asm/types.h>
-#include <asm/uaccess.h>
-
-#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE))
-#define SYNCLINK_GENERIC_HDLC 1
-#else
-#define SYNCLINK_GENERIC_HDLC 0
-#endif
-
-/*
- * module identification
- */
-static char *driver_name = "SyncLink GT";
-static char *tty_driver_name = "synclink_gt";
-static char *tty_dev_prefix = "ttySLG";
-MODULE_LICENSE("GPL");
-#define MGSL_MAGIC 0x5401
-#define MAX_DEVICES 32
-
-static struct pci_device_id pci_table[] = {
- {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
- {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT2_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
- {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
- {PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
- {0,}, /* terminate list */
-};
-MODULE_DEVICE_TABLE(pci, pci_table);
-
-static int init_one(struct pci_dev *dev,const struct pci_device_id *ent);
-static void remove_one(struct pci_dev *dev);
-static struct pci_driver pci_driver = {
- .name = "synclink_gt",
- .id_table = pci_table,
- .probe = init_one,
- .remove = __devexit_p(remove_one),
-};
-
-static bool pci_registered;
-
-/*
- * module configuration and status
- */
-static struct slgt_info *slgt_device_list;
-static int slgt_device_count;
-
-static int ttymajor;
-static int debug_level;
-static int maxframe[MAX_DEVICES];
-
-module_param(ttymajor, int, 0);
-module_param(debug_level, int, 0);
-module_param_array(maxframe, int, NULL, 0);
-
-MODULE_PARM_DESC(ttymajor, "TTY major device number override: 0=auto assigned");
-MODULE_PARM_DESC(debug_level, "Debug syslog output: 0=disabled, 1 to 5=increasing detail");
-MODULE_PARM_DESC(maxframe, "Maximum frame size used by device (4096 to 65535)");
-
-/*
- * tty support and callbacks
- */
-static struct tty_driver *serial_driver;
-
-static int open(struct tty_struct *tty, struct file * filp);
-static void close(struct tty_struct *tty, struct file * filp);
-static void hangup(struct tty_struct *tty);
-static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
-
-static int write(struct tty_struct *tty, const unsigned char *buf, int count);
-static int 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 int write_room(struct tty_struct *tty);
-static void flush_chars(struct tty_struct *tty);
-static void flush_buffer(struct tty_struct *tty);
-static void tx_hold(struct tty_struct *tty);
-static void tx_release(struct tty_struct *tty);
-
-static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static int chars_in_buffer(struct tty_struct *tty);
-static void throttle(struct tty_struct * tty);
-static void unthrottle(struct tty_struct * tty);
-static int set_break(struct tty_struct *tty, int break_state);
-
-/*
- * generic HDLC support and callbacks
- */
-#if SYNCLINK_GENERIC_HDLC
-#define dev_to_port(D) (dev_to_hdlc(D)->priv)
-static void hdlcdev_tx_done(struct slgt_info *info);
-static void hdlcdev_rx(struct slgt_info *info, char *buf, int size);
-static int hdlcdev_init(struct slgt_info *info);
-static void hdlcdev_exit(struct slgt_info *info);
-#endif
-
-
-/*
- * device specific structures, macros and functions
- */
-
-#define SLGT_MAX_PORTS 4
-#define SLGT_REG_SIZE 256
-
-/*
- * conditional wait facility
- */
-struct cond_wait {
- struct cond_wait *next;
- wait_queue_head_t q;
- wait_queue_t wait;
- unsigned int data;
-};
-static void init_cond_wait(struct cond_wait *w, unsigned int data);
-static void add_cond_wait(struct cond_wait **head, struct cond_wait *w);
-static void remove_cond_wait(struct cond_wait **head, struct cond_wait *w);
-static void flush_cond_wait(struct cond_wait **head);
-
-/*
- * DMA buffer descriptor and access macros
- */
-struct slgt_desc
-{
- __le16 count;
- __le16 status;
- __le32 pbuf; /* physical address of data buffer */
- __le32 next; /* physical address of next descriptor */
-
- /* driver book keeping */
- char *buf; /* virtual address of data buffer */
- unsigned int pdesc; /* physical address of this descriptor */
- dma_addr_t buf_dma_addr;
- unsigned short buf_count;
-};
-
-#define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b))
-#define set_desc_next(a,b) (a).next = cpu_to_le32((unsigned int)(b))
-#define set_desc_count(a,b)(a).count = cpu_to_le16((unsigned short)(b))
-#define set_desc_eof(a,b) (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0))
-#define set_desc_status(a, b) (a).status = cpu_to_le16((unsigned short)(b))
-#define desc_count(a) (le16_to_cpu((a).count))
-#define desc_status(a) (le16_to_cpu((a).status))
-#define desc_complete(a) (le16_to_cpu((a).status) & BIT15)
-#define desc_eof(a) (le16_to_cpu((a).status) & BIT2)
-#define desc_crc_error(a) (le16_to_cpu((a).status) & BIT1)
-#define desc_abort(a) (le16_to_cpu((a).status) & BIT0)
-#define desc_residue(a) ((le16_to_cpu((a).status) & 0x38) >> 3)
-
-struct _input_signal_events {
- int ri_up;
- int ri_down;
- int dsr_up;
- int dsr_down;
- int dcd_up;
- int dcd_down;
- int cts_up;
- int cts_down;
-};
-
-/*
- * device instance data structure
- */
-struct slgt_info {
- void *if_ptr; /* General purpose pointer (used by SPPP) */
- struct tty_port port;
-
- struct slgt_info *next_device; /* device list link */
-
- int magic;
-
- char device_name[25];
- struct pci_dev *pdev;
-
- int port_count; /* count of ports on adapter */
- int adapter_num; /* adapter instance number */
- int port_num; /* port instance number */
-
- /* array of pointers to port contexts on this adapter */
- struct slgt_info *port_array[SLGT_MAX_PORTS];
-
- int line; /* tty line instance number */
-
- struct mgsl_icount icount;
-
- int timeout;
- int x_char; /* xon/xoff character */
- unsigned int read_status_mask;
- unsigned int ignore_status_mask;
-
- wait_queue_head_t status_event_wait_q;
- wait_queue_head_t event_wait_q;
- struct timer_list tx_timer;
- struct timer_list rx_timer;
-
- unsigned int gpio_present;
- struct cond_wait *gpio_wait_q;
-
- spinlock_t lock; /* spinlock for synchronizing with ISR */
-
- struct work_struct task;
- u32 pending_bh;
- bool bh_requested;
- bool bh_running;
-
- int isr_overflow;
- bool irq_requested; /* true if IRQ requested */
- bool irq_occurred; /* for diagnostics use */
-
- /* device configuration */
-
- unsigned int bus_type;
- unsigned int irq_level;
- unsigned long irq_flags;
-
- unsigned char __iomem * reg_addr; /* memory mapped registers address */
- u32 phys_reg_addr;
- bool reg_addr_requested;
-
- MGSL_PARAMS params; /* communications parameters */
- u32 idle_mode;
- u32 max_frame_size; /* as set by device config */
-
- unsigned int rbuf_fill_level;
- unsigned int rx_pio;
- unsigned int if_mode;
- unsigned int base_clock;
- unsigned int xsync;
- unsigned int xctrl;
-
- /* device status */
-
- bool rx_enabled;
- bool rx_restart;
-
- bool tx_enabled;
- bool tx_active;
-
- unsigned char signals; /* serial signal states */
- int init_error; /* initialization error */
-
- unsigned char *tx_buf;
- int tx_count;
-
- char flag_buf[MAX_ASYNC_BUFFER_SIZE];
- char char_buf[MAX_ASYNC_BUFFER_SIZE];
- bool drop_rts_on_tx_done;
- struct _input_signal_events input_signal_events;
-
- int dcd_chkcount; /* check counts to prevent */
- int cts_chkcount; /* too many IRQs if a signal */
- int dsr_chkcount; /* is floating */
- int ri_chkcount;
-
- char *bufs; /* virtual address of DMA buffer lists */
- dma_addr_t bufs_dma_addr; /* physical address of buffer descriptors */
-
- unsigned int rbuf_count;
- struct slgt_desc *rbufs;
- unsigned int rbuf_current;
- unsigned int rbuf_index;
- unsigned int rbuf_fill_index;
- unsigned short rbuf_fill_count;
-
- unsigned int tbuf_count;
- struct slgt_desc *tbufs;
- unsigned int tbuf_current;
- unsigned int tbuf_start;
-
- unsigned char *tmp_rbuf;
- unsigned int tmp_rbuf_count;
-
- /* SPPP/Cisco HDLC device parts */
-
- int netcount;
- spinlock_t netlock;
-#if SYNCLINK_GENERIC_HDLC
- struct net_device *netdev;
-#endif
-
-};
-
-static MGSL_PARAMS default_params = {
- .mode = MGSL_MODE_HDLC,
- .loopback = 0,
- .flags = HDLC_FLAG_UNDERRUN_ABORT15,
- .encoding = HDLC_ENCODING_NRZI_SPACE,
- .clock_speed = 0,
- .addr_filter = 0xff,
- .crc_type = HDLC_CRC_16_CCITT,
- .preamble_length = HDLC_PREAMBLE_LENGTH_8BITS,
- .preamble = HDLC_PREAMBLE_PATTERN_NONE,
- .data_rate = 9600,
- .data_bits = 8,
- .stop_bits = 1,
- .parity = ASYNC_PARITY_NONE
-};
-
-
-#define BH_RECEIVE 1
-#define BH_TRANSMIT 2
-#define BH_STATUS 4
-#define IO_PIN_SHUTDOWN_LIMIT 100
-
-#define DMABUFSIZE 256
-#define DESC_LIST_SIZE 4096
-
-#define MASK_PARITY BIT1
-#define MASK_FRAMING BIT0
-#define MASK_BREAK BIT14
-#define MASK_OVERRUN BIT4
-
-#define GSR 0x00 /* global status */
-#define JCR 0x04 /* JTAG control */
-#define IODR 0x08 /* GPIO direction */
-#define IOER 0x0c /* GPIO interrupt enable */
-#define IOVR 0x10 /* GPIO value */
-#define IOSR 0x14 /* GPIO interrupt status */
-#define TDR 0x80 /* tx data */
-#define RDR 0x80 /* rx data */
-#define TCR 0x82 /* tx control */
-#define TIR 0x84 /* tx idle */
-#define TPR 0x85 /* tx preamble */
-#define RCR 0x86 /* rx control */
-#define VCR 0x88 /* V.24 control */
-#define CCR 0x89 /* clock control */
-#define BDR 0x8a /* baud divisor */
-#define SCR 0x8c /* serial control */
-#define SSR 0x8e /* serial status */
-#define RDCSR 0x90 /* rx DMA control/status */
-#define TDCSR 0x94 /* tx DMA control/status */
-#define RDDAR 0x98 /* rx DMA descriptor address */
-#define TDDAR 0x9c /* tx DMA descriptor address */
-#define XSR 0x40 /* extended sync pattern */
-#define XCR 0x44 /* extended control */
-
-#define RXIDLE BIT14
-#define RXBREAK BIT14
-#define IRQ_TXDATA BIT13
-#define IRQ_TXIDLE BIT12
-#define IRQ_TXUNDER BIT11 /* HDLC */
-#define IRQ_RXDATA BIT10
-#define IRQ_RXIDLE BIT9 /* HDLC */
-#define IRQ_RXBREAK BIT9 /* async */
-#define IRQ_RXOVER BIT8
-#define IRQ_DSR BIT7
-#define IRQ_CTS BIT6
-#define IRQ_DCD BIT5
-#define IRQ_RI BIT4
-#define IRQ_ALL 0x3ff0
-#define IRQ_MASTER BIT0
-
-#define slgt_irq_on(info, mask) \
- wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) | (mask)))
-#define slgt_irq_off(info, mask) \
- wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) & ~(mask)))
-
-static __u8 rd_reg8(struct slgt_info *info, unsigned int addr);
-static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value);
-static __u16 rd_reg16(struct slgt_info *info, unsigned int addr);
-static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value);
-static __u32 rd_reg32(struct slgt_info *info, unsigned int addr);
-static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value);
-
-static void msc_set_vcr(struct slgt_info *info);
-
-static int startup(struct slgt_info *info);
-static int block_til_ready(struct tty_struct *tty, struct file * filp,struct slgt_info *info);
-static void shutdown(struct slgt_info *info);
-static void program_hw(struct slgt_info *info);
-static void change_params(struct slgt_info *info);
-
-static int register_test(struct slgt_info *info);
-static int irq_test(struct slgt_info *info);
-static int loopback_test(struct slgt_info *info);
-static int adapter_test(struct slgt_info *info);
-
-static void reset_adapter(struct slgt_info *info);
-static void reset_port(struct slgt_info *info);
-static void async_mode(struct slgt_info *info);
-static void sync_mode(struct slgt_info *info);
-
-static void rx_stop(struct slgt_info *info);
-static void rx_start(struct slgt_info *info);
-static void reset_rbufs(struct slgt_info *info);
-static void free_rbufs(struct slgt_info *info, unsigned int first, unsigned int last);
-static void rdma_reset(struct slgt_info *info);
-static bool rx_get_frame(struct slgt_info *info);
-static bool rx_get_buf(struct slgt_info *info);
-
-static void tx_start(struct slgt_info *info);
-static void tx_stop(struct slgt_info *info);
-static void tx_set_idle(struct slgt_info *info);
-static unsigned int free_tbuf_count(struct slgt_info *info);
-static unsigned int tbuf_bytes(struct slgt_info *info);
-static void reset_tbufs(struct slgt_info *info);
-static void tdma_reset(struct slgt_info *info);
-static bool tx_load(struct slgt_info *info, const char *buf, unsigned int count);
-
-static void get_signals(struct slgt_info *info);
-static void set_signals(struct slgt_info *info);
-static void enable_loopback(struct slgt_info *info);
-static void set_rate(struct slgt_info *info, u32 data_rate);
-
-static int bh_action(struct slgt_info *info);
-static void bh_handler(struct work_struct *work);
-static void bh_transmit(struct slgt_info *info);
-static void isr_serial(struct slgt_info *info);
-static void isr_rdma(struct slgt_info *info);
-static void isr_txeom(struct slgt_info *info, unsigned short status);
-static void isr_tdma(struct slgt_info *info);
-
-static int alloc_dma_bufs(struct slgt_info *info);
-static void free_dma_bufs(struct slgt_info *info);
-static int alloc_desc(struct slgt_info *info);
-static void free_desc(struct slgt_info *info);
-static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count);
-static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count);
-
-static int alloc_tmp_rbuf(struct slgt_info *info);
-static void free_tmp_rbuf(struct slgt_info *info);
-
-static void tx_timeout(unsigned long context);
-static void rx_timeout(unsigned long context);
-
-/*
- * ioctl handlers
- */
-static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount);
-static int get_params(struct slgt_info *info, MGSL_PARAMS __user *params);
-static int set_params(struct slgt_info *info, MGSL_PARAMS __user *params);
-static int get_txidle(struct slgt_info *info, int __user *idle_mode);
-static int set_txidle(struct slgt_info *info, int idle_mode);
-static int tx_enable(struct slgt_info *info, int enable);
-static int tx_abort(struct slgt_info *info);
-static int rx_enable(struct slgt_info *info, int enable);
-static int modem_input_wait(struct slgt_info *info,int arg);
-static int wait_mgsl_event(struct slgt_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 int set_break(struct tty_struct *tty, int break_state);
-static int get_interface(struct slgt_info *info, int __user *if_mode);
-static int set_interface(struct slgt_info *info, int if_mode);
-static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
-static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
-static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
-static int get_xsync(struct slgt_info *info, int __user *if_mode);
-static int set_xsync(struct slgt_info *info, int if_mode);
-static int get_xctrl(struct slgt_info *info, int __user *if_mode);
-static int set_xctrl(struct slgt_info *info, int if_mode);
-
-/*
- * driver functions
- */
-static void add_device(struct slgt_info *info);
-static void device_init(int adapter_num, struct pci_dev *pdev);
-static int claim_resources(struct slgt_info *info);
-static void release_resources(struct slgt_info *info);
-
-/*
- * DEBUG OUTPUT CODE
- */
-#ifndef DBGINFO
-#define DBGINFO(fmt)
-#endif
-#ifndef DBGERR
-#define DBGERR(fmt)
-#endif
-#ifndef DBGBH
-#define DBGBH(fmt)
-#endif
-#ifndef DBGISR
-#define DBGISR(fmt)
-#endif
-
-#ifdef DBGDATA
-static void trace_block(struct slgt_info *info, const char *data, int count, const char *label)
-{
- int i;
- int linecount;
- printk("%s %s data:\n",info->device_name, label);
- while(count) {
- linecount = (count > 16) ? 16 : count;
- for(i=0; i < linecount; i++)
- printk("%02X ",(unsigned char)data[i]);
- for(;i<17;i++)
- printk(" ");
- for(i=0;i<linecount;i++) {
- if (data[i]>=040 && data[i]<=0176)
- printk("%c",data[i]);
- else
- printk(".");
- }
- printk("\n");
- data += linecount;
- count -= linecount;
- }
-}
-#else
-#define DBGDATA(info, buf, size, label)
-#endif
-
-#ifdef DBGTBUF
-static void dump_tbufs(struct slgt_info *info)
-{
- int i;
- printk("tbuf_current=%d\n", info->tbuf_current);
- for (i=0 ; i < info->tbuf_count ; i++) {
- printk("%d: count=%04X status=%04X\n",
- i, le16_to_cpu(info->tbufs[i].count), le16_to_cpu(info->tbufs[i].status));
- }
-}
-#else
-#define DBGTBUF(info)
-#endif
-
-#ifdef DBGRBUF
-static void dump_rbufs(struct slgt_info *info)
-{
- int i;
- printk("rbuf_current=%d\n", info->rbuf_current);
- for (i=0 ; i < info->rbuf_count ; i++) {
- printk("%d: count=%04X status=%04X\n",
- i, le16_to_cpu(info->rbufs[i].count), le16_to_cpu(info->rbufs[i].status));
- }
-}
-#else
-#define DBGRBUF(info)
-#endif
-
-static inline int sanity_check(struct slgt_info *info, char *devname, const char *name)
-{
-#ifdef SANITY_CHECK
- if (!info) {
- printk("null struct slgt_info for (%s) in %s\n", devname, name);
- return 1;
- }
- if (info->magic != MGSL_MAGIC) {
- printk("bad magic number struct slgt_info (%s) in %s\n", devname, name);
- return 1;
- }
-#else
- if (!info)
- return 1;
-#endif
- 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->ops->receive_buf)
- ld->ops->receive_buf(tty, data, flags, count);
- tty_ldisc_deref(ld);
- }
-}
-
-/* tty callbacks */
-
-static int open(struct tty_struct *tty, struct file *filp)
-{
- struct slgt_info *info;
- int retval, line;
- unsigned long flags;
-
- line = tty->index;
- if ((line < 0) || (line >= slgt_device_count)) {
- DBGERR(("%s: open with invalid line #%d.\n", driver_name, line));
- return -ENODEV;
- }
-
- info = slgt_device_list;
- while(info && info->line != line)
- info = info->next_device;
- if (sanity_check(info, tty->name, "open"))
- return -ENODEV;
- if (info->init_error) {
- DBGERR(("%s init error=%d\n", info->device_name, info->init_error));
- return -ENODEV;
- }
-
- tty->driver_data = info;
- info->port.tty = tty;
-
- DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count));
-
- /* If port is closing, signal caller to try again */
- if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
- if (info->port.flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->port.close_wait);
- retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
- goto cleanup;
- }
-
- mutex_lock(&info->port.mutex);
- info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
- spin_lock_irqsave(&info->netlock, flags);
- if (info->netcount) {
- retval = -EBUSY;
- spin_unlock_irqrestore(&info->netlock, flags);
- mutex_unlock(&info->port.mutex);
- goto cleanup;
- }
- info->port.count++;
- spin_unlock_irqrestore(&info->netlock, flags);
-
- if (info->port.count == 1) {
- /* 1st open on this device, init hardware */
- retval = startup(info);
- if (retval < 0) {
- mutex_unlock(&info->port.mutex);
- goto cleanup;
- }
- }
- mutex_unlock(&info->port.mutex);
- retval = block_til_ready(tty, filp, info);
- if (retval) {
- DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval));
- goto cleanup;
- }
-
- retval = 0;
-
-cleanup:
- if (retval) {
- if (tty->count == 1)
- info->port.tty = NULL; /* tty layer will release tty struct */
- if(info->port.count)
- info->port.count--;
- }
-
- DBGINFO(("%s open rc=%d\n", info->device_name, retval));
- return retval;
-}
-
-static void close(struct tty_struct *tty, struct file *filp)
-{
- struct slgt_info *info = tty->driver_data;
-
- if (sanity_check(info, tty->name, "close"))
- return;
- DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count));
-
- if (tty_port_close_start(&info->port, tty, filp) == 0)
- goto cleanup;
-
- mutex_lock(&info->port.mutex);
- if (info->port.flags & ASYNC_INITIALIZED)
- wait_until_sent(tty, info->timeout);
- flush_buffer(tty);
- tty_ldisc_flush(tty);
-
- shutdown(info);
- mutex_unlock(&info->port.mutex);
-
- tty_port_close_end(&info->port, tty);
- info->port.tty = NULL;
-cleanup:
- DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count));
-}
-
-static void hangup(struct tty_struct *tty)
-{
- struct slgt_info *info = tty->driver_data;
- unsigned long flags;
-
- if (sanity_check(info, tty->name, "hangup"))
- return;
- DBGINFO(("%s hangup\n", info->device_name));
-
- flush_buffer(tty);
-
- mutex_lock(&info->port.mutex);
- shutdown(info);
-
- spin_lock_irqsave(&info->port.lock, flags);
- info->port.count = 0;
- info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
- info->port.tty = NULL;
- spin_unlock_irqrestore(&info->port.lock, flags);
- mutex_unlock(&info->port.mutex);
-
- wake_up_interruptible(&info->port.open_wait);
-}
-
-static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
- struct slgt_info *info = tty->driver_data;
- unsigned long flags;
-
- DBGINFO(("%s set_termios\n", tty->driver->name));
-
- change_params(info);
-
- /* Handle transition to B0 status */
- if (old_termios->c_cflag & CBAUD &&
- !(tty->termios->c_cflag & CBAUD)) {
- info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
- spin_lock_irqsave(&info->lock,flags);
- set_signals(info);
- spin_unlock_irqrestore(&info->lock,flags);
- }
-
- /* Handle transition away from B0 status */
- if (!(old_termios->c_cflag & CBAUD) &&
- tty->termios->c_cflag & CBAUD) {
- info->signals |= SerialSignal_DTR;
- if (!(tty->termios->c_cflag & CRTSCTS) ||
- !test_bit(TTY_THROTTLED, &tty->flags)) {
- info->signals |= SerialSignal_RTS;
- }
- spin_lock_irqsave(&info->lock,flags);
- set_signals(info);
- spin_unlock_irqrestore(&info->lock,flags);
- }
-
- /* Handle turning off CRTSCTS */
- if (old_termios->c_cflag & CRTSCTS &&
- !(tty->termios->c_cflag & CRTSCTS)) {
- tty->hw_stopped = 0;
- tx_release(tty);
- }
-}
-
-static void update_tx_timer(struct slgt_info *info)
-{
- /*
- * use worst case speed of 1200bps to calculate transmit timeout
- * based on data in buffers (tbuf_bytes) and FIFO (128 bytes)
- */
- if (info->params.mode == MGSL_MODE_HDLC) {
- int timeout = (tbuf_bytes(info) * 7) + 1000;
- mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(timeout));
- }
-}
-
-static int write(struct tty_struct *tty,
- const unsigned char *buf, int count)
-{
- int ret = 0;
- struct slgt_info *info = tty->driver_data;
- unsigned long flags;
-
- if (sanity_check(info, tty->name, "write"))
- return -EIO;
-
- DBGINFO(("%s write count=%d\n", info->device_name, count));
-
- if (!info->tx_buf || (count > info->max_frame_size))
- return -EIO;
-
- if (!count || tty->stopped || tty->hw_stopped)
- return 0;
-
- spin_lock_irqsave(&info->lock, flags);
-
- if (info->tx_count) {
- /* send accumulated data from send_char() */
- if (!tx_load(info, info->tx_buf, info->tx_count))
- goto cleanup;
- info->tx_count = 0;
- }
-
- if (tx_load(info, buf, count))
- ret = count;
-
-cleanup:
- spin_unlock_irqrestore(&info->lock, flags);
- DBGINFO(("%s write rc=%d\n", info->device_name, ret));
- return ret;
-}
-
-static int put_char(struct tty_struct *tty, unsigned char ch)
-{
- struct slgt_info *info = tty->driver_data;
- unsigned long flags;
- int ret = 0;
-
- if (sanity_check(info, tty->name, "put_char"))
- return 0;
- DBGINFO(("%s put_char(%d)\n", info->device_name, ch));
- if (!info->tx_buf)
- return 0;
- spin_lock_irqsave(&info->lock,flags);
- if (info->tx_count < info->max_frame_size) {
- info->tx_buf[info->tx_count++] = ch;
- ret = 1;
- }
- spin_unlock_irqrestore(&info->lock,flags);
- return ret;
-}
-
-static void send_xchar(struct tty_struct *tty, char ch)
-{
- struct slgt_info *info = tty->driver_data;
- unsigned long flags;
-
- if (sanity_check(info, tty->name, "send_xchar"))
- return;
- DBGINFO(("%s send_xchar(%d)\n", info->device_name, ch));
- info->x_char = ch;
- if (ch) {
- spin_lock_irqsave(&info->lock,flags);
- if (!info->tx_enabled)
- tx_start(info);
- spin_unlock_irqrestore(&info->lock,flags);
- }
-}
-
-static void wait_until_sent(struct tty_struct *tty, int timeout)
-{
- struct slgt_info *info = tty->driver_data;
- unsigned long orig_jiffies, char_time;
-
- if (!info )
- return;
- if (sanity_check(info, tty->name, "wait_until_sent"))
- return;
- DBGINFO(("%s wait_until_sent entry\n", info->device_name));
- if (!(info->port.flags & ASYNC_INITIALIZED))
- goto exit;
-
- orig_jiffies = jiffies;
-
- /* Set check interval to 1/5 of estimated time to
- * send a character, and make it at least 1. The check
- * interval should also be less than the timeout.
- * Note: use tight timings here to satisfy the NIST-PCTS.
- */
-
- if (info->params.data_rate) {
- char_time = info->timeout/(32 * 5);
- if (!char_time)
- char_time++;
- } else
- char_time = 1;
-
- if (timeout)
- char_time = min_t(unsigned long, char_time, timeout);
-
- while (info->tx_active) {
- msleep_interruptible(jiffies_to_msecs(char_time));
- if (signal_pending(current))
- break;
- if (timeout && time_after(jiffies, orig_jiffies + timeout))
- break;
- }
-exit:
- DBGINFO(("%s wait_until_sent exit\n", info->device_name));
-}
-
-static int write_room(struct tty_struct *tty)
-{
- struct slgt_info *info = tty->driver_data;
- int ret;
-
- if (sanity_check(info, tty->name, "write_room"))
- return 0;
- ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
- DBGINFO(("%s write_room=%d\n", info->device_name, ret));
- return ret;
-}
-
-static void flush_chars(struct tty_struct *tty)
-{
- struct slgt_info *info = tty->driver_data;
- unsigned long flags;
-
- if (sanity_check(info, tty->name, "flush_chars"))
- return;
- DBGINFO(("%s flush_chars entry tx_count=%d\n", info->device_name, info->tx_count));
-
- if (info->tx_count <= 0 || tty->stopped ||
- tty->hw_stopped || !info->tx_buf)
- return;
-
- DBGINFO(("%s flush_chars start transmit\n", info->device_name));
-
- spin_lock_irqsave(&info->lock,flags);
- if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count))
- info->tx_count = 0;
- spin_unlock_irqrestore(&info->lock,flags);
-}
-
-static void flush_buffer(struct tty_struct *tty)
-{
- struct slgt_info *info = tty->driver_data;
- unsigned long flags;
-
- if (sanity_check(info, tty->name, "flush_buffer"))
- return;
- DBGINFO(("%s flush_buffer\n", info->device_name));
-
- spin_lock_irqsave(&info->lock, flags);
- info->tx_count = 0;
- spin_unlock_irqrestore(&info->lock, flags);
-
- tty_wakeup(tty);
-}
-
-/*
- * throttle (stop) transmitter
- */
-static void tx_hold(struct tty_struct *tty)
-{
- struct slgt_info *info = tty->driver_data;
- unsigned long flags;
-
- if (sanity_check(info, tty->name, "tx_hold"))
- return;
- DBGINFO(("%s tx_hold\n", info->device_name));
- spin_lock_irqsave(&info->lock,flags);
- if (info->tx_enabled && info->params.mode == MGSL_MODE_ASYNC)
- tx_stop(info);
- spin_unlock_irqrestore(&info->lock,flags);
-}
-
-/*
- * release (start) transmitter
- */
-static void tx_release(struct tty_struct *tty)
-{
- struct slgt_info *info = tty->driver_data;
- unsigned long flags;
-
- if (sanity_check(info, tty->name, "tx_release"))
- return;
- DBGINFO(("%s tx_release\n", info->device_name));
- spin_lock_irqsave(&info->lock, flags);
- if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count))
- info->tx_count = 0;
- spin_unlock_irqrestore(&info->lock, flags);
-}
-
-/*
- * Service an IOCTL request
- *
- * Arguments
- *
- * tty pointer to tty instance data
- * file pointer to associated file object for device
- * cmd IOCTL command code
- * arg command argument/context
- *
- * Return 0 if success, otherwise error code
- */
-static int ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct slgt_info *info = tty->driver_data;
- void __user *argp = (void __user *)arg;
- int ret;
-
- if (sanity_check(info, tty->name, "ioctl"))
- return -ENODEV;
- DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
-
- if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCMIWAIT)) {
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
- }
-
- switch (cmd) {
- case MGSL_IOCWAITEVENT:
- return wait_mgsl_event(info, argp);
- case TIOCMIWAIT:
- return modem_input_wait(info,(int)arg);
- case MGSL_IOCSGPIO:
- return set_gpio(info, argp);
- case MGSL_IOCGGPIO:
- return get_gpio(info, argp);
- case MGSL_IOCWAITGPIO:
- return wait_gpio(info, argp);
- case MGSL_IOCGXSYNC:
- return get_xsync(info, argp);
- case MGSL_IOCSXSYNC:
- return set_xsync(info, (int)arg);
- case MGSL_IOCGXCTRL:
- return get_xctrl(info, argp);
- case MGSL_IOCSXCTRL:
- return set_xctrl(info, (int)arg);
- }
- mutex_lock(&info->port.mutex);
- switch (cmd) {
- case MGSL_IOCGPARAMS:
- ret = get_params(info, argp);
- break;
- case MGSL_IOCSPARAMS:
- ret = set_params(info, argp);
- break;
- case MGSL_IOCGTXIDLE:
- ret = get_txidle(info, argp);
- break;
- case MGSL_IOCSTXIDLE:
- ret = set_txidle(info, (int)arg);
- break;
- case MGSL_IOCTXENABLE:
- ret = tx_enable(info, (int)arg);
- break;
- case MGSL_IOCRXENABLE:
- ret = rx_enable(info, (int)arg);
- break;
- case MGSL_IOCTXABORT:
- ret = tx_abort(info);
- break;
- case MGSL_IOCGSTATS:
- ret = get_stats(info, argp);
- break;
- case MGSL_IOCGIF:
- ret = get_interface(info, argp);
- break;
- case MGSL_IOCSIF:
- ret = set_interface(info,(int)arg);
- break;
- default:
- ret = -ENOIOCTLCMD;
- }
- mutex_unlock(&info->port.mutex);
- return ret;
-}
-
-static int get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-
-{
- struct slgt_info *info = tty->driver_data;
- struct mgsl_icount cnow; /* kernel counter temps */
- unsigned long flags;
-
- spin_lock_irqsave(&info->lock,flags);
- cnow = info->icount;
- spin_unlock_irqrestore(&info->lock,flags);
-
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
-
- retur