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

📄 netiucv.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * $Id: netiucv.c,v 1.66 2005/05/11 08:10:17 holzheu Exp $ * * IUCV network driver * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com) * * Driverfs integration and all bugs therein by Cornelia Huck(cohuck@de.ibm.com) * * Documentation used: *  the source of the original IUCV driver by: *    Stefan Hegewald <hegewald@de.ibm.com> *    Hartmut Penner <hpenner@de.ibm.com> *    Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) *    Martin Schwidefsky (schwidefsky@de.ibm.com) *    Alan Altmark (Alan_Altmark@us.ibm.com)  Sept. 2000 * * 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: IUCV network driver $Revision: 1.66 $ * */#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/device.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/uaccess.h>#include "iucv.h"#include "fsm.h"MODULE_AUTHOR    ("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");#define PRINTK_HEADER " iucv: "       /* for debugging */static struct device_driver netiucv_driver = {	.name = "netiucv",	.bus  = &iucv_bus,};/** * Per connection profiling data */struct connection_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;	unsigned long tx_pending;	unsigned long tx_max_pending;};/** * Representation of one iucv connection */struct iucv_connection {	struct iucv_connection    *next;	iucv_handle_t             handle;	__u16                     pathid;	struct sk_buff            *rx_buff;	struct sk_buff            *tx_buff;	struct sk_buff_head       collect_queue;	struct sk_buff_head	  commit_queue;	spinlock_t                collect_lock;	int                       collect_len;	int                       max_buffsize;	fsm_timer                 timer;	fsm_instance              *fsm;	struct net_device         *netdev;	struct connection_profile prof;	char                      userid[9];};/** * Linked list of all connection structs. */static struct iucv_connection *iucv_connections;/** * Representation of event-data for the * connection state machine. */struct iucv_event {	struct iucv_connection *conn;	void                   *data;};/** * Private part of the network device structure */struct netiucv_priv {	struct net_device_stats stats;	unsigned long           tbusy;	fsm_instance            *fsm;        struct iucv_connection  *conn;	struct device           *dev;};/** * Link level header for a packet. */typedef struct ll_header_t {	__u16 next;} ll_header;#define NETIUCV_HDRLEN           (sizeof(ll_header))#define NETIUCV_BUFSIZE_MAX      32768#define NETIUCV_BUFSIZE_DEFAULT  NETIUCV_BUFSIZE_MAX#define NETIUCV_MTU_MAX          (NETIUCV_BUFSIZE_MAX - NETIUCV_HDRLEN)#define NETIUCV_MTU_DEFAULT      9216#define NETIUCV_QUEUELEN_DEFAULT 50#define NETIUCV_TIMEOUT_5SEC     5000/** * Compatibility macros for busy handling * of network devices. */static __inline__ void netiucv_clear_busy(struct net_device *dev){	clear_bit(0, &(((struct netiucv_priv *)dev->priv)->tbusy));	netif_wake_queue(dev);}static __inline__ int netiucv_test_and_set_busy(struct net_device *dev){	netif_stop_queue(dev);	return test_and_set_bit(0, &((struct netiucv_priv *)dev->priv)->tbusy);}static __u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };static __u8 iucvMagic[16] = {	0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,	0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40};/** * This mask means the 16-byte IUCV "magic" and the origin userid must * match exactly as specified in order to give connection_pending() * control. */static __u8 netiucv_mask[] = {	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};/** * Convert an iucv userId to its printable * form (strip whitespace at end). * * @param An iucv userId * * @returns The printable string (static data!!) */static __inline__ char *netiucv_printname(char *name){	static char tmp[9];	char *p = tmp;	memcpy(tmp, name, 8);	tmp[8] = '\0';	while (*p && (!isspace(*p)))		p++;	*p = '\0';	return tmp;}/** * States of the interface statemachine. */enum dev_states {	DEV_STATE_STOPPED,	DEV_STATE_STARTWAIT,	DEV_STATE_STOPWAIT,	DEV_STATE_RUNNING,	/**	 * MUST be always the last element!!	 */	NR_DEV_STATES};static const char *dev_state_names[] = {	"Stopped",	"StartWait",	"StopWait",	"Running",};/** * Events of the interface statemachine. */enum dev_events {	DEV_EVENT_START,	DEV_EVENT_STOP,	DEV_EVENT_CONUP,	DEV_EVENT_CONDOWN,	/**	 * MUST be always the last element!!	 */	NR_DEV_EVENTS};static const char *dev_event_names[] = {	"Start",	"Stop",	"Connection up",	"Connection down",};/** * Events of the connection statemachine */enum conn_events {	/**	 * Events, representing callbacks from	 * lowlevel iucv layer)	 */	CONN_EVENT_CONN_REQ,	CONN_EVENT_CONN_ACK,	CONN_EVENT_CONN_REJ,	CONN_EVENT_CONN_SUS,	CONN_EVENT_CONN_RES,	CONN_EVENT_RX,	CONN_EVENT_TXDONE,	/**	 * Events, representing errors return codes from	 * calls to lowlevel iucv layer	 */	/**	 * Event, representing timer expiry.	 */	CONN_EVENT_TIMER,	/**	 * Events, representing commands from upper levels.	 */	CONN_EVENT_START,	CONN_EVENT_STOP,	/**	 * MUST be always the last element!!	 */	NR_CONN_EVENTS,};static const char *conn_event_names[] = {	"Remote connection request",	"Remote connection acknowledge",	"Remote connection reject",	"Connection suspended",	"Connection resumed",	"Data received",	"Data sent",	"Timer",	"Start",	"Stop",};/** * States of the connection statemachine. */enum conn_states {	/**	 * Connection not assigned to any device,	 * initial state, invalid	 */	CONN_STATE_INVALID,	/**	 * Userid assigned but not operating	 */	CONN_STATE_STOPPED,	/**	 * Connection registered,	 * no connection request sent yet,	 * no connection request received	 */	CONN_STATE_STARTWAIT,	/**	 * Connection registered and connection request sent,	 * no acknowledge and no connection request received yet.	 */	CONN_STATE_SETUPWAIT,	/**	 * Connection up and running idle	 */	CONN_STATE_IDLE,	/**	 * Data sent, awaiting CONN_EVENT_TXDONE	 */	CONN_STATE_TX,	/**	 * Error during registration.	 */	CONN_STATE_REGERR,	/**	 * Error during registration.	 */	CONN_STATE_CONNERR,	/**	 * MUST be always the last element!!	 */	NR_CONN_STATES,};static const char *conn_state_names[] = {	"Invalid",	"Stopped",	"StartWait",	"SetupWait",	"Idle",	"TX",	"Terminating",	"Registration error",	"Connect error",};/** * Debug Facility Stuff */static debug_info_t *iucv_dbf_setup = NULL;static debug_info_t *iucv_dbf_data = NULL;static debug_info_t *iucv_dbf_trace = NULL;DEFINE_PER_CPU(char[256], iucv_dbf_txt_buf);static voidiucv_unregister_dbf_views(void){	if (iucv_dbf_setup)		debug_unregister(iucv_dbf_setup);	if (iucv_dbf_data)		debug_unregister(iucv_dbf_data);	if (iucv_dbf_trace)		debug_unregister(iucv_dbf_trace);}static intiucv_register_dbf_views(void){	iucv_dbf_setup = debug_register(IUCV_DBF_SETUP_NAME,					IUCV_DBF_SETUP_PAGES,					IUCV_DBF_SETUP_NR_AREAS,					IUCV_DBF_SETUP_LEN);	iucv_dbf_data = debug_register(IUCV_DBF_DATA_NAME,				       IUCV_DBF_DATA_PAGES,				       IUCV_DBF_DATA_NR_AREAS,				       IUCV_DBF_DATA_LEN);	iucv_dbf_trace = debug_register(IUCV_DBF_TRACE_NAME,					IUCV_DBF_TRACE_PAGES,					IUCV_DBF_TRACE_NR_AREAS,					IUCV_DBF_TRACE_LEN);	if ((iucv_dbf_setup == NULL) || (iucv_dbf_data == NULL) ||	    (iucv_dbf_trace == NULL)) {		iucv_unregister_dbf_views();		return -ENOMEM;	}	debug_register_view(iucv_dbf_setup, &debug_hex_ascii_view);	debug_set_level(iucv_dbf_setup, IUCV_DBF_SETUP_LEVEL);	debug_register_view(iucv_dbf_data, &debug_hex_ascii_view);	debug_set_level(iucv_dbf_data, IUCV_DBF_DATA_LEVEL);	debug_register_view(iucv_dbf_trace, &debug_hex_ascii_view);	debug_set_level(iucv_dbf_trace, IUCV_DBF_TRACE_LEVEL);	return 0;}/** * Callback-wrappers, called from lowlevel iucv layer. *****************************************************************************/static voidnetiucv_callback_rx(iucv_MessagePending *eib, void *pgm_data){	struct iucv_connection *conn = (struct iucv_connection *)pgm_data;	struct iucv_event ev;	ev.conn = conn;	ev.data = (void *)eib;	fsm_event(conn->fsm, CONN_EVENT_RX, &ev);}static voidnetiucv_callback_txdone(iucv_MessageComplete *eib, void *pgm_data){	struct iucv_connection *conn = (struct iucv_connection *)pgm_data;	struct iucv_event ev;	ev.conn = conn;	ev.data = (void *)eib;	fsm_event(conn->fsm, CONN_EVENT_TXDONE, &ev);}static voidnetiucv_callback_connack(iucv_ConnectionComplete *eib, void *pgm_data){	struct iucv_connection *conn = (struct iucv_connection *)pgm_data;	struct iucv_event ev;	ev.conn = conn;	ev.data = (void *)eib;	fsm_event(conn->fsm, CONN_EVENT_CONN_ACK, &ev);}static voidnetiucv_callback_connreq(iucv_ConnectionPending *eib, void *pgm_data){	struct iucv_connection *conn = (struct iucv_connection *)pgm_data;	struct iucv_event ev;	ev.conn = conn;	ev.data = (void *)eib;	fsm_event(conn->fsm, CONN_EVENT_CONN_REQ, &ev);}static voidnetiucv_callback_connrej(iucv_ConnectionSevered *eib, void *pgm_data){	struct iucv_connection *conn = (struct iucv_connection *)pgm_data;	struct iucv_event ev;	ev.conn = conn;	ev.data = (void *)eib;	fsm_event(conn->fsm, CONN_EVENT_CONN_REJ, &ev);}static voidnetiucv_callback_connsusp(iucv_ConnectionQuiesced *eib, void *pgm_data){	struct iucv_connection *conn = (struct iucv_connection *)pgm_data;	struct iucv_event ev;	ev.conn = conn;	ev.data = (void *)eib;	fsm_event(conn->fsm, CONN_EVENT_CONN_SUS, &ev);}static voidnetiucv_callback_connres(iucv_ConnectionResumed *eib, void *pgm_data){	struct iucv_connection *conn = (struct iucv_connection *)pgm_data;	struct iucv_event ev;	ev.conn = conn;	ev.data = (void *)eib;	fsm_event(conn->fsm, CONN_EVENT_CONN_RES, &ev);}static iucv_interrupt_ops_t netiucv_ops = {	.ConnectionPending  = netiucv_callback_connreq,	.ConnectionComplete = netiucv_callback_connack,	.ConnectionSevered  = netiucv_callback_connrej,	.ConnectionQuiesced = netiucv_callback_connsusp,	.ConnectionResumed  = netiucv_callback_connres,	.MessagePending     = netiucv_callback_rx,	.MessageComplete    = netiucv_callback_txdone};/** * Dummy NOP action for all statemachines */static voidfsm_action_nop(fsm_instance *fi, int event, void *arg){}/** * Actions of the connection statemachine *****************************************************************************//** * Helper function for conn_action_rx() * Unpack a just received skb and hand it over to * upper layers. * * @param conn The connection where this skb has been received. * @param pskb The received skb. *///static __inline__ voidstatic voidnetiucv_unpack_skb(struct iucv_connection *conn, struct sk_buff *pskb){

⌨️ 快捷键说明

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