⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ctcmain.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic 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>	      Peter Tiedemann (ptiedem@de.ibm.com) * 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.78 $ * */#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/bitops.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/uaccess.h>#include <asm/idals.h>#include "ctctty.h"#include "fsm.h"#include "cu3088.h"#include "ctcdbug.h"#include "ctcmain.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");/** * 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!!	 */	CTC_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!!	 */	CTC_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,};/** * States of the channel statemachine. */enum ch_states {	/**	 * Channel not assigned to any device,	 * initial state, direction invalid	 */	CH_STATE_IDLE,	/**	 * Channel assigned but not operating	 */	CH_STATE_STOPPED,	CH_STATE_STARTWAIT,	CH_STATE_STARTRETRY,	CH_STATE_SETUPWAIT,	CH_STATE_RXINIT,	CH_STATE_TXINIT,	CH_STATE_RX,	CH_STATE_TX,	CH_STATE_RXIDLE,	CH_STATE_TXIDLE,	CH_STATE_RXERR,	CH_STATE_TXERR,	CH_STATE_TERM,	CH_STATE_DTERM,	CH_STATE_NOTOP,	/**	 * MUST be always the last element!!	 */	NR_CH_STATES,};static int loglevel = CTC_LOGLEVEL_DEFAULT;/** * Linked list of all detected channels. */static struct channel *channels = NULL;/** * Print Banner. */static voidprint_banner(void){	static int printed = 0;	char vbuf[] = "$Revision: 1.78 $";	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;}static const char *ch_event_names[] = {	"ccw_device success",	"ccw_device busy",	"ccw_device enodev",	"ccw_device ioerr",	"ccw_device unknown",	"Status ATTN & BUSY",	"Status ATTN",	"Status BUSY",	"Unit check remote reset",	"Unit check remote system reset",	"Unit check TX timeout",	"Unit check TX parity",	"Unit check Hardware failure",	"Unit check RX parity",	"Unit check ZERO",	"Unit check Unknown",	"SubChannel check Unknown",	"Machine check failure",	"Machine check operational",	"IRQ normal",	"IRQ final",	"Timer",	"Start",	"Stop",};static const char *ch_state_names[] = {	"Idle",	"Stopped",	"StartWait",	"StartRetry",	"SetupWait",	"RX init",	"TX init",	"RX",	"TX",	"RX idle",	"TX idle",	"RX error",	"TX error",	"Terminating",	"Restarting",	"Not operational",};#ifdef DEBUG/** * Dump header and first 16 bytes of an sk_buff for debugging purposes. * * @param skb    The sk_buff to dump. * @param offset Offset relative to skb-data, where to start the dump. */static voidctc_dump_skb(struct sk_buff *skb, int offset){	unsigned char *p = skb->data;	__u16 bl;	struct ll_header *header;	int i;	if (!(loglevel & CTC_LOGLEVEL_DEBUG))		return;	p += offset;	bl = *((__u16 *) p);	p += 2;	header = (struct ll_header *) p;	p -= 2;	printk(KERN_DEBUG "dump:\n");	printk(KERN_DEBUG "blocklen=%d %04x\n", bl, bl);	printk(KERN_DEBUG "h->length=%d %04x\n", header->length,	       header->length);	printk(KERN_DEBUG "h->type=%04x\n", header->type);	printk(KERN_DEBUG "h->unused=%04x\n", header->unused);	if (bl > 16)		bl = 16;	printk(KERN_DEBUG "data: ");	for (i = 0; i < bl; i++)		printk("%02x%s", *p++, (i % 16) ? " " : "\n<7>");	printk("\n");}#elsestatic inline voidctc_dump_skb(struct sk_buff *skb, int offset){}#endif/** * Unpack a just received skb and hand it over to * upper layers. * * @param ch The channel where this skb has been received. * @param pskb The received skb. */static __inline__ voidctc_unpack_skb(struct channel *ch, struct sk_buff *pskb){	struct net_device *dev = ch->netdev;	struct ctc_priv *privptr = (struct ctc_priv *) dev->priv;	__u16 len = *((__u16 *) pskb->data);	DBF_TEXT(trace, 4, __FUNCTION__);	skb_put(pskb, 2 + LL_HEADER_LENGTH);	skb_pull(pskb, 2);	pskb->dev = dev;	pskb->ip_summed = CHECKSUM_UNNECESSARY;	while (len > 0) {		struct sk_buff *skb;		struct ll_header *header = (struct ll_header *) pskb->data;		skb_pull(pskb, LL_HEADER_LENGTH);		if ((ch->protocol == CTC_PROTO_S390) &&		    (header->type != ETH_P_IP)) {#ifndef DEBUG		        if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) {#endif				/**				 * Check packet type only if we stick strictly				 * to S/390's protocol of OS390. This only				 * supports IP. Otherwise allow any packet				 * type.				 */				ctc_pr_warn(					"%s Illegal packet type 0x%04x received, dropping\n",					dev->name, header->type);				ch->logflags |= LOG_FLAG_ILLEGALPKT;#ifndef DEBUG			}#endif#ifdef DEBUG			ctc_dump_skb(pskb, -6);#endif			privptr->stats.rx_dropped++;			privptr->stats.rx_frame_errors++;			return;		}		pskb->protocol = ntohs(header->type);		if (header->length <= LL_HEADER_LENGTH) {#ifndef DEBUG		        if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) {#endif				ctc_pr_warn(				       "%s Illegal packet size %d "				       "received (MTU=%d blocklen=%d), "				       "dropping\n", dev->name, header->length,				       dev->mtu, len);				ch->logflags |= LOG_FLAG_ILLEGALSIZE;#ifndef DEBUG			}#endif#ifdef DEBUG			ctc_dump_skb(pskb, -6);#endif			privptr->stats.rx_dropped++;			privptr->stats.rx_length_errors++;			return;		}		header->length -= LL_HEADER_LENGTH;		len -= LL_HEADER_LENGTH;		if ((header->length > skb_tailroom(pskb)) ||

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -