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

📄 netiucv.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * $Id: netiucv.c,v 1.16 2001/12/03 14:28:45 felfert Exp $ * * IUCV network driver * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.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.16 $ * */#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>#include "iucv.h"#include "fsm.h"#undef DEBUG#ifdef MODULEMODULE_AUTHOR    ("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");MODULE_PARM (iucv, "1s");MODULE_PARM_DESC (iucv,		  "Specify the initial remote userids for iucv0 .. iucvn:\n"		  "iucv=userid0:userid1:...:useridN\n");#endifstatic char *iucv = "";/** * compatibility stuff */#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0))typedef struct net_device net_device;#elsetypedef struct device net_device;#endif/** * Per connection profiling data */typedef struct connection_profile_t {	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;} connection_profile;/** * Representation of one iucv connection */typedef struct iucv_connection_t {	struct iucv_connection_t *next;	iucv_handle_t            handle;	__u16                    pathid;	struct sk_buff           *rx_buff;	struct sk_buff           *tx_buff;	struct sk_buff_head      collect_queue;	spinlock_t               collect_lock;	int                      collect_len;	int                      max_buffsize;	int                      flags;	fsm_timer                timer;	int                      retry;	fsm_instance             *fsm;	net_device               *netdev;	connection_profile       prof;	char                     userid[9];} iucv_connection;#define CONN_FLAGS_BUFSIZE_CHANGED 1/** * Linked list of all connection structs. */iucv_connection *connections;/** * Representation of event-data for the * connection state machine. */typedef struct iucv_event_t {	iucv_connection *conn;	void            *data;} iucv_event;/** * Private part of the network device structure */typedef struct netiucv_priv_t {	struct net_device_stats stats;#if LINUX_VERSION_CODE >= 0x02032D	unsigned long           tbusy;#endif	fsm_instance            *fsm;        iucv_connection         *conn;	struct proc_dir_entry   *proc_dentry;	struct proc_dir_entry   *proc_stat_entry;	struct proc_dir_entry   *proc_buffer_entry;	struct proc_dir_entry   *proc_user_entry;	int                     proc_registered;} netiucv_priv;/** * 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. */#if LINUX_VERSION_CODE < 0x02032Dstatic __inline__ void netiucv_clear_busy(net_device *dev){	clear_bit(0 ,(void *)&dev->tbusy);	mark_bh(NET_BH);}static __inline__ int netiucv_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 netiucv_clear_busy(net_device *dev){	clear_bit(0, &(((netiucv_priv *)dev->priv)->tbusy));	netif_wake_queue(dev);}static __inline__ int netiucv_test_and_set_busy(net_device *dev){	netif_stop_queue(dev);	return test_and_set_bit(0, &((netiucv_priv *)dev->priv)->tbusy);}#define SET_DEVICE_START(device, value)#endif#if LINUX_VERSION_CODE < 0x020400#  define dev_kfree_skb_irq(a) dev_kfree_skb(a)#endif__u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };__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. */__u8 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,	/**	 * Terminating	 */	CONN_STATE_TERM,	/**	 * 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",};/** * Callback-wrappers, called from lowlevel iucv layer. *****************************************************************************/static voidnetiucv_callback_rx(iucv_MessagePending *eib, void *pgm_data){	iucv_connection *conn = (iucv_connection *)pgm_data;	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){	iucv_connection *conn = (iucv_connection *)pgm_data;	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){	iucv_connection *conn = (iucv_connection *)pgm_data;	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){	iucv_connection *conn = (iucv_connection *)pgm_data;	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){	iucv_connection *conn = (iucv_connection *)pgm_data;	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){	iucv_connection *conn = (iucv_connection *)pgm_data;	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){	iucv_connection *conn = (iucv_connection *)pgm_data;	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(iucv_connection *conn, struct sk_buff *pskb){	net_device     *dev = conn->netdev;	netiucv_priv   *privptr = (netiucv_priv *)dev->priv;	__u16          offset = 0;

⌨️ 快捷键说明

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