ctcmain.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,372 行 · 第 1/5 页
C
2,372 行
/* * $Id: ctcmain.c,v 1.63 2004/07/28 12:27:54 ptiedem 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> * Driver Model stuff by : Cornelia Huck <cohuck@de.ibm.com> * * 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.63 $ * */#undef DEBUG#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/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/ccwdev.h>#include <asm/ccwgroup.h>#include <asm/bitops.h>#include <asm/uaccess.h>#include <asm/idals.h>#include "ctctty.h"#include "fsm.h"#include "cu3088.h"#include "ctcdbug.h"MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert@millenux.com)");MODULE_DESCRIPTION("Linux for S/390 CTC/Escon Driver");MODULE_LICENSE("GPL");/** * 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#define CTC_ID_SIZE BUS_ID_SIZE+3struct ctc_profile { unsigned long maxmulti; unsigned long maxcqueue; unsigned long doios_single; unsigned long doios_multi; unsigned long txlen; unsigned long tx_time; struct timespec send_stamp;};/** * Definition of one channel */struct channel { /** * Pointer to next channel in list. */ struct channel *next; char id[CTC_ID_SIZE]; struct ccw_device *cdev; /** * Type of this channel. * CTC/A or Escon for valid channels. */ enum channel_types type; /** * Misc. flags. See CHANNEL_FLAGS_... below */ __u32 flags; /** * The protocol of this channel */ __u16 protocol; /** * I/O and irq related stuff */ struct ccw1 *ccw; struct irb *irb; /** * 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. */ struct net_device *netdev; struct ctc_profile prof; unsigned char *trans_skb_data; __u16 logflags;};#define CHANNEL_FLAGS_READ 0#define CHANNEL_FLAGS_WRITE 1#define CHANNEL_FLAGS_INUSE 2#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4#define CHANNEL_FLAGS_FAILED 8#define CHANNEL_FLAGS_WAITIRQ 16#define CHANNEL_FLAGS_RWMASK 1#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)#define LOG_FLAG_ILLEGALPKT 1#define LOG_FLAG_ILLEGALSIZE 2#define LOG_FLAG_OVERRUN 4#define LOG_FLAG_NOMEM 8#define CTC_LOGLEVEL_INFO 1#define CTC_LOGLEVEL_NOTICE 2#define CTC_LOGLEVEL_WARN 4#define CTC_LOGLEVEL_EMERG 8#define CTC_LOGLEVEL_ERR 16#define CTC_LOGLEVEL_DEBUG 32#define CTC_LOGLEVEL_CRIT 64#define CTC_LOGLEVEL_DEFAULT \(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT)#define CTC_LOGLEVEL_MAX ((CTC_LOGLEVEL_CRIT<<1)-1)static int loglevel = CTC_LOGLEVEL_DEFAULT;#define ctc_pr_debug(fmt, arg...) \do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0)#define ctc_pr_info(fmt, arg...) \do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0)#define ctc_pr_notice(fmt, arg...) \do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0)#define ctc_pr_warn(fmt, arg...) \do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0)#define ctc_pr_emerg(fmt, arg...) \do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0)#define ctc_pr_err(fmt, arg...) \do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0)#define ctc_pr_crit(fmt, arg...) \do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0)/** * Linked list of all detected channels. */static struct channel *channels = NULL;struct ctc_priv { struct net_device_stats stats; unsigned long tbusy; /** * The finite state machine of this interface. */ fsm_instance *fsm; /** * The protocol of this device */ __u16 protocol; /** * Timer for restarting after I/O Errors */ fsm_timer restart_timer; struct channel *channel[2];};/** * Definition of our link level header. */struct ll_header { __u16 length; __u16 type; __u16 unused;};#define LL_HEADER_LENGTH (sizeof(struct ll_header))/** * Compatibility macros for busy handling * of network devices. */static __inline__ voidctc_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);}static __inline__ intctc_test_and_set_busy(struct net_device * dev){ if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) netif_stop_queue(dev); return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);}/** * Print Banner. */static voidprint_banner(void){ static int printed = 0; char vbuf[] = "$Revision: 1.63 $"; 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%s"#ifdef DEBUG " (DEBUG-VERSION, " __DATE__ __TIME__ ")"#endif " initialized\n", version); printed = 1;}/** * Return type of a detected device. */static enum channel_typesget_channel_type(struct ccw_device_id *id){ enum channel_types type = (enum channel_types) id->driver_info; if (type == channel_type_ficon) type = channel_type_escon; return type;}/** * States of the interface statemachine. */enum dev_states { DEV_STATE_STOPPED, DEV_STATE_STARTWAIT_RXTX, DEV_STATE_STARTWAIT_RX, DEV_STATE_STARTWAIT_TX, DEV_STATE_STOPWAIT_RXTX, DEV_STATE_STOPWAIT_RX, DEV_STATE_STOPWAIT_TX, DEV_STATE_RUNNING, /** * MUST be always the last element!! */ NR_DEV_STATES};static const char *dev_state_names[] = { "Stopped", "StartWait RXTX", "StartWait RX", "StartWait TX", "StopWait RXTX", "StopWait RX", "StopWait TX", "Running",};/** * Events of the interface statemachine. */enum dev_events { DEV_EVENT_START, DEV_EVENT_STOP, DEV_EVENT_RXUP, DEV_EVENT_TXUP, DEV_EVENT_RXDOWN, DEV_EVENT_TXDOWN, DEV_EVENT_RESTART, /** * MUST be always the last element!! */ NR_DEV_EVENTS};static const char *dev_event_names[] = { "Start", "Stop", "RX up", "TX up", "RX down", "TX down", "Restart",};/** * Events of the channel statemachine */enum ch_events { /** * Events, representing return code of * I/O operations (ccw_device_start, ccw_device_halt et al.) */ CH_EVENT_IO_SUCCESS, CH_EVENT_IO_EBUSY, CH_EVENT_IO_ENODEV, CH_EVENT_IO_EIO, CH_EVENT_IO_UNKNOWN, CH_EVENT_ATTNBUSY, CH_EVENT_ATTN, CH_EVENT_BUSY, /** * Events, representing unit-check */ CH_EVENT_UC_RCRESET, CH_EVENT_UC_RSRESET, CH_EVENT_UC_TXTIMEOUT, CH_EVENT_UC_TXPARITY, CH_EVENT_UC_HWFAIL, CH_EVENT_UC_RXPARITY, CH_EVENT_UC_ZERO, CH_EVENT_UC_UNKNOWN, /** * Events, representing subchannel-check */ CH_EVENT_SC_UNKNOWN, /** * Events, representing machine checks */ CH_EVENT_MC_FAIL, CH_EVENT_MC_GOOD, /** * Event, representing normal IRQ */ CH_EVENT_IRQ, CH_EVENT_FINSTAT, /** * Event, representing timer expiry. */ CH_EVENT_TIMER, /** * Events, representing commands from upper levels. */ CH_EVENT_START, CH_EVENT_STOP, /** * MUST be always the last element!! */ NR_CH_EVENTS,};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?