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

📄 e100_main.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	e100_set_int_option(&(bdp->params.BundleMax), BundleMax[board], 0x1,			    0xFFFF, E100_DEFAULT_CPUSAVER_BUNDLE_MAX,			    "CPU saver bundle max value");}/** * e100_set_int_option - check and set an integer option * @option: a pointer to the relevant option field * @val: the value specified * @min: the minimum valid value * @max: the maximum valid value * @default_val: the default value * @name: the name of the option * * This routine does range checking on a command-line option. * If the option's value is '-1' use the specified default. * Otherwise, if the value is invalid, change it to the default. */void __devinite100_set_int_option(int *option, int val, int min, int max, int default_val,		    char *name){	if (val == -1) {	/* no value specified. use default */		*option = default_val;	} else if ((val < min) || (val > max)) {		printk(KERN_NOTICE		       "e100: Invalid %s specified (%i). "		       "Valid range is %i-%i\n",		       name, val, min, max);		printk(KERN_NOTICE "e100: Using default %s of %i\n", name,		       default_val);		*option = default_val;	} else {		printk(KERN_INFO "e100: Using specified %s of %i\n", name, val);		*option = val;	}}/** * e100_set_bool_option - check and set a boolean option * @bdp: atapter's private data struct * @val: the value specified * @mask: the mask for the relevant option * @default_val: the default value * @name: the name of the option * * This routine checks a boolean command-line option. * If the option's value is '-1' use the specified default. * Otherwise, if the value is invalid (not 0 or 1),  * change it to the default. */void __devinite100_set_bool_option(struct e100_private *bdp, int val, u32 mask,		     int default_val, char *name){	if (val == -1) {		if (default_val)			bdp->params.b_params |= mask;	} else if ((val != true) && (val != false)) {		printk(KERN_NOTICE		       "e100: Invalid %s specified (%i). "		       "Valid values are %i/%i\n",		       name, val, false, true);		printk(KERN_NOTICE "e100: Using default %s of %i\n", name,		       default_val);		if (default_val)			bdp->params.b_params |= mask;	} else {		printk(KERN_INFO "e100: Using specified %s of %i\n", name, val);		if (val)			bdp->params.b_params |= mask;	}}inte100_open(struct net_device *dev){	struct e100_private *bdp;	int rc = 0;	bdp = dev->priv;	/* setup the tcb pool */	if (!e100_alloc_tcb_pool(bdp)) {		rc = -ENOMEM;		goto err_exit;	}	bdp->last_tcb = NULL;	bdp->tcb_pool.head = 0;	bdp->tcb_pool.tail = 1;		e100_setup_tcb_pool((tcb_t *) bdp->tcb_pool.data,			    bdp->params.TxDescriptors, bdp);	if (!e100_alloc_rfd_pool(bdp)) {		rc = -ENOMEM;		goto err_exit;	}	if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0)) {		rc = -EAGAIN;		goto err_exit;	}	if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0)) {		rc = -EAGAIN;		goto err_exit;	}	mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ));	if (dev->flags & IFF_UP)		/* Otherwise process may sleep forever */		netif_wake_queue(dev);	else		netif_start_queue(dev);	e100_start_ru(bdp);	if ((rc = request_irq(dev->irq, &e100intr, SA_SHIRQ,			      dev->name, dev)) != 0) {		del_timer_sync(&bdp->watchdog_timer);		goto err_exit;	}	bdp->intr_mask = 0;	e100_set_intr_mask(bdp);	e100_force_config(bdp);	goto exit;err_exit:	e100_clear_pools(bdp);exit:	return rc;}inte100_close(struct net_device *dev){	struct e100_private *bdp = dev->priv;	e100_disable_clear_intr(bdp);	free_irq(dev->irq, dev);	bdp->intr_mask = SCB_INT_MASK;	e100_isolate_driver(bdp);	netif_carrier_off(bdp->device);	bdp->cur_line_speed = 0;	bdp->cur_dplx_mode = 0;	e100_clear_pools(bdp);	return 0;}static inte100_change_mtu(struct net_device *dev, int new_mtu){	if ((new_mtu < 68) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE)))		return -EINVAL;	dev->mtu = new_mtu;	return 0;}/** * e100_prepare_xmit_buff - prepare a buffer for transmission * @bdp: atapter's private data struct * @skb: skb to send * * This routine prepare a buffer for transmission. It checks * the message length for the appropiate size. It picks up a * free tcb from the TCB pool and sets up the corresponding * TBD's. If the number of fragments are more than the number * of TBD/TCB it copies all the fragments in a coalesce buffer. * It returns a pointer to the prepared TCB. */static inline tcb_t *e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb){	tcb_t *tcb, *prev_tcb;	tcb = bdp->tcb_pool.data;	tcb += TCB_TO_USE(bdp->tcb_pool);	if (bdp->flags & USE_IPCB) {		tcb->tcbu.ipcb.ip_activation_high = IPCB_IP_ACTIVATION_DEFAULT;		tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCP_PACKET;		tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCPUDP_CHECKSUM_ENABLE;	}	if(bdp->vlgrp && vlan_tx_tag_present(skb)) {		(tcb->tcbu).ipcb.ip_activation_high |= IPCB_INSERTVLAN_ENABLE;		(tcb->tcbu).ipcb.vlan = cpu_to_be16(vlan_tx_tag_get(skb));	}		tcb->tcb_hdr.cb_status = 0;	tcb->tcb_thrshld = bdp->tx_thld;	tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_S_BIT);	/* Set I (Interrupt) bit on every (TX_FRAME_CNT)th packet */	if (!(++bdp->tx_count % TX_FRAME_CNT))		tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_I_BIT);	else		/* Clear I bit on other packets */		tcb->tcb_hdr.cb_cmd &= ~__constant_cpu_to_le16(CB_I_BIT);	tcb->tcb_skb = skb;	if (skb->ip_summed == CHECKSUM_HW) {		const struct iphdr *ip = skb->nh.iph;		if ((ip->protocol == IPPROTO_TCP) ||		    (ip->protocol == IPPROTO_UDP)) {			tcb->tcbu.ipcb.ip_activation_high |=				IPCB_HARDWAREPARSING_ENABLE;			tcb->tcbu.ipcb.ip_schedule |=				IPCB_TCPUDP_CHECKSUM_ENABLE;			if (ip->protocol == IPPROTO_TCP)				tcb->tcbu.ipcb.ip_schedule |= IPCB_TCP_PACKET;		}	}	if (!skb_shinfo(skb)->nr_frags) {		(tcb->tbd_ptr)->tbd_buf_addr =			cpu_to_le32(pci_map_single(bdp->pdev, skb->data,						   skb->len, PCI_DMA_TODEVICE));		(tcb->tbd_ptr)->tbd_buf_cnt = cpu_to_le16(skb->len);		tcb->tcb_tbd_num = 1;		tcb->tcb_tbd_ptr = tcb->tcb_tbd_dflt_ptr;	} else {		int i;		void *addr;		tbd_t *tbd_arr_ptr = &(tcb->tbd_ptr[1]);		skb_frag_t *frag = &skb_shinfo(skb)->frags[0];		(tcb->tbd_ptr)->tbd_buf_addr =			cpu_to_le32(pci_map_single(bdp->pdev, skb->data,						   skb_headlen(skb),						   PCI_DMA_TODEVICE));		(tcb->tbd_ptr)->tbd_buf_cnt =			cpu_to_le16(skb_headlen(skb));		for (i = 0; i < skb_shinfo(skb)->nr_frags;		     i++, tbd_arr_ptr++, frag++) {			addr = ((void *) page_address(frag->page) +				frag->page_offset);			tbd_arr_ptr->tbd_buf_addr =				cpu_to_le32(pci_map_single(bdp->pdev,							   addr, frag->size,							   PCI_DMA_TODEVICE));			tbd_arr_ptr->tbd_buf_cnt = cpu_to_le16(frag->size);		}		tcb->tcb_tbd_num = skb_shinfo(skb)->nr_frags + 1;		tcb->tcb_tbd_ptr = tcb->tcb_tbd_expand_ptr;	}	/* clear the S-BIT on the previous tcb */	prev_tcb = bdp->tcb_pool.data;	prev_tcb += PREV_TCB_USED(bdp->tcb_pool);	prev_tcb->tcb_hdr.cb_cmd &= __constant_cpu_to_le16((u16) ~CB_S_BIT);	bdp->tcb_pool.tail = NEXT_TCB_TOUSE(bdp->tcb_pool.tail);	wmb();	e100_start_cu(bdp, tcb);	return tcb;}static inte100_xmit_frame(struct sk_buff *skb, struct net_device *dev){	int rc = 0;	int notify_stop = false;	struct e100_private *bdp = dev->priv;	if (!spin_trylock(&bdp->bd_non_tx_lock)) {		notify_stop = true;		rc = 1;		goto exit2;	}	/* tcb list may be empty temporarily during releasing resources */	if (!TCBS_AVAIL(bdp->tcb_pool) || (bdp->tcb_phys == 0) ||	    (bdp->non_tx_command_state != E100_NON_TX_IDLE)) {		notify_stop = true;		rc = 1;		goto exit1;	}	bdp->drv_stats.net_stats.tx_bytes += skb->len;	e100_prepare_xmit_buff(bdp, skb);	dev->trans_start = jiffies;exit1:	spin_unlock(&bdp->bd_non_tx_lock);exit2:	if (notify_stop) {		netif_stop_queue(dev);	}	return rc;}/** * e100_get_stats - get driver statistics * @dev: adapter's net_device struct * * This routine is called when the OS wants the adapter's stats returned. * It returns the address of the net_device_stats stucture for the device. * If the statistics are currently being updated, then they might be incorrect * for a short while. However, since this cannot actually cause damage, no * locking is used. */struct net_device_stats *e100_get_stats(struct net_device *dev){	struct e100_private *bdp = dev->priv;	bdp->drv_stats.net_stats.tx_errors =		bdp->drv_stats.net_stats.tx_carrier_errors +		bdp->drv_stats.net_stats.tx_aborted_errors;	bdp->drv_stats.net_stats.rx_errors =		bdp->drv_stats.net_stats.rx_crc_errors +		bdp->drv_stats.net_stats.rx_frame_errors +		bdp->drv_stats.net_stats.rx_length_errors +		bdp->drv_stats.rcv_cdt_frames;	return &(bdp->drv_stats.net_stats);}/** * e100_set_mac - set the MAC address * @dev: adapter's net_device struct * @addr: the new address * * This routine sets the ethernet address of the board * Returns: * 0  - if successful * -1 - otherwise */static inte100_set_mac(struct net_device *dev, void *addr){	struct e100_private *bdp;	int rc = -1;	struct sockaddr *p_sockaddr = (struct sockaddr *) addr;	if (!is_valid_ether_addr(p_sockaddr->sa_data))		return -EADDRNOTAVAIL;	bdp = dev->priv;	if (e100_setup_iaaddr(bdp, (u8 *) (p_sockaddr->sa_data))) {		memcpy(&(dev->dev_addr[0]), p_sockaddr->sa_data, ETH_ALEN);		rc = 0;	}	return rc;}static voide100_set_multi_exec(struct net_device *dev){	struct e100_private *bdp = dev->priv;	mltcst_cb_t *mcast_buff;	cb_header_t *cb_hdr;	struct dev_mc_list *mc_list;	unsigned int i;	nxmit_cb_entry_t *cmd = e100_alloc_non_tx_cmd(bdp);	if (cmd != NULL) {		mcast_buff = &((cmd->non_tx_cmd)->ntcb.multicast);		cb_hdr = &((cmd->non_tx_cmd)->ntcb.multicast.mc_cbhdr);	} else {		return;	}	/* initialize the multi cast command */	cb_hdr->cb_cmd = __constant_cpu_to_le16(CB_MULTICAST);	/* now fill in the rest of the multicast command */	*(u16 *) (&(mcast_buff->mc_count)) = cpu_to_le16(dev->mc_count * 6);	for (i = 0, mc_list = dev->mc_list;	     (i < dev->mc_count) && (i < MAX_MULTICAST_ADDRS);	     i++, mc_list = mc_list->next) {		/* copy into the command */		memcpy(&(mcast_buff->mc_addr[i * ETH_ALEN]),		       (u8 *) &(mc_list->dmi_addr), ETH_ALEN);	}	if (!e100_exec_non_cu_cmd(bdp, cmd)) {		printk(KERN_WARNING "e100: %s: Multicast setup failed\n", 		       dev->name);	}}/** * e100_set_multi - set multicast status * @dev: adapter's net_device struct * * This routine is called to add or remove multicast addresses, and/or to * change the adapter's promiscuous state. */static voide100_set_multi(struct net_device *dev){	struct e100_private *bdp = dev->priv;	unsigned char promisc_enbl;	unsigned char mulcast_enbl;	promisc_enbl = ((dev->flags & IFF_PROMISC) == IFF_PROMISC);	mulcast_enbl = ((dev->flags & IFF_ALLMULTI) ||			(dev->mc_count > MAX_MULTICAST_ADDRS));	e100_config_promisc(bdp, promisc_enbl);	e100_config_mulcast_enbl(bdp, mulcast_enbl);	/* reconfigure the chip if something has changed in its config space */	e100_config(bdp);	if (promisc_enbl || mulcast_enbl) {		return;	/* no need for Multicast Cmd */	}	/* get the multicast CB */	e100_set_multi_exec(dev);}static inte100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){	switch (cmd) {	case SIOCETHTOOL:		return e100_do_ethtool_ioctl(dev, ifr);		break;	case SIOCGMIIPHY:	/* Get address of MII PHY in use. */	case SIOCGMIIREG:	/* Read MII PHY register. */

⌨️ 快捷键说明

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