/*
* $Id: ctctty.c,v 1.29 2005/04/05 08:50:44 mschwide Exp $
*
* CTC / ESCON network driver, tty interface.
*
* Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/serial_reg.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <linux/devfs_fs_kernel.h>
#include "ctctty.h"
#include "ctcdbug.h"
#define CTC_TTY_MAJOR 43
#define CTC_TTY_MAX_DEVICES 64
#define CTC_ASYNC_MAGIC 0x49344C01 /* for paranoia-checking */
#define CTC_ASYNC_INITIALIZED 0x80000000 /* port was initialized */
#define CTC_ASYNC_NORMAL_ACTIVE 0x20000000 /* Normal device active */
#define CTC_ASYNC_CLOSING 0x08000000 /* Serial port is closing */
#define CTC_ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */
#define CTC_ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */
#define CTC_ASYNC_HUP_NOTIFY 0x0001 /* Notify tty on hangups/closes */
#define CTC_ASYNC_NETDEV_OPEN 0x0002 /* Underlying netdev is open */
#define CTC_ASYNC_TX_LINESTAT 0x0004 /* Must send line status */
#define CTC_ASYNC_SPLIT_TERMIOS 0x0008 /* Sep. termios for dialin/out */
#define CTC_TTY_XMIT_SIZE 1024 /* Default bufsize for write */
#define CTC_SERIAL_XMIT_MAX 4000 /* Maximum bufsize for write */
/* Private data (similar to async_struct in <linux/serial.h>) */
typedef struct {
int magic;
int flags; /* defined in tty.h */
int mcr; /* Modem control register */
int msr; /* Modem status register */
int lsr; /* Line status register */
int line;
int count; /* # of fd on device */
int blocked_open; /* # of blocked opens */
struct net_device *netdev;
struct sk_buff_head tx_queue; /* transmit queue */
struct sk_buff_head rx_queue; /* receive queue */
struct tty_struct *tty; /* Pointer to corresponding tty */
wait_queue_head_t open_wait;
wait_queue_head_t close_wait;
struct semaphore write_sem;
struct tasklet_struct tasklet;
struct timer_list stoptimer;
} ctc_tty_info;
/* Description of one CTC-tty */
typedef struct {
struct tty_driver *ctc_tty_device; /* tty-device */
ctc_tty_info info[CTC_TTY_MAX_DEVICES]; /* Private data */
} ctc_tty_driver;
static ctc_tty_driver *driver;
/* Leave this unchanged unless you know what you do! */
#define MODEM_PARANOIA_CHECK
#define MODEM_DO_RESTART
#define CTC_TTY_NAME "ctctty"
static __u32 ctc_tty_magic = CTC_ASYNC_MAGIC;
static int ctc_tty_shuttingdown = 0;
static spinlock_t ctc_tty_lock;
/* ctc_tty_try_read() is called from within ctc_tty_rcv_skb()
* to stuff incoming data directly into a tty's flip-buffer. If the
* flip buffer is full, the packet gets queued up.
*
* Return:
* 1 = Success
* 0 = Failure, data has to be buffered and later processed by
* ctc_tty_readmodem().
*/
static int
ctc_tty_try_read(ctc_tty_info * info, struct sk_buff *skb)
{
int c;
int len;
struct tty_struct *tty;
DBF_TEXT(trace, 5, __FUNCTION__);
if ((tty = info->tty)) {
if (info->mcr & UART_MCR_RTS) {
c = TTY_FLIPBUF_SIZE -