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

📄 i2o_lan.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *	drivers/i2o/i2o_lan.c * * 	I2O LAN CLASS OSM 		May 26th 2000 * *	(C) Copyright 1999, 2000 	University of Helsinki, *		      			Department of Computer Science * * 	This code is still under development / test. * *	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 of the License, or (at your option) any later version. * *	Authors: 	Auvo H鋕kinen <Auvo.Hakkinen@cs.Helsinki.FI> *	Fixes:		Juha Siev鋘en <Juha.Sievanen@cs.Helsinki.FI> *	 		Taneli V鋒鋕angas <Taneli.Vahakangas@cs.Helsinki.FI> *			Deepak Saxena <deepak@plexity.net> * *	Tested:		in FDDI environment (using SysKonnect's DDM) *			in Gigabit Eth environment (using SysKonnect's DDM) *			in Fast Ethernet environment (using Intel 82558 DDM) * *	TODO:		tests for other LAN classes (Token Ring, Fibre Channel) */#include <linux/config.h>#include <linux/module.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/fddidevice.h>#include <linux/trdevice.h>#include <linux/fcdevice.h>#include <linux/skbuff.h>#include <linux/if_arp.h>#include <linux/malloc.h>#include <linux/init.h>#include <linux/spinlock.h>#include <linux/tqueue.h>#include <asm/io.h>#include <linux/errno.h>#include <linux/i2o.h>#include "i2o_lan.h"//#define DRIVERDEBUG#ifdef DRIVERDEBUG#define dprintk(s, args...) printk(s, ## args)#else#define dprintk(s, args...)#endif/* The following module parameters are used as default values * for per interface values located in the net_device private area. * Private values are changed via /proc filesystem. */static u32 max_buckets_out = I2O_LAN_MAX_BUCKETS_OUT;static u32 bucket_thresh   = I2O_LAN_BUCKET_THRESH;static u32 rx_copybreak    = I2O_LAN_RX_COPYBREAK;static u8  tx_batch_mode   = I2O_LAN_TX_BATCH_MODE;static u32 i2o_event_mask  = I2O_LAN_EVENT_MASK;#define MAX_LAN_CARDS 16static struct net_device *i2o_landevs[MAX_LAN_CARDS+1];static int unit = -1; 	  /* device unit number */static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop, struct i2o_message *m);static void i2o_lan_send_post_reply(struct i2o_handler *h, struct i2o_controller *iop, struct i2o_message *m);static int i2o_lan_receive_post(struct net_device *dev);static void i2o_lan_receive_post_reply(struct i2o_handler *h, struct i2o_controller *iop, struct i2o_message *m);static void i2o_lan_release_buckets(struct net_device *dev, u32 *msg);static int i2o_lan_reset(struct net_device *dev);static void i2o_lan_handle_event(struct net_device *dev, u32 *msg);/* Structures to register handlers for the incoming replies. */static struct i2o_handler i2o_lan_send_handler = {	i2o_lan_send_post_reply, 	// For send replies	NULL,	NULL,	NULL,	"I2O LAN OSM send",	-1,	I2O_CLASS_LAN};static int lan_send_context;static struct i2o_handler i2o_lan_receive_handler = {	i2o_lan_receive_post_reply,	// For receive replies	NULL,	NULL,	NULL,	"I2O LAN OSM receive",	-1,	I2O_CLASS_LAN};static int lan_receive_context;static struct i2o_handler i2o_lan_handler = {	i2o_lan_reply,			// For other replies	NULL,	NULL,	NULL,	"I2O LAN OSM",	-1,	I2O_CLASS_LAN};static int lan_context;DECLARE_TASK_QUEUE(i2o_post_buckets_task);struct tq_struct run_i2o_post_buckets_task = {	routine: (void (*)(void *)) run_task_queue,	data: (void *) 0};/* Functions to handle message failures and transaction errors:==============================================================*//* * i2o_lan_handle_failure(): Fail bit has been set since IOP's message * layer cannot deliver the request to the target, or the target cannot * process the request. */static void i2o_lan_handle_failure(struct net_device *dev, u32 *msg){	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	struct i2o_device *i2o_dev = priv->i2o_dev;	struct i2o_controller *iop = i2o_dev->controller;	u32 *preserved_msg = (u32*)(iop->mem_offset + msg[7]);	u32 *sgl_elem = &preserved_msg[4];	struct sk_buff *skb = NULL;	u8 le_flag;	i2o_report_status(KERN_INFO, dev->name, msg);	/* If PacketSend failed, free sk_buffs reserved by upper layers */	if (msg[1] >> 24 == LAN_PACKET_SEND) {		do {			skb = (struct sk_buff *)(sgl_elem[1]);			dev_kfree_skb_irq(skb);			atomic_dec(&priv->tx_out);			le_flag = *sgl_elem >> 31;			sgl_elem +=3;		} while (le_flag == 0); /* Last element flag not set */		if (netif_queue_stopped(dev))			netif_wake_queue(dev);	}	/* If ReceivePost failed, free sk_buffs we have reserved */	if (msg[1] >> 24 == LAN_RECEIVE_POST) {		do {			skb = (struct sk_buff *)(sgl_elem[1]);			dev_kfree_skb_irq(skb);			atomic_dec(&priv->buckets_out);			le_flag = *sgl_elem >> 31;			sgl_elem +=3;		} while (le_flag == 0); /* Last element flag not set */	}	/* Release the preserved msg frame by resubmitting it as a NOP */	preserved_msg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;	preserved_msg[1] = I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0;	preserved_msg[2] = 0;	i2o_post_message(iop, msg[7]);}/* * i2o_lan_handle_transaction_error(): IOP or DDM has rejected the request * for general cause (format error, bad function code, insufficient resources, * etc.). We get one transaction_error for each failed transaction. */static void i2o_lan_handle_transaction_error(struct net_device *dev, u32 *msg){	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	struct sk_buff *skb;	i2o_report_status(KERN_INFO, dev->name, msg);	/* If PacketSend was rejected, free sk_buff reserved by upper layers */	if (msg[1] >> 24 == LAN_PACKET_SEND) {		skb = (struct sk_buff *)(msg[3]); // TransactionContext		dev_kfree_skb_irq(skb);		atomic_dec(&priv->tx_out);		if (netif_queue_stopped(dev))			netif_wake_queue(dev); 	}	/* If ReceivePost was rejected, free sk_buff we have reserved */	if (msg[1] >> 24 == LAN_RECEIVE_POST) {		skb = (struct sk_buff *)(msg[3]);		dev_kfree_skb_irq(skb);		atomic_dec(&priv->buckets_out);	}}/* * i2o_lan_handle_status(): Common parts of handling a not succeeded request * (status != SUCCESS). */static int i2o_lan_handle_status(struct net_device *dev, u32 *msg){	/* Fail bit set? */	if (msg[0] & MSG_FAIL) {		i2o_lan_handle_failure(dev, msg);		return -1;	}	/* Message rejected for general cause? */	if ((msg[4]>>24) == I2O_REPLY_STATUS_TRANSACTION_ERROR) {		i2o_lan_handle_transaction_error(dev, msg);		return -1;	}	/* Else have to handle it in the callback function */	return 0;}/* Callback functions called from the interrupt routine:=======================================================*//* * i2o_lan_send_post_reply(): Callback function to handle PostSend replies. */static void i2o_lan_send_post_reply(struct i2o_handler *h,			struct i2o_controller *iop, struct i2o_message *m){	u32 *msg = (u32 *)m;	u8 unit  = (u8)(msg[2]>>16); // InitiatorContext	struct net_device *dev = i2o_landevs[unit];	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	u8 trl_count  = msg[3] & 0x000000FF;	if ((msg[4] >> 24) != I2O_REPLY_STATUS_SUCCESS) {		if (i2o_lan_handle_status(dev, msg))			return;	}#ifdef DRIVERDEBUG	i2o_report_status(KERN_INFO, dev->name, msg);#endif	/* DDM has handled transmit request(s), free sk_buffs.	 * We get similar single transaction reply also in error cases 	 * (except if msg failure or transaction error).	 */	while (trl_count) {		dev_kfree_skb_irq((struct sk_buff *)msg[4 + trl_count]);		dprintk(KERN_INFO "%s: tx skb freed (trl_count=%d).\n",			dev->name, trl_count);		atomic_dec(&priv->tx_out);		trl_count--;	}	/* If priv->tx_out had reached tx_max_out, the queue was stopped */	if (netif_queue_stopped(dev)) 		netif_wake_queue(dev);}/* * i2o_lan_receive_post_reply(): Callback function to process incoming packets. */static void i2o_lan_receive_post_reply(struct i2o_handler *h,			struct i2o_controller *iop, struct i2o_message *m){	u32 *msg = (u32 *)m;	u8 unit  = (u8)(msg[2]>>16); // InitiatorContext	struct net_device *dev = i2o_landevs[unit];	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	struct i2o_bucket_descriptor *bucket = (struct i2o_bucket_descriptor *)&msg[6];	struct i2o_packet_info *packet;	u8 trl_count = msg[3] & 0x000000FF;	struct sk_buff *skb, *old_skb;	unsigned long flags = 0;	if ((msg[4] >> 24) != I2O_REPLY_STATUS_SUCCESS) {		if (i2o_lan_handle_status(dev, msg))			return;		i2o_lan_release_buckets(dev, msg);		return;	}#ifdef DRIVERDEBUG	i2o_report_status(KERN_INFO, dev->name, msg);#endif	/* Else we are receiving incoming post. */	while (trl_count--) {		skb = (struct sk_buff *)bucket->context;		packet = (struct i2o_packet_info *)bucket->packet_info;		atomic_dec(&priv->buckets_out);		/* Sanity checks: Any weird characteristics in bucket? */		if (packet->flags & 0x0f || ! packet->flags & 0x40) {			if (packet->flags & 0x01)				printk(KERN_WARNING "%s: packet with errors, error code=0x%02x.\n",					dev->name, packet->status & 0xff);			/* The following shouldn't happen, unless parameters in			 * LAN_OPERATION group are changed during the run time.			 */			 if (packet->flags & 0x0c)				printk(KERN_DEBUG "%s: multi-bucket packets not supported!\n", 					dev->name);								if (! packet->flags & 0x40)				printk(KERN_DEBUG "%s: multiple packets in a bucket not supported!\n", 					dev->name);			dev_kfree_skb_irq(skb);			bucket++;			continue;		}		/* Copy short packet to a new skb */				if (packet->len < priv->rx_copybreak) {			old_skb = skb;			skb = (struct sk_buff *)dev_alloc_skb(packet->len+2);			if (skb == NULL) {				printk(KERN_ERR "%s: Can't allocate skb.\n", dev->name);				return;			}			skb_reserve(skb, 2);			memcpy(skb_put(skb, packet->len), old_skb->data, packet->len);			spin_lock_irqsave(&priv->fbl_lock, flags);			if (priv->i2o_fbl_tail < I2O_LAN_MAX_BUCKETS_OUT)				priv->i2o_fbl[++priv->i2o_fbl_tail] = old_skb;			else				dev_kfree_skb_irq(old_skb);			spin_unlock_irqrestore(&priv->fbl_lock, flags);		} else			skb_put(skb, packet->len);		/* Deliver to upper layers */		skb->dev = dev;		skb->protocol = priv->type_trans(skb, dev);		netif_rx(skb);		dev->last_rx = jiffies;		dprintk(KERN_INFO "%s: Incoming packet (%d bytes) delivered "			"to upper level.\n", dev->name, packet->len);		bucket++; // to next Packet Descriptor Block	}#ifdef DRIVERDEBUG	if (msg[5] == 0)		printk(KERN_INFO "%s: DDM out of buckets (priv->count = %d)!\n",		       dev->name, atomic_read(&priv->buckets_out));#endif	/* If DDM has already consumed bucket_thresh buckets, post new ones */	if (atomic_read(&priv->buckets_out) <= priv->max_buckets_out - priv->bucket_thresh) {		run_i2o_post_buckets_task.data = (void *)dev;		queue_task(&run_i2o_post_buckets_task, &tq_immediate);		mark_bh(IMMEDIATE_BH);	}	return;}/* * i2o_lan_reply(): Callback function to handle other incoming messages * except SendPost and ReceivePost.

⌨️ 快捷键说明

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