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

📄 i2o_lan.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 4 页
字号:
 * except SendPost and ReceivePost. */static void i2o_lan_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];	if ((msg[4] >> 24) != I2O_REPLY_STATUS_SUCCESS) {		if (i2o_lan_handle_status(dev, msg))			return;		/* In other error cases just report and continue */		i2o_report_status(KERN_INFO, dev->name, msg);	}#ifdef DRIVERDEBUG	i2o_report_status(KERN_INFO, dev->name, msg);#endif	switch (msg[1] >> 24) {		case LAN_RESET:		case LAN_SUSPEND:			/* default reply without payload */		break;		case I2O_CMD_UTIL_EVT_REGISTER: 		case I2O_CMD_UTIL_EVT_ACK:			i2o_lan_handle_event(dev, msg);		break;		case I2O_CMD_UTIL_PARAMS_SET:			/* default reply, results in ReplyPayload (not examined) */			switch (msg[3] >> 16) {			    case 1: dprintk(KERN_INFO "%s: Reply to set MAC filter mask.\n",					dev->name);			    break;			    case 2: dprintk(KERN_INFO "%s: Reply to set MAC table.\n", 					dev->name);			    break;			    default: printk(KERN_WARNING "%s: Bad group 0x%04X\n",			 		dev->name,msg[3] >> 16);			}		break;		default:			printk(KERN_ERR "%s: No handler for the reply.\n",		       		dev->name);			i2o_report_status(KERN_INFO, dev->name, msg);	}}/* Functions used by the above callback functions:=================================================*//* * i2o_lan_release_buckets(): Free unused buckets (sk_buffs). */static void i2o_lan_release_buckets(struct net_device *dev, u32 *msg){	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	u8 trl_elem_size = (u8)(msg[3]>>8 & 0x000000FF);	u8 trl_count = (u8)(msg[3] & 0x000000FF);	u32 *pskb = &msg[6];	while (trl_count--) {		dprintk(KERN_DEBUG "%s: Releasing unused rx skb %p (trl_count=%d).\n",			dev->name, (struct sk_buff*)(*pskb),trl_count+1);		dev_kfree_skb_irq((struct sk_buff *)(*pskb));		pskb += 1 + trl_elem_size;		atomic_dec(&priv->buckets_out);	}}/* * i2o_lan_event_reply(): Handle events. */static void i2o_lan_handle_event(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 max_evt_data_size =iop->status_block->inbound_frame_size-5;	struct i2o_reply {		u32 header[4];		u32 evt_indicator;		u32 data[max_evt_data_size];	} *evt = (struct i2o_reply *)msg;	int evt_data_len = ((msg[0]>>16) - 5) * 4; /* real size*/	printk(KERN_INFO "%s: I2O event - ", dev->name);	if (msg[1]>>24 == I2O_CMD_UTIL_EVT_ACK) {		printk("Event acknowledgement reply.\n");		return;	}	/* Else evt->function == I2O_CMD_UTIL_EVT_REGISTER) */	switch (evt->evt_indicator) {	case I2O_EVT_IND_STATE_CHANGE:  {		struct state_data {			u16 status;			u8 state;			u8 data;		} *evt_data = (struct state_data *)(evt->data[0]);		printk("State chance 0x%08x.\n", evt->data[0]);		/* If the DDM is in error state, recovery may be		 * possible if status = Transmit or Receive Control		 * Unit Inoperable.		 */		if (evt_data->state==0x05 && evt_data->status==0x0003)			i2o_lan_reset(dev);		break;	}	case I2O_EVT_IND_FIELD_MODIFIED: {		u16 *work16 = (u16 *)evt->data;		printk("Group 0x%04x, field %d changed.\n", work16[0], work16[1]);		break;	}	case I2O_EVT_IND_VENDOR_EVT: {		int i;		printk("Vendor event:\n");		for (i = 0; i < evt_data_len / 4; i++)			printk("   0x%08x\n", evt->data[i]);		break;	}	case I2O_EVT_IND_DEVICE_RESET:		/* Spec 2.0 p. 6-121:		 * The event of _DEVICE_RESET should also be responded		 */		printk("Device reset.\n");		if (i2o_event_ack(iop, msg) < 0)			printk("%s: Event Acknowledge timeout.\n", dev->name);		break;#if 0	case I2O_EVT_IND_EVT_MASK_MODIFIED:		printk("Event mask modified, 0x%08x.\n", evt->data[0]);		break;	case I2O_EVT_IND_GENERAL_WARNING:		printk("General warning 0x%04x.\n", evt->data[0]);		break;	case I2O_EVT_IND_CONFIGURATION_FLAG:		printk("Configuration requested.\n");		break;	case I2O_EVT_IND_CAPABILITY_CHANGE:		printk("Capability change 0x%04x.\n", evt->data[0]);		break;	case I2O_EVT_IND_DEVICE_STATE:		printk("Device state changed 0x%08x.\n", evt->data[0]);		break;#endif	case I2O_LAN_EVT_LINK_DOWN:		netif_carrier_off(dev); 		printk("Link to the physical device is lost.\n");		break;	case I2O_LAN_EVT_LINK_UP:		netif_carrier_on(dev); 		printk("Link to the physical device is (re)established.\n");		break;	case I2O_LAN_EVT_MEDIA_CHANGE:		printk("Media change.\n");		break;	default:		printk("0x%08x. No handler.\n", evt->evt_indicator);	}}/* * i2o_lan_receive_post(): Post buckets to receive packets. */static int i2o_lan_receive_post(struct net_device *dev){	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;	struct sk_buff *skb;	u32 m, *msg;	u32 bucket_len = (dev->mtu + dev->hard_header_len);	u32 total = priv->max_buckets_out - atomic_read(&priv->buckets_out);	u32 bucket_count;	u32 *sgl_elem;	unsigned long flags;	/* Send (total/bucket_count) separate I2O requests */	while (total) {		m = I2O_POST_READ32(iop);		if (m == 0xFFFFFFFF)			return -ETIMEDOUT;		msg = (u32 *)(iop->mem_offset + m);		bucket_count = (total >= priv->sgl_max) ? priv->sgl_max : total;		total -= bucket_count;		atomic_add(bucket_count, &priv->buckets_out);		dprintk(KERN_INFO "%s: Sending %d buckets (size %d) to LAN DDM.\n",			dev->name, bucket_count, bucket_len);		/* Fill in the header */		__raw_writel(I2O_MESSAGE_SIZE(4 + 3 * bucket_count) | SGL_OFFSET_4, msg);		__raw_writel(LAN_RECEIVE_POST<<24 | HOST_TID<<12 | i2o_dev->lct_data.tid, msg+1);		__raw_writel(priv->unit << 16 | lan_receive_context, msg+2);		__raw_writel(bucket_count, msg+3);		sgl_elem = &msg[4];		/* Fill in the payload - contains bucket_count SGL elements */		while (bucket_count--) {			spin_lock_irqsave(&priv->fbl_lock, flags);			if (priv->i2o_fbl_tail >= 0)				skb = priv->i2o_fbl[priv->i2o_fbl_tail--];			else {				skb = dev_alloc_skb(bucket_len + 2);				if (skb == NULL) {					spin_unlock_irqrestore(&priv->fbl_lock, flags);					return -ENOMEM;				}				skb_reserve(skb, 2);			}			spin_unlock_irqrestore(&priv->fbl_lock, flags);			__raw_writel(0x51000000 | bucket_len, sgl_elem);			__raw_writel((u32)skb,		      sgl_elem+1);			__raw_writel(virt_to_bus(skb->data),  sgl_elem+2);			sgl_elem += 3;		}		/* set LE flag and post  */		__raw_writel(__raw_readl(sgl_elem-3) | 0x80000000, (sgl_elem-3));		i2o_post_message(iop, m);	}	return 0;}/* Functions called from the network stack, and functions called by them:========================================================================*//* * i2o_lan_reset(): Reset the LAN adapter into the operational state and * 	restore it to full operation. */static int i2o_lan_reset(struct net_device *dev){	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 msg[5];	dprintk(KERN_INFO "%s: LAN RESET MESSAGE.\n", dev->name);	msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;	msg[1] = LAN_RESET<<24 | HOST_TID<<12 | i2o_dev->lct_data.tid;	msg[2] = priv->unit << 16 | lan_context; // InitiatorContext	msg[3] = 0; 				 // TransactionContext	msg[4] = 0;				 // Keep posted buckets	if (i2o_post_this(iop, msg, sizeof(msg)) < 0)		return -ETIMEDOUT;	return 0;}/* * i2o_lan_suspend(): Put LAN adapter into a safe, non-active state. * 	IOP replies to any LAN class message with status error_no_data_transfer *	/ suspended. */static int i2o_lan_suspend(struct net_device *dev){	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 msg[5];	dprintk(KERN_INFO "%s: LAN SUSPEND MESSAGE.\n", dev->name);	msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;	msg[1] = LAN_SUSPEND<<24 | HOST_TID<<12 | i2o_dev->lct_data.tid;	msg[2] = priv->unit << 16 | lan_context; // InitiatorContext	msg[3] = 0; 				 // TransactionContext	msg[4] = 1 << 16; 			 // return posted buckets	if (i2o_post_this(iop, msg, sizeof(msg)) < 0)		return -ETIMEDOUT;	return 0;}/* * i2o_set_ddm_parameters: * These settings are done to ensure proper initial values for DDM. * They can be changed via proc file system or vai configuration utility. */static void i2o_set_ddm_parameters(struct net_device *dev){	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 val;	/*	 * When PacketOrphanlimit is set to the maximum packet length,	 * the packets will never be split into two separate buckets	 */	val = dev->mtu + dev->hard_header_len;	if (i2o_set_scalar(iop, i2o_dev->lct_data.tid, 0x0004, 2, &val, sizeof(val)) < 0)		printk(KERN_WARNING "%s: Unable to set PacketOrphanLimit.\n",		       dev->name);	else		dprintk(KERN_INFO "%s: PacketOrphanLimit set to %d.\n",			dev->name, val);	/* When RxMaxPacketsBucket = 1, DDM puts only one packet into bucket */	val = 1;	if (i2o_set_scalar(iop, i2o_dev->lct_data.tid, 0x0008, 4, &val, sizeof(val)) <0)		printk(KERN_WARNING "%s: Unable to set RxMaxPacketsBucket.\n",		       dev->name);	else		dprintk(KERN_INFO "%s: RxMaxPacketsBucket set to %d.\n", 			dev->name, val);	return;}/* Functions called from the network stack:==========================================*//* * i2o_lan_open(): Open the device to send/receive packets via * the network device. */static int i2o_lan_open(struct net_device *dev){	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 mc_addr_group[64];	MOD_INC_USE_COUNT;	if (i2o_claim_device(i2o_dev, &i2o_lan_handler)) {		printk(KERN_WARNING "%s: Unable to claim the I2O LAN device.\n", dev->name);		MOD_DEC_USE_COUNT;		return -EAGAIN;	}	dprintk(KERN_INFO "%s: I2O LAN device (tid=%d) claimed by LAN OSM.\n",		dev->name, i2o_dev->lct_data.tid);	if (i2o_event_register(iop, i2o_dev->lct_data.tid,			       priv->unit << 16 | lan_context, 0, priv->i2o_event_mask) < 0)		printk(KERN_WARNING "%s: Unable to set the event mask.\n", dev->name);	i2o_lan_reset(dev);	/* Get the max number of multicast addresses */	if (i2o_query_scalar(iop, i2o_dev->lct_data.tid, 0x0001, -1,			     &mc_addr_group, sizeof(mc_addr_group)) < 0 ) {		printk(KERN_WARNING "%s: Unable to query LAN_MAC_ADDRESS group.\n", dev->name);		MOD_DEC_USE_COUNT;		return -EAGAIN;	}	priv->max_size_mc_table = mc_addr_group[8];	/* Malloc space for free bucket list to resuse reveive post buckets */	priv->i2o_fbl = kmalloc(priv->max_buckets_out * sizeof(struct sk_buff *),				GFP_KERNEL);	if (priv->i2o_fbl == NULL) {		MOD_DEC_USE_COUNT;		return -ENOMEM;	}	priv->i2o_fbl_tail = -1;	priv->send_active = 0;	i2o_set_ddm_parameters(dev);	i2o_lan_receive_post(dev);	netif_start_queue(dev);	return 0;}

⌨️ 快捷键说明

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