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

📄 e100_main.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 5 页
字号:
e100_open(struct net_device *dev){	struct e100_private *bdp;	int rc = 0;	bdp = dev->priv;	read_lock(&(bdp->isolate_lock));	if (bdp->driver_isolated) {		rc = -EBUSY;		goto exit;	}	/* 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)) {		rc = -EAGAIN;		goto err_exit;	}	if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE)) {		rc = -EAGAIN;		goto err_exit;	}	mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ));	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:	read_unlock(&(bdp->isolate_lock));	return rc;}static inte100_close(struct net_device *dev){	struct e100_private *bdp = dev->priv;	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;	free_irq(dev->irq, dev);	e100_clear_pools(bdp);	/* set the isolate flag to false, so e100_open can be called */	bdp->driver_isolated = false;	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;}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;	read_lock(&(bdp->isolate_lock));	if (bdp->driver_isolated) {		rc = -EBUSY;		goto exit2;	}	if (!spin_trylock(&bdp->bd_non_tx_lock)) {		notify_stop = true;		rc = 1;		goto exit2;	}	if (!TCBS_AVAIL(bdp->tcb_pool) ||	    (bdp->non_tx_command_state != E100_NON_TX_IDLE)) {		notify_stop = true;		rc = 1;		goto exit1;	}	e100_prepare_xmit_buff(bdp, skb);	bdp->drv_stats.net_stats.tx_bytes += skb->len;	dev->trans_start = jiffies;exit1:	spin_unlock(&bdp->bd_non_tx_lock);exit2:	read_unlock(&(bdp->isolate_lock));	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;	bdp = dev->priv;	read_lock(&(bdp->isolate_lock));	if (bdp->driver_isolated) {		goto exit;	}	if (e100_setup_iaaddr(bdp, (u8 *) (p_sockaddr->sa_data))) {		memcpy(&(dev->dev_addr[0]), p_sockaddr->sa_data, ETH_ALEN);		rc = 0;	}exit:	read_unlock(&(bdp->isolate_lock));	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;	read_lock(&(bdp->isolate_lock));	if (bdp->driver_isolated) {		goto exit;	}	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) {		goto exit;	/* no need for Multicast Cmd */	}	/* get the multicast CB */	e100_set_multi_exec(dev);exit:	read_unlock(&(bdp->isolate_lock));}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. */	case SIOCSMIIREG:	/* Write to MII PHY register. */		return e100_mii_ioctl(dev, ifr, cmd);		break;	default:		return -EOPNOTSUPP;	}	return 0;}/** * e100init - initialize the adapter * @bdp: atapter's private data struct * * This routine is called when this driver is loaded. This is the initialization * routine which allocates memory, configures the adapter and determines the * system resources. * * Returns: *      true: if successful *      false: otherwise */static unsigned char __devinite100_init(struct e100_private *bdp){	u32 st_timeout = 0;	u32 st_result = 0;	e100_sw_init(bdp);	if (!e100_selftest(bdp, &st_timeout, &st_result)) {        	if (st_timeout) {			printk(KERN_ERR "e100: selftest timeout\n");		} else {			printk(KERN_ERR "e100: selftest failed. Results: %x\n",					st_result);		}		return false;	}	else		printk(KERN_DEBUG "e100: selftest OK.\n");	/* read the MAC address from the eprom */	e100_rd_eaddr(bdp);	/* read NIC's part number */	e100_rd_pwa_no(bdp);	if (!e100_hw_init(bdp, PORT_SOFTWARE_RESET)) {		printk(KERN_ERR "e100: hw init failed\n");		return false;	}	e100_dis_intr(bdp);	return true;}/** * e100_sw_init - initialize software structs * @bdp: atapter's private data struct *  * This routine initializes all software structures. Sets up the * circular structures for the RFD's & TCB's. Allocates the per board * structure for storing adapter information. The CSR is also memory  * mapped in this routine. * * Returns : *      true: if S/W was successfully initialized *      false: otherwise */static unsigned char __devinite100_sw_init(struct e100_private *bdp){	bdp->next_cu_cmd = START_WAIT;	// init the next cu state	/* 	 * Set the value for # of good xmits per underrun. the value assigned	 * here is an intelligent  suggested default. Nothing magical about it.	 */	bdp->tx_per_underrun = DEFAULT_TX_PER_UNDERRUN;	/* get the default transmit threshold value */	bdp->tx_thld = TX_THRSHLD;	/* get the EPROM size */	bdp->eeprom_size = e100_eeprom_size(bdp);	/* Initialize our spinlocks */	spin_lock_init(&(bdp->bd_lock));	spin_lock_init(&(bdp->bd_non_tx_lock));	spin_lock_init(&(bdp->config_lock));	spin_lock_init(&(bdp->mdi_access_lock));	bdp->isolate_lock = RW_LOCK_UNLOCKED;	bdp->driver_isolated = false;	return 1;}/** * e100_hw_init - initialized tthe hardware * @bdp: atapter's private data struct * @reset_cmd: s/w reset or selective reset * * This routine performs a reset on the adapter, and configures the adapter. * This includes configuring the 82557 LAN controller, validating and setting * the node address, detecting and configuring the Phy chip on the adapter, * and initializing all of the on chip counters. * * Returns: *      true - If the adapter was initialized *      false - If the adapter failed initialization */unsigned char __devinite100_hw_init(struct e100_private *bdp, u32 reset_cmd){	if (!e100_phy_init(bdp))		return false;	/* Issue a software reset to the e100 */	e100_sw_reset(bdp, reset_cmd);	/* Load the CU BASE (set to 0, because we use linear mode) */	if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE))		return false;	if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE))		return false;	/* Load interrupt microcode  */	if (e100_load_microcode(bdp)) {		bdp->flags |= DF_UCODE_LOADED;	}	e100_config_init(bdp);	if (!e100_config(bdp)) {		return false;	}	if (!e100_setup_iaaddr(bdp, bdp->device->dev_addr))		return false;	/* Clear the internal counters */	if (!e100_clr_cntrs(bdp))		return false;	/* Change for 82558 enhancement */	/* If 82558/9 and if the user has enabled flow control, set up the	 * Flow Control Reg. in the CSR */	if ((bdp->flags & IS_BACHELOR)	    && (bdp->params.b_params & PRM_FC)) {		writeb(DFLT_FC_THLD, &bdp->scb->scb_ext.d101_scb.scb_fc_thld);		writeb(DFLT_FC_CMD,		       &bdp->scb->scb_ext.d101_scb.scb_fc_xon_xoff);	}	return true;}/** * e100_setup_tcb_pool - setup TCB circular list * @head: Pointer to head of the allocated TCBs * @qlen: Number of elements in the queue * @bdp: atapter's private data struct *  * This routine arranges the contigiously allocated TCB's in a circular list. * Also does the one time initialization of the TCBs. */static voide100_setup_tcb_pool(tcb_t *head, unsigned int qlen, struct e100_private *bdp){	int ele_no;	tcb_t *pcurr_tcb;	/* point to current tcb */	u32 next_phys;		/* the next phys addr */	u16 txcommand = CB_S_BIT | CB_TX_SF_BIT;	if (bdp->flags & USE_IPCB) {		txcommand |= CB_IPCB_TRANSMIT | CB_CID_DEFAULT;

⌨️ 快捷键说明

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