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

📄 fcc_enet.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	ep->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB) << 24;	ep->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB) << 24;	/* Set maximum bytes per receive buffer.	 * It must be a multiple of 32.	 */	ep->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;	/* Allocate space in the reserved FCC area of DPRAM for the	 * internal buffers.  No one uses this space (yet), so we	 * can do this.  Later, we will add resource management for	 * this area.	 */	mem_addr = CPM_FCC_SPECIAL_BASE + (fip->fc_fccnum * 128);	ep->fen_genfcc.fcc_riptr = mem_addr;	ep->fen_genfcc.fcc_tiptr = mem_addr+32;	ep->fen_padptr = mem_addr+64;	memset((char *)(&(immap->im_dprambase[(mem_addr+64)])), 0x88, 32);	ep->fen_genfcc.fcc_rbptr = 0;	ep->fen_genfcc.fcc_tbptr = 0;	ep->fen_genfcc.fcc_rcrc = 0;	ep->fen_genfcc.fcc_tcrc = 0;	ep->fen_genfcc.fcc_res1 = 0;	ep->fen_genfcc.fcc_res2 = 0;	ep->fen_camptr = 0;	/* CAM isn't used in this driver */	/* Set CRC preset and mask.	*/	ep->fen_cmask = 0xdebb20e3;	ep->fen_cpres = 0xffffffff;	ep->fen_crcec = 0;	/* CRC Error counter */	ep->fen_alec = 0;	/* alignment error counter */	ep->fen_disfc = 0;	/* discard frame counter */	ep->fen_retlim = 15;	/* Retry limit threshold */	ep->fen_pper = 0;	/* Normal persistence */	/* Clear hash filter tables.	*/	ep->fen_gaddrh = 0;	ep->fen_gaddrl = 0;	ep->fen_iaddrh = 0;	ep->fen_iaddrl = 0;	/* Clear the Out-of-sequence TxBD.	*/	ep->fen_tfcstat = 0;	ep->fen_tfclen = 0;	ep->fen_tfcptr = 0;	ep->fen_mflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */	ep->fen_minflr = PKT_MINBUF_SIZE;  /* minimum frame length register */	/* Set Ethernet station address.	 *	 * This is supplied in the board information structure, so we	 * copy that into the controller.	 * So, far we have only been given one Ethernet address. We make	 * it unique by setting a few bits in the upper byte of the	 * non-static part of the address.	 */	eap = (unsigned char *)&(ep->fen_paddrh);	for (i=5; i>=0; i--) {/* * The EP8260 only uses FCC3, so we can safely give it the real * MAC address. */#ifdef CONFIG_SBC82xx		if (i == 5) {			/* bd->bi_enetaddr holds the SCC0 address; the FCC			   devices count up from there */			dev->dev_addr[i] = bd->bi_enetaddr[i] & ~3;			dev->dev_addr[i] += 1 + fip->fc_fccnum;			*eap++ = dev->dev_addr[i];		}#else#ifndef CONFIG_RPX8260		if (i == 3) {			dev->dev_addr[i] = bd->bi_enetaddr[i];			dev->dev_addr[i] |= (1 << (7 - fip->fc_fccnum));			*eap++ = dev->dev_addr[i];		} else#endif		{			*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];		}#endif	}	ep->fen_taddrh = 0;	ep->fen_taddrm = 0;	ep->fen_taddrl = 0;	ep->fen_maxd1 = PKT_MAXDMA_SIZE;	/* maximum DMA1 length */	ep->fen_maxd2 = PKT_MAXDMA_SIZE;	/* maximum DMA2 length */	/* Clear stat counters, in case we ever enable RMON.	*/	ep->fen_octc = 0;	ep->fen_colc = 0;	ep->fen_broc = 0;	ep->fen_mulc = 0;	ep->fen_uspc = 0;	ep->fen_frgc = 0;	ep->fen_ospc = 0;	ep->fen_jbrc = 0;	ep->fen_p64c = 0;	ep->fen_p65c = 0;	ep->fen_p128c = 0;	ep->fen_p256c = 0;	ep->fen_p512c = 0;	ep->fen_p1024c = 0;	ep->fen_rfthr = 0;	/* Suggested by manual */	ep->fen_rfcnt = 0;	ep->fen_cftype = 0;	/* Now allocate the host memory pages and initialize the	 * buffer descriptors.	 */	bdp = cep->tx_bd_base;	for (i=0; i<TX_RING_SIZE; i++) {		/* Initialize the BD for every fragment in the page.		*/		bdp->cbd_sc = 0;		bdp->cbd_datlen = 0;		bdp->cbd_bufaddr = 0;		bdp++;	}	/* Set the last buffer to wrap.	*/	bdp--;	bdp->cbd_sc |= BD_SC_WRAP;	bdp = cep->rx_bd_base;	for (i=0; i<FCC_ENET_RX_PAGES; i++) {		/* Allocate a page.		*/		mem_addr = __get_free_page(GFP_KERNEL);		/* Initialize the BD for every fragment in the page.		*/		for (j=0; j<FCC_ENET_RX_FRPPG; j++) {			bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;			bdp->cbd_datlen = 0;			bdp->cbd_bufaddr = __pa(mem_addr);			mem_addr += FCC_ENET_RX_FRSIZE;			bdp++;		}	}	/* Set the last buffer to wrap.	*/	bdp--;	bdp->cbd_sc |= BD_SC_WRAP;	/* Let's re-initialize the channel now.  We have to do it later	 * than the manual describes because we have just now finished	 * the BD initialization.	 */	cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock, 0x0c,			CPM_CR_INIT_TRX) | CPM_CR_FLG;	while (cp->cp_cpcr & CPM_CR_FLG);	cep->skb_cur = cep->skb_dirty = 0;}/* Let 'er rip.*/static void __initinit_fcc_startup(fcc_info_t *fip, struct net_device *dev){	volatile fcc_t	*fccp;	struct fcc_enet_private *cep;	cep = (struct fcc_enet_private *)(dev->priv);	fccp = cep->fccp;#ifdef CONFIG_RPX8260#ifdef PHY_INTERRUPT	/* Route PHY interrupt to IRQ.  The following code only works for	 * IRQ1 - IRQ7.  It does not work for Port C interrupts.	 */	*((volatile u_char *) (RPX_CSR_ADDR + 13)) &= ~BCSR13_FETH_IRQMASK;	*((volatile u_char *) (RPX_CSR_ADDR + 13)) |=		((PHY_INTERRUPT - SIU_INT_IRQ1 + 1) << 4);#endif	/* Initialize MDIO pins. */	*((volatile u_char *) (RPX_CSR_ADDR + 4)) &= ~BCSR4_MII_MDC;	*((volatile u_char *) (RPX_CSR_ADDR + 4)) |=		BCSR4_MII_READ | BCSR4_MII_MDIO;	/* Enable external LXT971 PHY. */	*((volatile u_char *) (RPX_CSR_ADDR + 4)) |= BCSR4_EN_PHY;	udelay(1000);	*((volatile u_char *) (RPX_CSR_ADDR+ 4)) |= BCSR4_EN_MII;	udelay(1000);#endif	/* ifdef CONFIG_RPX8260 */	fccp->fcc_fcce = 0xffff;	/* Clear any pending events */	/* Leave FCC interrupts masked for now.  Will be unmasked by	 * fcc_restart().	 */	fccp->fcc_fccm = 0;	/* Install our interrupt handler.	*/	if (request_irq(fip->fc_interrupt, fcc_enet_interrupt, 0, "fenet",				dev) < 0)		printk("Can't get FCC IRQ %d\n", fip->fc_interrupt);#ifdef	PHY_INTERRUPT#ifdef CONFIG_ADS8272	if (request_irq(PHY_INTERRUPT, mii_link_interrupt, SA_SHIRQ,				"mii", dev) < 0)		printk(KERN_CRIT "Can't get MII IRQ %d\n", PHY_INTERRUPT);#else	/* Make IRQn edge triggered.  This does not work if PHY_INTERRUPT is	 * on Port C.	 */	((volatile cpm2_map_t *) CPM_MAP_ADDR)->im_intctl.ic_siexr |=		(1 << (14 - (PHY_INTERRUPT - SIU_INT_IRQ1)));	if (request_irq(PHY_INTERRUPT, mii_link_interrupt, 0,							"mii", dev) < 0)		printk(KERN_CRIT "Can't get MII IRQ %d\n", PHY_INTERRUPT);#endif#endif	/* PHY_INTERRUPT */	/* Set GFMR to enable Ethernet operating mode.	 */	fccp->fcc_gfmr = (FCC_GFMR_TCI | FCC_GFMR_MODE_ENET);	/* Set sync/delimiters.	*/	fccp->fcc_fdsr = 0xd555;	/* Set protocol specific processing mode for Ethernet.	 * This has to be adjusted for Full Duplex operation after we can	 * determine how to detect that.	 */	fccp->fcc_fpsmr = FCC_PSMR_ENCRC;#ifdef CONFIG_PQ2ADS	/* Enable the PHY. */	*(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_FETHIEN;	*(volatile uint *)(BCSR_ADDR + 4) |=  BCSR1_FETH_RST;#endif#if defined(CONFIG_PQ2ADS) || defined(CONFIG_PQ2FADS)	/* Enable the 2nd PHY. */	*(volatile uint *)(BCSR_ADDR + 12) &= ~BCSR3_FETHIEN2;	*(volatile uint *)(BCSR_ADDR + 12) |=  BCSR3_FETH2_RST;#endif#if defined(CONFIG_USE_MDIO) || defined(CONFIG_TQM8260)	/* start in full duplex mode, and negotiate speed	 */	fcc_restart (dev, 1);#else	/* start in half duplex mode	 */	fcc_restart (dev, 0);#endif}#ifdef	CONFIG_USE_MDIO/* MII command/status interface. * I'm not going to describe all of the details.  You can find the * protocol definition in many other places, including the data sheet * of most PHY parts. * I wonder what "they" were thinking (maybe weren't) when they leave * the I2C in the CPM but I have to toggle these bits...... */#ifdef CONFIG_RPX8260	/* The EP8260 has the MDIO pins in a BCSR instead of on Port C	 * like most other boards.	 */#define MDIO_ADDR ((volatile u_char *)(RPX_CSR_ADDR + 4))#define MAKE_MDIO_OUTPUT *MDIO_ADDR &= ~BCSR4_MII_READ#define MAKE_MDIO_INPUT  *MDIO_ADDR |=  BCSR4_MII_READ | BCSR4_MII_MDIO#define OUT_MDIO(bit)				\	if (bit)				\		*MDIO_ADDR |=  BCSR4_MII_MDIO;	\	else					\		*MDIO_ADDR &= ~BCSR4_MII_MDIO;#define IN_MDIO (*MDIO_ADDR & BCSR4_MII_MDIO)#define OUT_MDC(bit)				\	if (bit)				\		*MDIO_ADDR |=  BCSR4_MII_MDC;	\	else					\		*MDIO_ADDR &= ~BCSR4_MII_MDC;#else	/* ifdef CONFIG_RPX8260 */	/* This is for the usual case where the MDIO pins are on Port C.	 */#define MDIO_ADDR (((volatile cpm2_map_t *)CPM_MAP_ADDR)->im_ioport)#define MAKE_MDIO_OUTPUT MDIO_ADDR.iop_pdirc |= fip->fc_mdio#define MAKE_MDIO_INPUT MDIO_ADDR.iop_pdirc &= ~fip->fc_mdio#define OUT_MDIO(bit)				\	if (bit)				\		MDIO_ADDR.iop_pdatc |= fip->fc_mdio;	\	else					\		MDIO_ADDR.iop_pdatc &= ~fip->fc_mdio;#define IN_MDIO ((MDIO_ADDR.iop_pdatc) & fip->fc_mdio)#define OUT_MDC(bit)				\	if (bit)				\		MDIO_ADDR.iop_pdatc |= fip->fc_mdck;	\	else					\		MDIO_ADDR.iop_pdatc &= ~fip->fc_mdck;#endif	/* ifdef CONFIG_RPX8260 */static uintmii_send_receive(fcc_info_t *fip, uint cmd){	uint		retval;	int		read_op, i, off;	const int	us = 1;	read_op = ((cmd & 0xf0000000) == 0x60000000);	/* Write preamble	 */	OUT_MDIO(1);	MAKE_MDIO_OUTPUT;	OUT_MDIO(1);	for (i = 0; i < 32; i++)	{		udelay(us);		OUT_MDC(1);		udelay(us);		OUT_MDC(0);	}	/* Write data	 */	for (i = 0, off = 31; i < (read_op ? 14 : 32); i++, --off)	{		OUT_MDIO((cmd >> off) & 0x00000001);		udelay(us);		OUT_MDC(1);		udelay(us);		OUT_MDC(0);	}	retval = cmd;	if (read_op)	{		retval >>= 16;		MAKE_MDIO_INPUT;		udelay(us);		OUT_MDC(1);		udelay(us);		OUT_MDC(0);		for (i = 0; i < 16; i++)		{			udelay(us);			OUT_MDC(1);			udelay(us);			retval <<= 1;			if (IN_MDIO)				retval++;			OUT_MDC(0);		}	}	MAKE_MDIO_INPUT;	udelay(us);	OUT_MDC(1);	udelay(us);	OUT_MDC(0);	return retval;}#endif	/* CONFIG_USE_MDIO */static voidfcc_stop(struct net_device *dev){	struct fcc_enet_private	*fep= (struct fcc_enet_private *)(dev->priv);	volatile fcc_t	*fccp = fep->fccp;	fcc_info_t *fip = fep->fip;	volatile fcc_enet_t *ep = fep->ep;	volatile cpm_cpm2_t *cp = cpmp;	volatile cbd_t *bdp;	int i;	if ((fccp->fcc_gfmr & (FCC_GFMR_ENR | FCC_GFMR_ENT)) == 0)		return;	/* already down */	fccp->fcc_fccm = 0;	/* issue the graceful stop tx command */	while (cp->cp_cpcr & CPM_CR_FLG);	cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock,				0x0c, CPM_CR_GRA_STOP_TX) | CPM_CR_FLG;	while (cp->cp_cpcr & CPM_CR_FLG);	/* Disable transmit/receive */	fccp->fcc_gfmr &= ~(FCC_GFMR_ENR | FCC_GFMR_ENT);	/* issue the restart tx command */	fccp->fcc_fcce = FCC_ENET_GRA;	while (cp->cp_cpcr & CPM_CR_FLG);	cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock,				0x0c, CPM_CR_RESTART_TX) | CPM_CR_FLG;	while (cp->cp_cpcr & CPM_CR_FLG);	/* free tx buffers */	fep->skb_cur = fep->skb_dirty = 0;	for (i=0; i<=TX_RING_MOD_MASK; i++) {		if (fep->tx_skbuff[i] != NULL) {			dev_kfree_skb(fep->tx_skbuff[i]);			fep->tx_skbuff[i] = NULL;		}	}	fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;	fep->tx_free = TX_RING_SIZE;	ep->fen_genfcc.fcc_tbptr = ep->fen_genfcc.fcc_tbase;	/* Initialize the tx buffer descriptors. */	bdp = fep->tx_bd_base;	for (i=0; i<TX_RING_SIZE; i++) {		bdp->cbd_sc = 0;		bdp->cbd_datlen = 0;		bdp->cbd_bufaddr = 0;		bdp++;	}	/* Set the last buffer to wrap. */	bdp--;	bdp->cbd_sc |= BD_SC_WRAP;}static voidfcc_restart(struct net_device *dev, int duplex){	struct fcc_enet_private	*fep = (struct fcc_enet_private *)(dev->priv);	volatile fcc_t	*fccp = fep->fccp;	/* stop any transmissions in progress */	fcc_stop(dev);	if (duplex)		fccp->fcc_fpsmr |= FCC_PSMR_FDE | FCC_PSMR_LPB;	else		fccp->fcc_fpsmr &= ~(FCC_PSMR_FDE | FCC_PSMR_LPB);	/* Enable interrupts for transmit error, complete frame	 * received, and any transmit buffer we have also set the	 * interrupt flag.	 */	fccp->fcc_fccm = (FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB);	/* Enable transmit/receive */	fccp->fcc_gfmr |= FCC_GFMR_ENR | FCC_GFMR_ENT;}static intfcc_enet_open(struct net_device *dev){	struct fcc_enet_private *fep = dev->priv;#ifdef	CONFIG_USE_MDIO	fep->sequence_done = 0;	fep->link = 0;	if (fep-

⌨️ 快捷键说明

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