📄 ctcmain.c
字号:
/* * $Id: ctcmain.c,v 1.55 2001/12/03 14:28:45 felfert Exp $ * * CTC / ESCON network driver * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com) * Fixes by : Jochen R鰄rig (roehrig@de.ibm.com) * Arnaldo Carvalho de Melo <acme@conectiva.com.br> * * Documentation used: * - Principles of Operation (IBM doc#: SA22-7201-06) * - Common IO/-Device Commands and Self Description (IBM doc#: SA22-7204-02) * - Common IO/-Device Commands and Self Description (IBM doc#: SN22-5535) * - ESCON Channel-to-Channel Adapter (IBM doc#: SA22-7203-00) * - ESCON I/O Interface (IBM doc#: SA22-7202-029 * * and the source of the original CTC driver by: * Dieter Wellerdiek (wel@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com) * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) * Jochen R鰄rig (roehrig@de.ibm.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. * * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.55 $ * */#include <linux/version.h>#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/interrupt.h>#include <linux/timer.h>#include <linux/sched.h>#include <linux/signal.h>#include <linux/string.h>#include <linux/proc_fs.h>#include <linux/ip.h>#include <linux/if_arp.h>#include <linux/tcp.h>#include <linux/skbuff.h>#include <linux/ctype.h>#include <net/dst.h>#include <asm/io.h>#include <asm/bitops.h>#include <asm/uaccess.h>#ifdef CONFIG_CHANDEV#define CTC_CHANDEV#endif#ifdef CTC_CHANDEV#include <asm/chandev.h>#define REQUEST_IRQ chandev_request_irq#define FREE_IRQ chandev_free_irq#else#define REQUEST_IRQ request_irq#define FREE_IRQ free_irq#endif#if LINUX_VERSION_CODE >= 0x020213# include <asm/idals.h>#else# define set_normalized_cda(ccw, addr) ((ccw)->cda = (addr),0)# define clear_normalized_cda(ccw)#endif#if LINUX_VERSION_CODE < 0x020400# define s390_dev_info_t dev_info_t# define dev_kfree_skb_irq(a) dev_kfree_skb(a)#endif#include <asm/irq.h>#include "ctctty.h"#include "fsm.h"#ifdef MODULEMODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert@millenux.com)");MODULE_DESCRIPTION("Linux for S/390 CTC/Escon Driver");#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,12))MODULE_LICENSE("GPL");#endif#ifndef CTC_CHANDEVMODULE_PARM(ctc, "s");MODULE_PARM_DESC(ctc,"One or more definitions in the same format like the kernel param for ctc.\n""E.g.: ctc0:0x700:0x701:0:ctc1:0x702:0x703:0\n");char *ctc = NULL;#endif#else/** * Number of devices in monolithic (not module) driver version. */#define MAX_STATIC_DEVICES 16#endif /* MODULE */#undef DEBUG/** * CCW commands, used in this driver. */#define CCW_CMD_WRITE 0x01#define CCW_CMD_READ 0x02#define CCW_CMD_SET_EXTENDED 0xc3#define CCW_CMD_PREPARE 0xe3#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#define CTC_TIMEOUT_5SEC 5000#define CTC_INITIAL_BLOCKLEN 2#define READ 0#define WRITE 1/** * Enum for classifying detected devices. */enum channel_types { /** * Device is not a channel. */ channel_type_none, /** * Device is a channel, but we don't know * anything about it. */ channel_type_unknown, /** * Device is a CTC/A. */ channel_type_ctca, /** * Device is a ESCON channel. */ channel_type_escon, /** * Device is an unsupported model. */ channel_type_unsupported};typedef enum channel_types channel_type_t;#ifndef CTC_CHANDEVstatic int ctc_no_auto = 0;#endif/** * If running on 64 bit, this must be changed. XXX Why? (bird) */typedef unsigned long intparm_t;#ifndef CTC_CHANDEV/** * Definition of a per device parameter block */#define MAX_PARAM_NAME_LEN 11typedef struct param_t { struct param_t *next; int read_dev; int write_dev; __u16 proto; char name[MAX_PARAM_NAME_LEN];} param;static param *params = NULL;#endiftypedef struct { unsigned long maxmulti; unsigned long maxcqueue; unsigned long doios_single; unsigned long doios_multi; unsigned long txlen; unsigned long tx_time; struct timeval send_stamp;} ctc_profile;/** * Definition of one channel */typedef struct channel_t { /** * Pointer to next channel in list. */ struct channel_t *next; __u16 devno; int irq; /** * Type of this channel. * CTC/A or Escon for valid channels. */ channel_type_t type; /** * Misc. flags. See CHANNEL_FLAGS_... below */ __u32 flags; /** * The protocol of this channel */ __u16 protocol; /** * I/O and irq related stuff */ ccw1_t *ccw; devstat_t *devstat; /** * Bottom half task queue. */ struct tq_struct tq; /** * RX/TX buffer size */ int max_bufsize; /** * Transmit/Receive buffer. */ struct sk_buff *trans_skb; /** * Universal I/O queue. */ struct sk_buff_head io_queue; /** * TX queue for collecting skb's during busy. */ struct sk_buff_head collect_queue; /** * Amount of data in collect_queue. */ int collect_len; /** * spinlock for collect_queue and collect_len */ spinlock_t collect_lock; /** * Timer for detecting unresposive * I/O operations. */ fsm_timer timer; /** * Retry counter for misc. operations. */ int retry; /** * The finite state machine of this channel */ fsm_instance *fsm; /** * The corresponding net_device this channel * belongs to. */ net_device *netdev; ctc_profile prof; unsigned char *trans_skb_data;} channel;#define CHANNEL_FLAGS_READ 0#define CHANNEL_FLAGS_WRITE 1#define CHANNEL_FLAGS_INUSE 2#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4#define CHANNEL_FLAGS_RWMASK 1#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)/** * Linked list of all detected channels. */static channel *channels = NULL;#ifdef CTC_CHANDEVstatic int activated;#endiftypedef struct ctc_priv_t { struct net_device_stats stats;#if LINUX_VERSION_CODE >= 0x02032D unsigned long tbusy;#endif /** * 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; struct proc_dir_entry *proc_ctrl_entry; int proc_registered;} ctc_priv;/** * Definition of our link level header. */typedef struct ll_header_t { __u16 length; __u16 type; __u16 unused;} ll_header;#define LL_HEADER_LENGTH (sizeof(ll_header))/** * Compatibility macros for busy handling * of network devices. */#if LINUX_VERSION_CODE < 0x02032Dstatic __inline__ void ctc_clear_busy(net_device *dev){ clear_bit(0 ,(void *)&dev->tbusy); mark_bh(NET_BH);}static __inline__ int ctc_test_and_set_busy(net_device *dev){ return(test_and_set_bit(0, (void *)&dev->tbusy));}#define SET_DEVICE_START(device, value) dev->start = value#elsestatic __inline__ void ctc_clear_busy(net_device *dev){ clear_bit(0, &(((ctc_priv *)dev->priv)->tbusy)); netif_wake_queue(dev);}static __inline__ int ctc_test_and_set_busy(net_device *dev){ netif_stop_queue(dev); return test_and_set_bit(0, &((ctc_priv *)dev->priv)->tbusy);}#define SET_DEVICE_START(device, value)#endif/** * Print Banner. */static void print_banner(void) { static int printed = 0; char vbuf[] = "$Revision: 1.55 $"; char *version = vbuf; if (printed) return; if ((version = strchr(version, ':'))) { char *p = strchr(version + 1, '$'); if (p) *p = '\0'; } else version = " ??? "; printk(KERN_INFO "CTC driver Version%swith"#ifndef CTC_CHANDEV "out"#endif " CHANDEV support"#ifdef DEBUG " (DEBUG-VERSION, " __DATE__ __TIME__ ")"#endif " initialized\n", version); printed = 1;}#ifndef CTC_CHANDEV/** * Return type of a detected device. */static channel_type_t channel_type (senseid_t *id) { channel_type_t type = channel_type_none; switch (id->cu_type) { case 0x3088: switch (id->cu_model) { case 0x08: /** * 3088-08 = CTCA */ type = channel_type_ctca; break; case 0x1F: /** * 3088-1F = ESCON channel */ type = channel_type_escon; break; /** * 3088-01 = P390 OSA emulation */ case 0x01: /* fall thru */ /** * 3088-60 = OSA/2 adapter */ case 0x60: /* fall thru */ /** * 3088-61 = CISCO 7206 CLAW proto * on ESCON */ case 0x61: /* fall thru */ /** * 3088-62 = OSA/D device */ case 0x62: type = channel_type_unsupported; break; default: type = channel_type_unknown; printk(KERN_INFO "channel: Unknown model found " "3088-%02x\n", id->cu_model); } break; default: type = channel_type_none; } return type;}#endif/** * States of the interface statemachine. */enum dev_states {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -