patch-2.4.4 linux/drivers/s390/net/ctcmain.c
Next file: linux/drivers/s390/net/ctctty.c
Previous file: linux/drivers/s390/net/ctc.c
Back to the patch index
Back to the overall index
- Lines: 484
- Date:
Wed Apr 18 14:40:07 2001
- Orig file:
v2.4.3/linux/drivers/s390/net/ctcmain.c
- Orig date:
Tue Feb 13 14:13:44 2001
diff -u --recursive --new-file v2.4.3/linux/drivers/s390/net/ctcmain.c linux/drivers/s390/net/ctcmain.c
@@ -1,12 +1,12 @@
/*
- * $Id: ctcmain.c,v 1.11 2000/12/15 19:34:54 bird Exp $
+ * $Id: ctcmain.c,v 1.17 2001/01/23 14:23:51 felfert Exp $
*
* CTC / ESCON network driver
*
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
* Fixes by : Jochen Röhrig (roehrig@de.ibm.com)
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
* Documentation used:
* - Principles of Operation (IBM doc#: SA22-7201-06)
@@ -36,6 +36,26 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: ctcmain.c,v $
+ * Revision 1.17 2001/01/23 14:23:51 felfert
+ * Added ctc based tty.
+ *
+ * Revision 1.16 2001/01/18 16:10:53 felfert
+ * Added fixes by acme@conectiva.com.br.
+ *
+ * Revision 1.15 2001/01/12 15:40:11 felfert
+ * Fixed ITPM# PL030052IME (Unitchecks when using real escon).
+ *
+ * Revision 1.14 2001/01/11 17:43:52 felfert
+ * Fixed ITPM# PL030051IME (Initialization of escon).
+ *
+ * Revision 1.13 2001/01/11 16:40:26 smolinsk
+ * resolved name space conflict with LVM and renamed
+ * dev_info_t to s390_dev_info_t
+ * worked around a bug in OSA microcode by stepping back to 2k IDALS in idals.c
+ *
+ * Revision 1.12 2000/12/27 09:40:45 tonn
+ * upgrade to test12
+ *
* Revision 1.11 2000/12/15 19:34:54 bird
* struct ctc_priv_t: set type of tbusy to "unsigned long"
*
@@ -89,8 +109,6 @@
#include <linux/string.h>
#include <linux/proc_fs.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
#include <linux/ip.h>
#include <linux/if_arp.h>
#include <linux/tcp.h>
@@ -112,6 +130,7 @@
#include <asm/irq.h>
+#include "ctctty.h"
#include "fsm.h"
#ifdef MODULE
@@ -142,7 +161,8 @@
#define CTC_PROTO_S390 0
#define CTC_PROTO_LINUX 1
-#define CTC_PROTO_MAX 1
+#define CTC_PROTO_LINUX_TTY 2
+#define CTC_PROTO_MAX 2
#define CTC_BUFSIZE_LIMIT 65535
#define CTC_BUFSIZE_DEFAULT 32768
@@ -186,19 +206,13 @@
typedef enum channel_types channel_type_t;
-static int ctc_no_auto;
+static int ctc_no_auto = 0;
/**
* If running on 64 bit, this must be changed. XXX Why? (bird)
*/
typedef unsigned long intparm_t;
-#if LINUX_VERSION_CODE < 0x020300
-typedef struct device net_device;
-#else
-typedef struct net_device net_device;
-#endif
-
/**
* Definition of a per device parameter block
*/
@@ -211,7 +225,7 @@
char name[MAX_PARAM_NAME_LEN];
} param;
-static param *params;
+static param *params = NULL;
typedef struct {
unsigned long maxmulti;
@@ -248,7 +262,7 @@
__u32 flags;
/**
- * The protocol of this channel (currently always 0)
+ * The protocol of this channel
*/
__u16 protocol;
@@ -342,7 +356,7 @@
/**
* Linked list of all detected channels.
*/
-static channel *channels;
+static channel *channels = NULL;
typedef struct ctc_priv_t {
struct net_device_stats stats;
@@ -353,6 +367,10 @@
* The finite state machine of this interface.
*/
fsm_instance *fsm;
+ /**
+ * The protocol of this device
+ */
+ __u16 protocol;
channel *channel[2];
struct proc_dir_entry *proc_dentry;
struct proc_dir_entry *proc_stat_entry;
@@ -406,8 +424,8 @@
* Print Banner.
*/
static void print_banner(void) {
- static int printed;
- char vbuf[] = "$Revision: 1.11 $";
+ static int printed = 0;
+ char vbuf[] = "$Revision: 1.17 $";
char *version = vbuf;
if (printed)
@@ -796,7 +814,10 @@
dev_kfree_skb(skb);
goto again;
}
- netif_rx(skb2);
+ if (ch->protocol == CTC_PROTO_LINUX_TTY)
+ ctc_tty_netif_rx(skb2);
+ else
+ netif_rx(skb2);
privptr->stats.rx_packets++;
privptr->stats.rx_bytes += skb2->len;
/**
@@ -805,7 +826,10 @@
skb_pull(skb, header->length);
skb_put(skb, LL_HEADER_LENGTH);
} else {
- netif_rx(skb);
+ if (ch->protocol == CTC_PROTO_LINUX_TTY)
+ ctc_tty_netif_rx(skb);
+ else
+ netif_rx(skb);
privptr->stats.rx_packets++;
privptr->stats.rx_bytes += skb->len;
}
@@ -892,8 +916,10 @@
ch->devno);
fsm_event(ch->fsm, CH_EVENT_UC_TXPARITY, ch);
}
+ } else if (sense & SNS0_CMD_REJECT) {
+ printk(KERN_WARNING "ch-%04x: Command reject\n", ch->devno);
} else if (sense == 0) {
- printk(KERN_DEBUG "ch-%04x: Unit check\n", ch->devno);
+ printk(KERN_DEBUG "ch-%04x: Unit check ZERO\n", ch->devno);
fsm_event(ch->fsm, CH_EVENT_UC_ZERO, ch);
} else {
printk(KERN_WARNING
@@ -1078,15 +1104,15 @@
fsm_deltimer(&ch->timer);
if (len < 8) {
- printk(KERN_WARNING "%s: got packet with length < 8\n",
- dev->name);
+ printk(KERN_WARNING "%s: got packet with length %d < 8\n",
+ dev->name, len);
privptr->stats.rx_dropped++;
privptr->stats.rx_length_errors++;
goto again;
}
if (len > ch->max_bufsize) {
- printk(KERN_WARNING "%s: got packet with length > %d\n",
- dev->name, ch->max_bufsize);
+ printk(KERN_WARNING "%s: got packet with length %d > %d\n",
+ dev->name, len, ch->max_bufsize);
privptr->stats.rx_dropped++;
privptr->stats.rx_length_errors++;
goto again;
@@ -1764,14 +1790,18 @@
channel **c = &channels;
channel *ch;
char name[10];
- int ret = -1;
- if ((ch = (channel *)kmalloc(sizeof(channel), GFP_KERNEL)) == NULL)
- goto out;
+ if ((ch = (channel *)kmalloc(sizeof(channel), GFP_KERNEL)) == NULL) {
+ printk(KERN_WARNING "ctc: Out of memory in add_channel\n");
+ return -1;
+ }
memset(ch, 0, sizeof(channel));
if ((ch->ccw = (ccw1_t *)kmalloc(sizeof(ccw1_t) * 5,
- GFP_KERNEL|GFP_DMA)) == NULL)
- goto out_ch;
+ GFP_KERNEL|GFP_DMA)) == NULL) {
+ kfree(ch);
+ printk(KERN_WARNING "ctc: Out of memory in add_channel\n");
+ return -1;
+ }
/**
* "static" ccws are used in the following way:
@@ -1804,12 +1834,19 @@
ch->fsm = init_fsm(name, ch_state_names,
ch_event_names, NR_CH_STATES, NR_CH_EVENTS,
ch_fsm, CH_FSM_LEN, GFP_KERNEL);
- if (ch->fsm == NULL)
- goto out_ccw;
+ if (ch->fsm == NULL) {
+ printk(KERN_WARNING "ctc: Could not create FSM in add_channel\n");
+ kfree(ch);
+ return -1;
+ }
fsm_newstate(ch->fsm, CH_STATE_IDLE);
if ((ch->devstat = (devstat_t*)kmalloc(sizeof(devstat_t), GFP_KERNEL))
- == NULL)
- goto out_ccw;
+ == NULL) {
+ printk(KERN_WARNING "ctc: Out of memory in add_channel\n");
+ kfree_fsm(ch->fsm);
+ kfree(ch);
+ return -1;
+ }
memset(ch->devstat, 0, sizeof(devstat_t));
while (*c && ((*c)->devno < devno))
c = &(*c)->next;
@@ -1817,8 +1854,10 @@
printk(KERN_DEBUG
"ctc: add_channel: device %04x already in list\n",
(*c)->devno);
- ret = 0;
- goto out_devstat;
+ kfree(ch->devstat);
+ kfree_fsm(ch->fsm);
+ kfree(ch);
+ return 0;
}
fsm_settimer(ch->fsm, &ch->timer);
skb_queue_head_init(&ch->io_queue);
@@ -1826,16 +1865,6 @@
ch->next = *c;
*c = ch;
return 0;
-out_devstat:
- kfree(ch->devstat);
-out_ccw:
- kfree(ch->ccw);
-out_ch:
- kfree(ch);
-out:
- if (ret)
- printk(KERN_WARNING "ctc: Out of memory in add_channel\n");
- return ret;
}
/**
@@ -1846,9 +1875,9 @@
*/
static void channel_scan(int print_result)
{
- int irq;
- int nr_escon = 0;
- int nr_ctca = 0;
+ int irq;
+ int nr_escon = 0;
+ int nr_ctca = 0;
s390_dev_info_t di;
for (irq = 0; irq < NR_IRQS; irq++) {
@@ -2284,6 +2313,8 @@
if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) {
int l = skb->len + LL_HEADER_LENGTH;
+ if (ch->type == channel_type_escon)
+ return -EBUSY;
spin_lock_irqsave(&ch->collect_lock, saveflags);
if (ch->collect_len + l > ch->max_bufsize - 2)
rc = -EBUSY;
@@ -3141,7 +3172,7 @@
*
* @param dev Pointer to net_device to be initialized.
*
- * @return 0 on success, !0 on failure.
+ * @returns 0 on success, !0 on failure.
*/
int ctc_probe(net_device *dev)
{
@@ -3190,6 +3221,7 @@
return -ENOMEM;
memset(dev->priv, 0, sizeof(ctc_priv));
privptr = (ctc_priv *)dev->priv;
+ privptr->protocol = proto;
privptr->proc_dentry = (struct proc_dir_entry *)
(((char *)privptr) + sizeof(ctc_priv));
privptr->proc_stat_entry = (struct proc_dir_entry *)
@@ -3220,7 +3252,6 @@
dev->type = ARPHRD_SLIP;
dev->tx_queue_len = 100;
SET_DEVICE_START(dev, 1);
- dev_init_buffers(dev);
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
for (direction = READ; direction <= WRITE; direction++) {
if ((ctc_no_auto == 0) || (devno[direction] == -1))
@@ -3295,6 +3326,7 @@
void cleanup_module(void) {
channel *c = channels;
+ ctc_tty_cleanup();
/* we are called if all interfaces are down only, so no need
* to bother around with locking stuff
*/
@@ -3313,7 +3345,10 @@
privptr->channel[WRITE]->devstat);
kfree_fsm(privptr->channel[READ]->fsm);
kfree_fsm(privptr->channel[WRITE]->fsm);
- unregister_netdev(nd);
+ if (privptr->protocol != CTC_PROTO_LINUX_TTY)
+ unregister_netdev(nd);
+ else
+ ctc_tty_unregister_netdev(nd);
kfree_fsm(privptr->fsm);
privptr->channel[READ]->netdev = NULL;
privptr->channel[WRITE]->netdev = NULL;
@@ -3345,6 +3380,7 @@
int cnt[2];
int itype;
int activated;
+ int ret = 0;
param *par;
print_banner();
@@ -3359,10 +3395,11 @@
#endif
activated = 0;
par = params;
+ ctc_tty_init();
for (itype = 0; itype < 2; itype++) {
net_device *dev = NULL;
char *bname = (itype) ? "escon" : "ctc";
- int nlen = strlen(bname);
+
cnt[itype] = 0;
do {
dev = kmalloc(sizeof(net_device)
@@ -3370,8 +3407,10 @@
+ 11 /* name + zero */
#endif
, GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
+ if (!dev) {
+ ret = -ENOMEM;
+ break;
+ }
memset(dev, 0, sizeof(net_device));
#if LINUX_VERSION_CODE < 0x020300
dev->name = (unsigned char *)dev + sizeof(net_device);
@@ -3386,10 +3425,10 @@
if (isdigit(*p))
break;
if (p && *p) {
+ int it = (strncmp(dev->name, "escon", 5)) ? 1 : 0;
n = simple_strtoul(p, NULL, 0);
- if (n >= cnt[itype] &&
- (!strncmp(par->name, bname, nlen)))
- cnt[itype] = n + 1;
+ if (n >= cnt[it])
+ cnt[it] = n + 1;
}
} else {
if (ctc_no_auto) {
@@ -3406,6 +3445,7 @@
__FUNCTION__, dev->name);
#endif
if (ctc_probe(dev) == 0) {
+ ctc_priv *privptr = (ctc_priv *)dev->priv;
#ifdef DEBUG
printk(KERN_DEBUG
"ctc: %s(): probing succeeded\n",
@@ -3413,28 +3453,49 @@
printk(KERN_DEBUG
"ctc: %s(): registering device %s\n",
__FUNCTION__, dev->name);
+#endif
+ if (privptr->protocol != CTC_PROTO_LINUX_TTY) {
+ if (register_netdev(dev) != 0) {
+ printk(KERN_WARNING
+ "ctc: Couldn't register netdev %s\n",
+ dev->name);
+ free_irq(privptr->channel[READ]->irq,
+ privptr->channel[READ]->devstat);
+ free_irq(privptr->channel[WRITE]->irq,
+ privptr->channel[WRITE]->devstat);
+ channel_free(privptr->channel[READ]);
+ channel_free(privptr->channel[WRITE]);
+ kfree(dev->priv);
+ kfree(dev);
+ } else {
+#ifdef DEBUG
+ printk(KERN_DEBUG
+ "ctc: %s(): register succeed\n",
+ __FUNCTION__);
#endif
- if (register_netdev(dev) != 0) {
- ctc_priv *privptr =
- (ctc_priv *)dev->priv;
- printk(KERN_WARNING
- "ctc: Couldn't register %s\n",
- dev->name);
- free_irq(privptr->channel[READ]->irq,
- privptr->channel[READ]->devstat);
- free_irq(privptr->channel[WRITE]->irq,
- privptr->channel[WRITE]->devstat);
- channel_free(privptr->channel[READ]);
- channel_free(privptr->channel[WRITE]);
- kfree(dev->priv);
- kfree(dev);
+ activated++;
+ }
} else {
+ if (ctc_tty_register_netdev(dev) != 0) {
+ printk(KERN_WARNING
+ "ctc: Couldn't register ttydev %s\n",
+ dev->name);
+ free_irq(privptr->channel[READ]->irq,
+ privptr->channel[READ]->devstat);
+ free_irq(privptr->channel[WRITE]->irq,
+ privptr->channel[WRITE]->devstat);
+ channel_free(privptr->channel[READ]);
+ channel_free(privptr->channel[WRITE]);
+ kfree(dev->priv);
+ kfree(dev);
+ } else {
#ifdef DEBUG
- printk(KERN_DEBUG
- "ctc: %s(): register succeed\n",
- __FUNCTION__);
+ printk(KERN_DEBUG
+ "ctc: %s(): register succeed\n",
+ __FUNCTION__);
#endif
- activated++;
+ activated++;
+ }
}
} else {
@@ -3446,13 +3507,15 @@
kfree(dev);
dev = NULL;
}
- } while (dev);
+ } while (dev && (ret == 0));
}
if (!activated) {
printk(KERN_WARNING "ctc: No devices registered\n");
- return -ENODEV;
+ ret = -ENODEV;
}
- return 0;
+ if (ret)
+ ctc_tty_cleanup();
+ return ret;
}
#ifndef MODULE
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)