diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/crypto/z90crypt.h | 185 | ||||
-rw-r--r-- | drivers/s390/net/Makefile | 3 | ||||
-rw-r--r-- | drivers/s390/net/ctcmain.c | 45 | ||||
-rw-r--r-- | drivers/s390/net/ctcmain.h | 12 | ||||
-rw-r--r-- | drivers/s390/net/ctctty.c | 1259 | ||||
-rw-r--r-- | drivers/s390/net/ctctty.h | 35 |
6 files changed, 18 insertions, 1521 deletions
diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h index 5e6b1f535f6..0ca1d126ccb 100644 --- a/drivers/s390/crypto/z90crypt.h +++ b/drivers/s390/crypto/z90crypt.h @@ -1,7 +1,7 @@ /* * linux/drivers/s390/crypto/z90crypt.h * - * z90crypt 1.3.3 + * z90crypt 1.3.3 (kernel-private header) * * Copyright (C) 2001, 2005 IBM Corporation * Author(s): Robert Burroughs (burrough@us.ibm.com) @@ -27,188 +27,7 @@ #ifndef _Z90CRYPT_H_ #define _Z90CRYPT_H_ -#include <linux/ioctl.h> - -#define z90crypt_VERSION 1 -#define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards -#define z90crypt_VARIANT 3 // 3 = CEX2A support - -/** - * struct ica_rsa_modexpo - * - * Requirements: - * - outputdatalength is at least as large as inputdatalength. - * - All key parts are right justified in their fields, padded on - * the left with zeroes. - * - length(b_key) = inputdatalength - * - length(n_modulus) = inputdatalength - */ -struct ica_rsa_modexpo { - char __user * inputdata; - unsigned int inputdatalength; - char __user * outputdata; - unsigned int outputdatalength; - char __user * b_key; - char __user * n_modulus; -}; - -/** - * struct ica_rsa_modexpo_crt - * - * Requirements: - * - inputdatalength is even. - * - outputdatalength is at least as large as inputdatalength. - * - All key parts are right justified in their fields, padded on - * the left with zeroes. - * - length(bp_key) = inputdatalength/2 + 8 - * - length(bq_key) = inputdatalength/2 - * - length(np_key) = inputdatalength/2 + 8 - * - length(nq_key) = inputdatalength/2 - * - length(u_mult_inv) = inputdatalength/2 + 8 - */ -struct ica_rsa_modexpo_crt { - char __user * inputdata; - unsigned int inputdatalength; - char __user * outputdata; - unsigned int outputdatalength; - char __user * bp_key; - char __user * bq_key; - char __user * np_prime; - char __user * nq_prime; - char __user * u_mult_inv; -}; - -#define Z90_IOCTL_MAGIC 'z' // NOTE: Need to allocate from linux folks - -/** - * Interface notes: - * - * The ioctl()s which are implemented (along with relevant details) - * are: - * - * ICARSAMODEXPO - * Perform an RSA operation using a Modulus-Exponent pair - * This takes an ica_rsa_modexpo struct as its arg. - * - * NOTE: please refer to the comments preceding this structure - * for the implementation details for the contents of the - * block - * - * ICARSACRT - * Perform an RSA operation using a Chinese-Remainder Theorem key - * This takes an ica_rsa_modexpo_crt struct as its arg. - * - * NOTE: please refer to the comments preceding this structure - * for the implementation details for the contents of the - * block - * - * Z90STAT_TOTALCOUNT - * Return an integer count of all device types together. - * - * Z90STAT_PCICACOUNT - * Return an integer count of all PCICAs. - * - * Z90STAT_PCICCCOUNT - * Return an integer count of all PCICCs. - * - * Z90STAT_PCIXCCMCL2COUNT - * Return an integer count of all MCL2 PCIXCCs. - * - * Z90STAT_PCIXCCMCL3COUNT - * Return an integer count of all MCL3 PCIXCCs. - * - * Z90STAT_CEX2CCOUNT - * Return an integer count of all CEX2Cs. - * - * Z90STAT_CEX2ACOUNT - * Return an integer count of all CEX2As. - * - * Z90STAT_REQUESTQ_COUNT - * Return an integer count of the number of entries waiting to be - * sent to a device. - * - * Z90STAT_PENDINGQ_COUNT - * Return an integer count of the number of entries sent to a - * device awaiting the reply. - * - * Z90STAT_TOTALOPEN_COUNT - * Return an integer count of the number of open file handles. - * - * Z90STAT_DOMAIN_INDEX - * Return the integer value of the Cryptographic Domain. - * - * Z90STAT_STATUS_MASK - * Return an 64 element array of unsigned chars for the status of - * all devices. - * 0x01: PCICA - * 0x02: PCICC - * 0x03: PCIXCC_MCL2 - * 0x04: PCIXCC_MCL3 - * 0x05: CEX2C - * 0x06: CEX2A - * 0x0d: device is disabled via the proc filesystem - * - * Z90STAT_QDEPTH_MASK - * Return an 64 element array of unsigned chars for the queue - * depth of all devices. - * - * Z90STAT_PERDEV_REQCNT - * Return an 64 element array of unsigned integers for the number - * of successfully completed requests per device since the device - * was detected and made available. - * - * ICAZ90STATUS (deprecated) - * Return some device driver status in a ica_z90_status struct - * This takes an ica_z90_status struct as its arg. - * - * NOTE: this ioctl() is deprecated, and has been replaced with - * single ioctl()s for each type of status being requested - * - * Z90STAT_PCIXCCCOUNT (deprecated) - * Return an integer count of all PCIXCCs (MCL2 + MCL3). - * This is DEPRECATED now that MCL3 PCIXCCs are treated differently from - * MCL2 PCIXCCs. - * - * Z90QUIESCE (not recommended) - * Quiesce the driver. This is intended to stop all new - * requests from being processed. Its use is NOT recommended, - * except in circumstances where there is no other way to stop - * callers from accessing the driver. Its original use was to - * allow the driver to be "drained" of work in preparation for - * a system shutdown. - * - * NOTE: once issued, this ban on new work cannot be undone - * except by unloading and reloading the driver. - */ - -/** - * Supported ioctl calls - */ -#define ICARSAMODEXPO _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x05, 0) -#define ICARSACRT _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x06, 0) - -/* DEPRECATED status calls (bound for removal at some point) */ -#define ICAZ90STATUS _IOR(Z90_IOCTL_MAGIC, 0x10, struct ica_z90_status) -#define Z90STAT_PCIXCCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x43, int) - -/* unrelated to ICA callers */ -#define Z90QUIESCE _IO(Z90_IOCTL_MAGIC, 0x11) - -/* New status calls */ -#define Z90STAT_TOTALCOUNT _IOR(Z90_IOCTL_MAGIC, 0x40, int) -#define Z90STAT_PCICACOUNT _IOR(Z90_IOCTL_MAGIC, 0x41, int) -#define Z90STAT_PCICCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x42, int) -#define Z90STAT_PCIXCCMCL2COUNT _IOR(Z90_IOCTL_MAGIC, 0x4b, int) -#define Z90STAT_PCIXCCMCL3COUNT _IOR(Z90_IOCTL_MAGIC, 0x4c, int) -#define Z90STAT_CEX2CCOUNT _IOR(Z90_IOCTL_MAGIC, 0x4d, int) -#define Z90STAT_CEX2ACOUNT _IOR(Z90_IOCTL_MAGIC, 0x4e, int) -#define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int) -#define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int) -#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int) -#define Z90STAT_DOMAIN_INDEX _IOR(Z90_IOCTL_MAGIC, 0x47, int) -#define Z90STAT_STATUS_MASK _IOR(Z90_IOCTL_MAGIC, 0x48, char[64]) -#define Z90STAT_QDEPTH_MASK _IOR(Z90_IOCTL_MAGIC, 0x49, char[64]) -#define Z90STAT_PERDEV_REQCNT _IOR(Z90_IOCTL_MAGIC, 0x4a, int[64]) +#include <asm/z90crypt.h> /** * local errno definitions diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile index 90d4d0ef3dd..6775a837d64 100644 --- a/drivers/s390/net/Makefile +++ b/drivers/s390/net/Makefile @@ -2,7 +2,7 @@ # S/390 network devices # -ctc-objs := ctcmain.o ctctty.o ctcdbug.o +ctc-objs := ctcmain.o ctcdbug.o obj-$(CONFIG_IUCV) += iucv.o obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o @@ -10,6 +10,7 @@ obj-$(CONFIG_SMSGIUCV) += smsgiucv.o obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o obj-$(CONFIG_LCS) += lcs.o cu3088.o obj-$(CONFIG_CLAW) += claw.o cu3088.o +obj-$(CONFIG_MPC) += ctcmpc.o fsm.o cu3088.o qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o qeth-$(CONFIG_PROC_FS) += qeth_proc.o obj-$(CONFIG_QETH) += qeth.o diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index fe986af884f..20c8eb16f46 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c @@ -6,7 +6,7 @@ * Fixes by : Jochen Röhrig (roehrig@de.ibm.com) * Arnaldo Carvalho de Melo <acme@conectiva.com.br> Peter Tiedemann (ptiedem@de.ibm.com) - * Driver Model stuff by : Cornelia Huck <huckc@de.ibm.com> + * Driver Model stuff by : Cornelia Huck <cornelia.huck@de.ibm.com> * * Documentation used: * - Principles of Operation (IBM doc#: SA22-7201-06) @@ -65,7 +65,6 @@ #include <asm/idals.h> -#include "ctctty.h" #include "fsm.h" #include "cu3088.h" @@ -479,10 +478,7 @@ ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb) skb->dev = pskb->dev; skb->protocol = pskb->protocol; pskb->ip_summed = CHECKSUM_UNNECESSARY; - if (ch->protocol == CTC_PROTO_LINUX_TTY) - ctc_tty_netif_rx(skb); - else - netif_rx_ni(skb); + netif_rx_ni(skb); /** * Successful rx; reset logflags */ @@ -557,8 +553,7 @@ ccw_unit_check(struct channel *ch, unsigned char sense) DBF_TEXT(trace, 5, __FUNCTION__); if (sense & SNS0_INTERVENTION_REQ) { if (sense & 0x01) { - if (ch->protocol != CTC_PROTO_LINUX_TTY) - ctc_pr_debug("%s: Interface disc. or Sel. reset " + ctc_pr_debug("%s: Interface disc. or Sel. reset " "(remote)\n", ch->id); fsm_event(ch->fsm, CH_EVENT_UC_RCRESET, ch); } else { @@ -2034,7 +2029,6 @@ static void dev_action_chup(fsm_instance * fi, int event, void *arg) { struct net_device *dev = (struct net_device *) arg; - struct ctc_priv *privptr = dev->priv; DBF_TEXT(trace, 3, __FUNCTION__); switch (fsm_getstate(fi)) { @@ -2049,8 +2043,6 @@ dev_action_chup(fsm_instance * fi, int event, void *arg) fsm_newstate(fi, DEV_STATE_RUNNING); ctc_pr_info("%s: connected with remote side\n", dev->name); - if (privptr->protocol == CTC_PROTO_LINUX_TTY) - ctc_tty_setcarrier(dev, 1); ctc_clear_busy(dev); } break; @@ -2059,8 +2051,6 @@ dev_action_chup(fsm_instance * fi, int event, void *arg) fsm_newstate(fi, DEV_STATE_RUNNING); ctc_pr_info("%s: connected with remote side\n", dev->name); - if (privptr->protocol == CTC_PROTO_LINUX_TTY) - ctc_tty_setcarrier(dev, 1); ctc_clear_busy(dev); } break; @@ -2086,14 +2076,10 @@ dev_action_chup(fsm_instance * fi, int event, void *arg) static void dev_action_chdown(fsm_instance * fi, int event, void *arg) { - struct net_device *dev = (struct net_device *) arg; - struct ctc_priv *privptr = dev->priv; DBF_TEXT(trace, 3, __FUNCTION__); switch (fsm_getstate(fi)) { case DEV_STATE_RUNNING: - if (privptr->protocol == CTC_PROTO_LINUX_TTY) - ctc_tty_setcarrier(dev, 0); if (event == DEV_EVENT_TXDOWN) fsm_newstate(fi, DEV_STATE_STARTWAIT_TX); else @@ -2397,8 +2383,6 @@ ctc_tx(struct sk_buff *skb, struct net_device * dev) */ if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) { fsm_event(privptr->fsm, DEV_EVENT_START, dev); - if (privptr->protocol == CTC_PROTO_LINUX_TTY) - return -EBUSY; dev_kfree_skb(skb); privptr->stats.tx_dropped++; privptr->stats.tx_errors++; @@ -2608,20 +2592,13 @@ ctc_netdev_unregister(struct net_device * dev) if (!dev) return; privptr = (struct ctc_priv *) dev->priv; - if (privptr->protocol != CTC_PROTO_LINUX_TTY) - unregister_netdev(dev); - else - ctc_tty_unregister_netdev(dev); + unregister_netdev(dev); } static int ctc_netdev_register(struct net_device * dev) { - struct ctc_priv *privptr = (struct ctc_priv *) dev->priv; - if (privptr->protocol != CTC_PROTO_LINUX_TTY) - return register_netdev(dev); - else - return ctc_tty_register_netdev(dev); + return register_netdev(dev); } static void @@ -2667,7 +2644,9 @@ ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *b if (!priv) return -ENODEV; sscanf(buf, "%u", &value); - if ((value < 0) || (value > CTC_PROTO_MAX)) + if (!((value == CTC_PROTO_S390) || + (value == CTC_PROTO_LINUX) || + (value == CTC_PROTO_OS390))) return -EINVAL; priv->protocol = value; @@ -2897,10 +2876,7 @@ ctc_new_device(struct ccwgroup_device *cgdev) goto out; } - if (privptr->protocol == CTC_PROTO_LINUX_TTY) - strlcpy(dev->name, "ctctty%d", IFNAMSIZ); - else - strlcpy(dev->name, "ctc%d", IFNAMSIZ); + strlcpy(dev->name, "ctc%d", IFNAMSIZ); for (direction = READ; direction <= WRITE; direction++) { privptr->channel[direction] = @@ -3046,7 +3022,6 @@ ctc_exit(void) { DBF_TEXT(setup, 3, __FUNCTION__); unregister_cu3088_discipline(&ctc_group_driver); - ctc_tty_cleanup(); ctc_unregister_dbf_views(); ctc_pr_info("CTC driver unloaded\n"); } @@ -3073,10 +3048,8 @@ ctc_init(void) ctc_pr_crit("ctc_init failed with ctc_register_dbf_views rc = %d\n", ret); return ret; } - ctc_tty_init(); ret = register_cu3088_discipline(&ctc_group_driver); if (ret) { - ctc_tty_cleanup(); ctc_unregister_dbf_views(); } return ret; diff --git a/drivers/s390/net/ctcmain.h b/drivers/s390/net/ctcmain.h index d2e835c0c13..7f305d119f3 100644 --- a/drivers/s390/net/ctcmain.h +++ b/drivers/s390/net/ctcmain.h @@ -35,7 +35,9 @@ #include <asm/ccwdev.h> #include <asm/ccwgroup.h> -#include "ctctty.h" +#include <linux/skbuff.h> +#include <linux/netdevice.h> + #include "fsm.h" #include "cu3088.h" @@ -50,9 +52,7 @@ #define CTC_PROTO_S390 0 #define CTC_PROTO_LINUX 1 -#define CTC_PROTO_LINUX_TTY 2 #define CTC_PROTO_OS390 3 -#define CTC_PROTO_MAX 3 #define CTC_BUFSIZE_LIMIT 65535 #define CTC_BUFSIZE_DEFAULT 32768 @@ -257,15 +257,13 @@ static __inline__ void ctc_clear_busy(struct net_device * dev) { clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy)); - if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) - netif_wake_queue(dev); + netif_wake_queue(dev); } static __inline__ int ctc_test_and_set_busy(struct net_device * dev) { - if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) - netif_stop_queue(dev); + netif_stop_queue(dev); return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy); } diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c deleted file mode 100644 index af54d1de07b..00000000000 --- a/drivers/s390/net/ctctty.c +++ /dev/null @@ -1,1259 +0,0 @@ -/* - * 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/tty_flip.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 len; - struct tty_struct *tty; - - DBF_TEXT(trace, 5, __FUNCTION__); - if ((tty = info->tty)) { - if (info->mcr & UART_MCR_RTS) { - len = skb->len; - tty_insert_flip_string(tty, skb->data, len); - tty_flip_buffer_push(tty); - kfree_skb(skb); - return 1; - } - } - return 0; -} - -/* ctc_tty_readmodem() is called periodically from within timer-interrupt. - * It tries getting received data from the receive queue an stuff it into - * the tty's flip-buffer. - */ -static int -ctc_tty_readmodem(ctc_tty_info *info) -{ - int ret = 1; - struct tty_struct *tty; - - DBF_TEXT(trace, 5, __FUNCTION__); - if ((tty = info->tty)) { - if (info->mcr & UART_MCR_RTS) { - struct sk_buff *skb; - - if ((skb = skb_dequeue(&info->rx_queue))) { - int len = skb->len; - tty_insert_flip_string(tty, skb->data, len); - skb_pull(skb, len); - tty_flip_buffer_push(tty); - if (skb->len > 0) - skb_queue_head(&info->rx_queue, skb); - else { - kfree_skb(skb); - ret = !skb_queue_empty(&info->rx_queue); - } - } - } - } - return ret; -} - -void -ctc_tty_setcarrier(struct net_device *netdev, int on) -{ - int i; - - DBF_TEXT(trace, 4, __FUNCTION__); - if ((!driver) || ctc_tty_shuttingdown) - return; - for (i = 0; i < CTC_TTY_MAX_DEVICES; i++) - if (driver->info[i].netdev == netdev) { - ctc_tty_info *info = &driver->info[i]; - if (on) - info->msr |= UART_MSR_DCD; - else - info->msr &= ~UART_MSR_DCD; - if ((info->flags & CTC_ASYNC_CHECK_CD) && (!on)) - tty_hangup(info->tty); - } -} - -void -ctc_tty_netif_rx(struct sk_buff *skb) -{ - int i; - ctc_tty_info *info = NULL; - - DBF_TEXT(trace, 5, __FUNCTION__); - if (!skb) - return; - if ((!skb->dev) || (!driver) || ctc_tty_shuttingdown) { - dev_kfree_skb(skb); - return; - } - for (i = 0; i < CTC_TTY_MAX_DEVICES; i++) - if (driver->info[i].netdev == skb->dev) { - info = &driver->info[i]; - break; - } - if (!info) { - dev_kfree_skb(skb); - return; - } - if (skb->len < 6) { - dev_kfree_skb(skb); - return; - } - if (memcmp(skb->data, &ctc_tty_magic, sizeof(__u32))) { - dev_kfree_skb(skb); - return; - } - skb_pull(skb, sizeof(__u32)); - - i = *((int *)skb->data); - skb_pull(skb, sizeof(info->mcr)); - if (i & UART_MCR_RTS) { - info->msr |= UART_MSR_CTS; - if (info->flags & CTC_ASYNC_CTS_FLOW) - info->tty->hw_stopped = 0; - } else { - info->msr &= ~UART_MSR_CTS; - if (info->flags & CTC_ASYNC_CTS_FLOW) - info->tty->hw_stopped = 1; - } - if (i & UART_MCR_DTR) - info->msr |= UART_MSR_DSR; - else - info->msr &= ~UART_MSR_DSR; - if (skb->len <= 0) { - kfree_skb(skb); - return; - } - /* Try to deliver directly via tty-flip-buf if queue is empty */ - if (skb_queue_empty(&info->rx_queue)) - if (ctc_tty_try_read(info, skb)) - return; - /* Direct deliver failed or queue wasn't empty. - * Queue up for later dequeueing via timer-irq. - */ - skb_queue_tail(&info->rx_queue, skb); - /* Schedule dequeuing */ - tasklet_schedule(&info->tasklet); -} - -static int -ctc_tty_tint(ctc_tty_info * info) -{ - struct sk_buff *skb = skb_dequeue(&info->tx_queue); - int stopped = (info->tty->hw_stopped || info->tty->stopped); - int wake = 1; - int rc; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (!info->netdev) { - if (skb) - kfree_skb(skb); - return 0; - } - if (info->flags & CTC_ASYNC_TX_LINESTAT) { - int skb_res = info->netdev->hard_header_len + - sizeof(info->mcr) + sizeof(__u32); - /* If we must update line status, - * create an empty dummy skb and insert it. - */ - if (skb) - skb_queue_head(&info->tx_queue, skb); - - skb = dev_alloc_skb(skb_res); - if (!skb) { - printk(KERN_WARNING - "ctc_tty: Out of memory in %s%d tint\n", - CTC_TTY_NAME, info->line); - return 1; - } - skb_reserve(skb, skb_res); - stopped = 0; - wake = 0; - } - if (!skb) - return 0; - if (stopped) { - skb_queue_head(&info->tx_queue, skb); - return 1; - } -#if 0 - if (skb->len > 0) - printk(KERN_DEBUG "tint: %d %02x\n", skb->len, *(skb->data)); - else - printk(KERN_DEBUG "tint: %d STAT\n", skb->len); -#endif - memcpy(skb_push(skb, sizeof(info->mcr)), &info->mcr, sizeof(info->mcr)); - memcpy(skb_push(skb, sizeof(__u32)), &ctc_tty_magic, sizeof(__u32)); - rc = info->netdev->hard_start_xmit(skb, info->netdev); - if (rc) { - skb_pull(skb, sizeof(info->mcr) + sizeof(__u32)); - if (skb->len > 0) - skb_queue_head(&info->tx_queue, skb); - else - kfree_skb(skb); - } else { - struct tty_struct *tty = info->tty; - - info->flags &= ~CTC_ASYNC_TX_LINESTAT; - if (tty) { - tty_wakeup(tty); - } - } - return (skb_queue_empty(&info->tx_queue) ? 0 : 1); -} - -/************************************************************ - * - * Modem-functions - * - * mostly "stolen" from original Linux-serial.c and friends. - * - ************************************************************/ - -static inline int -ctc_tty_paranoia_check(ctc_tty_info * info, char *name, const char *routine) -{ -#ifdef MODEM_PARANOIA_CHECK - if (!info) { - printk(KERN_WARNING "ctc_tty: null info_struct for %s in %s\n", - name, routine); - return 1; - } - if (info->magic != CTC_ASYNC_MAGIC) { - printk(KERN_WARNING "ctc_tty: bad magic for info struct %s in %s\n", - name, routine); - return 1; - } -#endif - return 0; -} - -static void -ctc_tty_inject(ctc_tty_info *info, char c) -{ - int skb_res; - struct sk_buff *skb; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (ctc_tty_shuttingdown) - return; - skb_res = info->netdev->hard_header_len + sizeof(info->mcr) + - sizeof(__u32) + 1; - skb = dev_alloc_skb(skb_res); - if (!skb) { - printk(KERN_WARNING - "ctc_tty: Out of memory in %s%d tx_inject\n", - CTC_TTY_NAME, info->line); - return; - } - skb_reserve(skb, skb_res); - *(skb_put(skb, 1)) = c; - skb_queue_head(&info->tx_queue, skb); - tasklet_schedule(&info->tasklet); -} - -static void -ctc_tty_transmit_status(ctc_tty_info *info) -{ - DBF_TEXT(trace, 5, __FUNCTION__); - if (ctc_tty_shuttingdown) - return; - info->flags |= CTC_ASYNC_TX_LINESTAT; - tasklet_schedule(&info->tasklet); -} - -static void -ctc_tty_change_speed(ctc_tty_info * info) -{ - unsigned int cflag; - unsigned int quot; - int i; - - DBF_TEXT(trace, 3, __FUNCTION__); - if (!info->tty || !info->tty->termios) - return; - cflag = info->tty->termios->c_cflag; - - quot = i = cflag & CBAUD; - if (i & CBAUDEX) { - i &= ~CBAUDEX; - if (i < 1 || i > 2) - info->tty->termios->c_cflag &= ~CBAUDEX; - else - i += 15; - } - if (quot) { - info->mcr |= UART_MCR_DTR; - info->mcr |= UART_MCR_RTS; - ctc_tty_transmit_status(info); - } else { - info->mcr &= ~UART_MCR_DTR; - info->mcr &= ~UART_MCR_RTS; - ctc_tty_transmit_status(info); - return; - } - - /* CTS flow control flag and modem status interrupts */ - if (cflag & CRTSCTS) { - info->flags |= CTC_ASYNC_CTS_FLOW; - } else - info->flags &= ~CTC_ASYNC_CTS_FLOW; - if (cflag & CLOCAL) - info->flags &= ~CTC_ASYNC_CHECK_CD; - else { - info->flags |= CTC_ASYNC_CHECK_CD; - } -} - -static int -ctc_tty_startup(ctc_tty_info * info) -{ - DBF_TEXT(trace, 3, __FUNCTION__); - if (info->flags & CTC_ASYNC_INITIALIZED) - return 0; -#ifdef CTC_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "starting up %s%d ...\n", CTC_TTY_NAME, info->line); -#endif - /* - * Now, initialize the UART - */ - info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); - /* - * and set the speed of the serial port - */ - ctc_tty_change_speed(info); - - info->flags |= CTC_ASYNC_INITIALIZED; - if (!(info->flags & CTC_ASYNC_NETDEV_OPEN)) - info->netdev->open(info->netdev); - info->flags |= CTC_ASYNC_NETDEV_OPEN; - return 0; -} - -static void -ctc_tty_stopdev(unsigned long data) -{ - ctc_tty_info *info = (ctc_tty_info *)data; - - if ((!info) || (!info->netdev) || - (info->flags & CTC_ASYNC_INITIALIZED)) - return; - info->netdev->stop(info->netdev); - info->flags &= ~CTC_ASYNC_NETDEV_OPEN; -} - -/* - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - */ -static void -ctc_tty_shutdown(ctc_tty_info * info) -{ - DBF_TEXT(trace, 3, __FUNCTION__); - if (!(info->flags & CTC_ASYNC_INITIALIZED)) - return; -#ifdef CTC_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "Shutting down %s%d ....\n", CTC_TTY_NAME, info->line); -#endif - info->msr &= ~UART_MSR_RI; - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) - info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS); - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - mod_timer(&info->stoptimer, jiffies + (10 * HZ)); - skb_queue_purge(&info->tx_queue); - skb_queue_purge(&info->rx_queue); - info->flags &= ~CTC_ASYNC_INITIALIZED; -} - -/* ctc_tty_write() is the main send-routine. It is called from the upper - * levels within the kernel to perform sending data. Depending on the - * online-flag it either directs output to the at-command-interpreter or - * to the lower level. Additional tasks done here: - * - If online, check for escape-sequence (+++) - * - If sending audio-data, call ctc_tty_DLEdown() to parse DLE-codes. - * - If receiving audio-data, call ctc_tty_end_vrx() to abort if needed. - * - If dialing, abort dial. - */ -static int -ctc_tty_write(struct tty_struct *tty, const u_char * buf, int count) -{ - int c; - int total = 0; - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - - DBF_TEXT(trace, 5, __FUNCTION__); - if (ctc_tty_shuttingdown) - goto ex; - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write")) - goto ex; - if (!tty) - goto ex; - if (!info->netdev) { - total = -ENODEV; - goto ex; - } - while (1) { - struct sk_buff *skb; - int skb_res; - - c = (count < CTC_TTY_XMIT_SIZE) ? count : CTC_TTY_XMIT_SIZE; - if (c <= 0) - break; - - skb_res = info->netdev->hard_header_len + sizeof(info->mcr) + - + sizeof(__u32); - skb = dev_alloc_skb(skb_res + c); - if (!skb) { - printk(KERN_WARNING - "ctc_tty: Out of memory in %s%d write\n", - CTC_TTY_NAME, info->line); - break; - } - skb_reserve(skb, skb_res); - memcpy(skb_put(skb, c), buf, c); - skb_queue_tail(&info->tx_queue, skb); - buf += c; - total += c; - count -= c; - } - if (!skb_queue_empty(&info->tx_queue)) { - info->lsr &= ~UART_LSR_TEMT; - tasklet_schedule(&info->tasklet); - } -ex: - DBF_TEXT(trace, 6, __FUNCTION__); - return total; -} - -static int -ctc_tty_write_room(struct tty_struct *tty) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write_room")) - return 0; - return CTC_TTY_XMIT_SIZE; -} - -static int -ctc_tty_chars_in_buffer(struct tty_struct *tty) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_chars_in_buffer")) - return 0; - return 0; -} - -static void -ctc_tty_flush_buffer(struct tty_struct *tty) -{ - ctc_tty_info *info; - unsigned long flags; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (!tty) - goto ex; - spin_lock_irqsave(&ctc_tty_lock, flags); - info = (ctc_tty_info *) tty->driver_data; - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_buffer")) { - spin_unlock_irqrestore(&ctc_tty_lock, flags); - goto ex; - } - skb_queue_purge(&info->tx_queue); - info->lsr |= UART_LSR_TEMT; - spin_unlock_irqrestore(&ctc_tty_lock, flags); - wake_up_interruptible(&tty->write_wait); - tty_wakeup(tty); -ex: - DBF_TEXT_(trace, 2, "ex: %s ", __FUNCTION__); - return; -} - -static void -ctc_tty_flush_chars(struct tty_struct *tty) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (ctc_tty_shuttingdown) - return; - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_chars")) - return; - if (tty->stopped || tty->hw_stopped || skb_queue_empty(&info->tx_queue)) - return; - tasklet_schedule(&info->tasklet); -} - -/* - * ------------------------------------------------------------ - * ctc_tty_throttle() - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - * ------------------------------------------------------------ - */ -static void -ctc_tty_throttle(struct tty_struct *tty) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_throttle")) - return; - info->mcr &= ~UART_MCR_RTS; - if (I_IXOFF(tty)) - ctc_tty_inject(info, STOP_CHAR(tty)); - ctc_tty_transmit_status(info); -} - -static void -ctc_tty_unthrottle(struct tty_struct *tty) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_unthrottle")) - return; - info->mcr |= UART_MCR_RTS; - if (I_IXOFF(tty)) - ctc_tty_inject(info, START_CHAR(tty)); - ctc_tty_transmit_status(info); -} - -/* - * ------------------------------------------------------------ - * ctc_tty_ioctl() and friends - * ------------------------------------------------------------ - */ - -/* - * ctc_tty_get_lsr_info - get line status register info - * - * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows RS485 driver to be written in user space. - */ -static int -ctc_tty_get_lsr_info(ctc_tty_info * info, uint __user *value) -{ - u_char status; - uint result; - ulong flags; - - DBF_TEXT(trace, 4, __FUNCTION__); - spin_lock_irqsave(&ctc_tty_lock, flags); - status = info->lsr; - spin_unlock_irqrestore(&ctc_tty_lock, flags); - result = ((statu |