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

📄 ibm_ocp_enet.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
			if (ctrl & EMAC_RX_ST_OE)				fep->stats.rx_fifo_errors++;			if (ctrl & EMAC_RX_ST_AE)				fep->stats.rx_frame_errors++;			if (ctrl & EMAC_RX_ST_BFCS)				fep->stats.rx_crc_errors++;			if (ctrl & (EMAC_RX_ST_RP | EMAC_RX_ST_PTL |				    EMAC_RX_ST_ORE | EMAC_RX_ST_IRE))				fep->stats.rx_length_errors++;		} else {			/* Send the skb up the chain. */		frame_length = fep->rx_desc[i].data_len - 4;			skb_put(fep->rx_skb[i], frame_length);			fep->rx_skb[i]->dev = dev;			fep->rx_skb[i]->protocol =			    eth_type_trans(fep->rx_skb[i], dev);			error = netif_rx(fep->rx_skb[i]);			if ((error == NET_RX_DROP) || (error == NET_RX_BAD)) {				fep->stats.rx_dropped++;			} else {				fep->stats.rx_packets++;				fep->stats.rx_bytes += frame_length;			}			fep->rx_skb[i] = NULL;		}	      skip:		slots_walked = 1;	} while ((i = (i + 1) % NUM_RX_BUFF) != fep->rx_slot);	PKT_DEBUG(("emac_rx_clean() exit, rx_slot: %d\n", fep->rx_slot));	if (slots_walked && call_rx_fill)           emac_rx_fill(dev, i);}static voidemac_rxeob_dev(void *param, u32 chanmask){	struct net_device *dev = param;	struct ocp_enet_private *fep = dev->priv;        unsigned long flags;	spin_lock_irqsave(&fep->lock, flags);	emac_rx_clean(dev, 1);	spin_unlock_irqrestore(&fep->lock, flags);}/* * This interrupt should never occurr, we don't program * the MAL for contiunous mode. */static voidemac_txde_dev(void *param, u32 chanmask){	struct net_device *dev = param;	struct ocp_enet_private *fep = dev->priv;	printk(KERN_WARNING "%s: transmit descriptor error\n", dev->name);	emac_mac_dump(dev);	emac_mal_dump(dev);	/* Reenable the transmit channel */	mal_enable_tx_channels(fep->mal, fep->commac.tx_chan_mask);}/* * This interrupt should be very rare at best.  This occurs when * the hardware has a problem with the receive descriptors.  The manual * states that it occurs when the hardware cannot the receive descriptor * empty bit is not set.  The recovery mechanism will be to * traverse through the descriptors, handle any that are marked to be * handled and reinitialize each along the way.  At that point the driver * will be restarted. */static voidemac_rxde_dev(void *param, u32 chanmask){ 	struct net_device *dev = param;     	struct ocp_enet_private *fep = dev->priv;        unsigned long flags;	printk(KERN_WARNING "%s: receive descriptor error\n", fep->ndev->name);	emac_mac_dump(dev);	emac_mal_dump(dev);	emac_desc_dump(dev);	/* Disable RX channel */	spin_lock_irqsave(&fep->lock, flags);       	mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask);       		/* For now, charge the error against all emacs */	fep->stats.rx_errors++;	/* so do we have any good packets still? */	emac_rx_clean(dev,0);	/* When the interface is restarted it resets processing to the	 *  first descriptor in the table.	 */	fep->rx_slot = 0;	emac_rx_fill(dev, 0);	set_mal_dcrn(fep->mal, DCRN_MALRXEOBISR, fep->commac.rx_chan_mask);	set_mal_dcrn(fep->mal, DCRN_MALRXDEIR, fep->commac.rx_chan_mask);	/* Reenable the receive channels */       	mal_enable_rx_channels(fep->mal, fep->commac.rx_chan_mask);	spin_unlock_irqrestore(&fep->lock, flags);}static voidemac_mac_irq(int irq, void *dev_instance, struct pt_regs *regs){	struct net_device *dev = dev_instance;	struct ocp_enet_private *fep = dev->priv;	volatile emac_t *emacp = fep->emacp;	unsigned long tmp_em0isr;	/* EMAC interrupt */	tmp_em0isr = in_be32(&emacp->em0isr);	if (tmp_em0isr & (EMAC_ISR_TE0 | EMAC_ISR_TE1)) {		/* This error is a hard transmit error - could retransmit */		fep->stats.tx_errors++;		/* Reenable the transmit channel */		mal_enable_tx_channels(fep->mal, fep->commac.tx_chan_mask);	} else {		fep->stats.rx_errors++;	}	if (tmp_em0isr & EMAC_ISR_RP)		fep->stats.rx_length_errors++;	if (tmp_em0isr & EMAC_ISR_ALE)		fep->stats.rx_frame_errors++;	if (tmp_em0isr & EMAC_ISR_BFCS)		fep->stats.rx_crc_errors++;	if (tmp_em0isr & EMAC_ISR_PTLE)		fep->stats.rx_length_errors++;	if (tmp_em0isr & EMAC_ISR_ORE)		fep->stats.rx_length_errors++;	if (tmp_em0isr & EMAC_ISR_TE0)		fep->stats.tx_aborted_errors++;	emac_err_dump(dev, tmp_em0isr);	out_be32(&emacp->em0isr, tmp_em0isr);}static intemac_start_xmit(struct sk_buff *skb, struct net_device *dev){	unsigned short ctrl;	unsigned long flags;	struct ocp_enet_private *fep = dev->priv;	volatile emac_t *emacp = fep->emacp;        spin_lock_irqsave(&fep->lock, flags);	PKT_DEBUG(("emac_start_xmit() entry, queue stopped: %d, fep->tx_cnt: %d\n",		netif_queue_stopped(dev), fep->tx_cnt));	/* That shouldn't happen... */	if (netif_queue_stopped(dev) || (fep->tx_cnt == NUM_TX_BUFF)) {		printk("%s: start_xmit called on full queue !\n", dev->name);		BUG();	}	if (++fep->tx_cnt == NUM_TX_BUFF) {		PKT_DEBUG(("emac_start_xmit() stopping queue\n"));		netif_stop_queue(dev);	}		/* Store the skb buffer for later ack by the transmit end of buffer	 * interrupt.	 */	fep->tx_skb[fep->tx_slot] = skb;	consistent_sync((void *) skb->data, skb->len, PCI_DMA_TODEVICE);	ctrl = EMAC_TX_CTRL_DFLT;	if ((NUM_TX_BUFF - 1) == fep->tx_slot)		ctrl |= MAL_TX_CTRL_WRAP;	fep->tx_desc[fep->tx_slot].data_ptr = (char *) virt_to_phys(skb->data);	fep->tx_desc[fep->tx_slot].data_len = (short) skb->len;	fep->tx_desc[fep->tx_slot].ctrl = ctrl;	/* Send the packet out. */	out_be32(&emacp->em0tmr0, EMAC_TMR0_XMIT);	if (++fep->tx_slot == NUM_TX_BUFF)		fep->tx_slot = 0;	fep->stats.tx_packets++;	fep->stats.tx_bytes += skb->len;	PKT_DEBUG(("emac_start_xmit() exitn"));        spin_unlock_irqrestore(&fep->lock, flags);	return 0;}static intemac_adjust_to_link(struct ocp_enet_private *fep){	volatile emac_t *emacp = fep->emacp;	unsigned long mode_reg;	int full_duplex, speed;	full_duplex = 0;	speed = SPEED_10;	/* set mode register 1 defaults */	mode_reg = EMAC_M1_DEFAULT;	/* Read link mode on PHY */    	if (fep->phy_mii.def->ops->read_link(&fep->phy_mii) == 0) {	        /* If an error occurred, we don't deal with it yet */		full_duplex = (fep->phy_mii.duplex == DUPLEX_FULL);		speed = fep->phy_mii.speed;	        	}	/* set speed (default is 10Mb) */	if (speed == SPEED_100) {		mode_reg |= EMAC_M1_MF_100MBPS;		if (fep->zmii_dev)			emac_zmii_port_speed(fep->zmii_dev, fep->zmii_input, 100);	} else {		mode_reg &= ~EMAC_M1_MF_100MBPS;		if (fep->zmii_dev)			emac_zmii_port_speed(fep->zmii_dev, fep->zmii_input, 10);	}	if (full_duplex)		mode_reg |= EMAC_M1_FDE | EMAC_M1_EIFC | EMAC_M1_IST;	else		mode_reg &= ~(EMAC_M1_FDE | EMAC_M1_EIFC | EMAC_M1_ILE);        LINK_DEBUG(("%s: adjust to link, speed: %d, duplex: %d, opened: %d\n",            fep->ndev->name, speed, full_duplex, fep->opened));        printk(KERN_INFO "%s: Speed: %s, %s duplex.\n",	       fep->ndev->name,	       speed == SPEED_100 ? "100" : "10",	       full_duplex ? "Full" : "Half");	if (fep->opened)	        out_be32(&emacp->em0mr1, mode_reg);	return 0;}static void__emac_set_multicast_list(struct net_device *dev){	struct ocp_enet_private *fep = dev->priv;	volatile emac_t *emacp = fep->emacp;	u32 rmr = in_be32(&emacp->em0rmr);		/* First clear all special bits, they can be set later */	rmr &= ~(EMAC_RMR_PME | EMAC_RMR_PMME | EMAC_RMR_MAE);		if (dev->flags & IFF_PROMISC) {		rmr |= EMAC_RMR_PME;	} else if (dev->flags & IFF_ALLMULTI || 32 < dev->mc_count) {		/* Must be setting up to use multicast.  Now check for promiscuous		 * multicast		 */		rmr |= EMAC_RMR_PMME;	} else if (dev->flags & IFF_MULTICAST && 0 < dev->mc_count) {		unsigned short em0gaht[4] = { 0, 0, 0, 0 };		struct dev_mc_list *dmi;		/* Need to hash on the multicast address. */		for (dmi = dev->mc_list; dmi; dmi = dmi->next) {			unsigned long mc_crc;			unsigned int bit_number;			mc_crc = ether_crc(6, (char *) dmi->dmi_addr);			bit_number = 63 - (mc_crc >> 26);	/* MSB: 0 LSB: 63 */			em0gaht[bit_number >> 4] |=			    0x8000 >> (bit_number & 0x0f);		}		emacp->em0gaht1 = em0gaht[0];		emacp->em0gaht2 = em0gaht[1];		emacp->em0gaht3 = em0gaht[2];		emacp->em0gaht4 = em0gaht[3];		/* Turn on multicast addressing */		rmr |= EMAC_RMR_MAE;	}		out_be32(&emacp->em0rmr, rmr);}static voidemac_init_rings(struct net_device *dev){	struct ocp_enet_private *ep = dev->priv;	int loop;	ep->tx_desc = (struct mal_descriptor *) ((char *) ep->mal->tx_virt_addr +				      (ep->mal_tx_chan * MAL_DT_ALIGN));	ep->rx_desc = (struct mal_descriptor *) ((char *) ep->mal->rx_virt_addr +				      (ep->mal_rx_chan * MAL_DT_ALIGN));	/* Fill in the transmit descriptor ring. */	for (loop = 0; loop < NUM_TX_BUFF; loop++) {                if (ep->tx_skb[loop])                        dev_kfree_skb_irq(ep->tx_skb[loop]);		ep->tx_skb[loop] = NULL;		ep->tx_desc[loop].ctrl = 0;		ep->tx_desc[loop].data_len = 0;		ep->tx_desc[loop].data_ptr = NULL;	}	ep->tx_desc[loop - 1].ctrl |= MAL_TX_CTRL_WRAP;	/* Format the receive descriptor ring. */	ep->rx_slot = 0;	emac_rx_fill(dev, 0);	if (ep->rx_slot != 0) {		printk(KERN_ERR		       "%s: Not enough mem for RxChain durning Open?\n",		       dev->name);		/*We couldn't fill the ring at startup?		 *We could clean up and fail to open but right now we will try to		 *carry on. It may be a sign of a bad NUM_RX_BUFF value		 */	}	ep->tx_cnt = 0;	ep->tx_slot = 0;	ep->ack_slot = 0;}static voidemac_reset_configure(struct ocp_enet_private *fep){	volatile emac_t *emacp = fep->emacp;        int i;	mal_disable_tx_channels(fep->mal, fep->commac.tx_chan_mask);	mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask);	/* Reset the EMAC */	out_be32(&emacp->em0mr0, EMAC_M0_SRST);	udelay(20);        for (i=0; i<100; i++) {                if ((in_be32(&emacp->em0mr0) & EMAC_M0_SRST) == 0)                        break;                udelay(10);        }	        if (i >= 100) {                printk(KERN_ERR "%s: Cannot reset EMAC\n", fep->ndev->name);		return;        }	/* Switch IRQs off for now */	out_be32(&emacp->em0iser, 0);	/* Configure MAL rx channel */	mal_set_rcbs(fep->mal, fep->mal_rx_chan, DESC_BUF_SIZE_REG);	/* set the high address */	out_be32(&emacp->em0iahr, (fep->ndev->dev_addr[0] << 8) | fep->ndev->dev_addr[1]);	/* set the low address */	out_be32(&emacp->em0ialr,		 (fep->ndev->dev_addr[2] << 24) | (fep->ndev->dev_addr[3] << 16)		 | (fep->ndev->dev_addr[4] << 8) | fep->ndev->dev_addr[5]);        /* Adjust to link */	if (netif_carrier_ok(fep->ndev))	    emac_adjust_to_link(fep);	/* enable broadcast/individual address and RX FIFO defaults */	out_be32(&emacp->em0rmr, EMAC_RMR_DEFAULT);	/* set transmit request threshold register */	out_be32(&emacp->em0trtr, EMAC_TRTR_DEFAULT);        /* Reconfigure multicast */        __emac_set_multicast_list(fep->ndev);	/* Set receiver/transmitter defaults */	out_be32(&emacp->em0rwmr, EMAC_RWMR_DEFAULT);	out_be32(&emacp->em0tmr0, EMAC_TMR0_DEFAULT);	out_be32(&emacp->em0tmr1, EMAC_TMR1_DEFAULT);	/* set frame gap */	out_be32(&emacp->em0ipgvr, CONFIG_IBM_OCP_ENET_GAP);        /* Init ring buffers */        emac_init_rings(fep->ndev);}static voidemac_kick(struct ocp_enet_private *fep){	volatile emac_t *emacp = fep->emacp;	unsigned long emac_ier;	emac_ier = EMAC_ISR_PP | EMAC_ISR_BP | EMAC_ISR_RP |	    EMAC_ISR_SE | EMAC_ISR_PTLE | EMAC_ISR_ALE |	    EMAC_ISR_BFCS | EMAC_ISR_ORE | EMAC_ISR_IRE;	out_be32(&emacp->em0iser, emac_ier);	/* enable all MAL transmit and receive channels */	mal_enable_tx_channels(fep->mal, fep->commac.tx_chan_mask);	mal_enable_rx_channels(fep->mal, fep->commac.rx_chan_mask);	/* set transmit and receive enable */	out_be32(&emacp->em0mr0, EMAC_M0_TXE | EMAC_M0_RXE);}static voidemac_start_link(struct ocp_enet_private *fep, struct ethtool_cmd *ep){	u32 advertise;	int autoneg;	int forced_speed;	int forced_duplex;	/* Default advertise */	advertise = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |		    ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;	autoneg = fep->want_autoneg;	forced_speed = fep->phy_mii.speed;	forced_duplex = fep->phy_mii.duplex;	/* Setup link parameters */	if (ep) {	    if (ep->autoneg == AUTONEG_ENABLE) {		advertise = ep->advertising;		autoneg = 1;	    } else {		autoneg = 0;		forced_speed = ep->speed;		forced_duplex = ep->duplex;	    }	}	/* Configure PHY & start aneg */	fep->want_autoneg = autoneg;	if (autoneg) {                LINK_DEBUG(("%s: start link aneg, advertise: 0x%x\n",                        fep->ndev->name, advertise));		fep->phy_mii.def->ops->setup_aneg(&fep->phy_mii, advertise);        } else {                LINK_DEBUG(("%s: start link forced, speed: %d, duplex: %d\n",                        fep->ndev->name, forced_speed, forced_duplex));		fep->phy_mii.def->ops->setup_forced(&fep->phy_mii, forced_speed,				forced_duplex);        }	fep->timer_ticks = 0;	mod_timer(&fep->link_timer, jiffies + HZ);}static voidemac_link_timer(unsigned long data){        struct ocp_enet_private *fep = (struct ocp_enet_private *)data;	int link;	if (fep->going_away)		return;	spin_lock_irq(&fep->lock);		link = fep->phy_mii.def->ops->poll_link(&fep->phy_mii);        LINK_DEBUG(("%s: poll_link: %d\n", fep->ndev->name, link));

⌨️ 快捷键说明

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