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

📄 fec.c.orig

📁 实现一个网卡到内存空间的零拷贝程序
💻 ORIG
📖 第 1 页 / 共 4 页
字号:
	},	(const phy_cmd_t []) { /* ack_int */		/* read SR and ISR to acknowledge */		{ mk_mii_read(MII_REG_SR), mii_parse_sr },		{ mk_mii_read(MII_LXT970_ISR), NULL },		/* find out the current status */		{ mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr },		{ mk_mii_end, }	},	(const phy_cmd_t []) {  /* shutdown - disable interrupts */		{ mk_mii_write(MII_LXT970_IER, 0x0000), NULL },		{ mk_mii_end, }	},};#endif /* CONFIG_FEC_LXT970 *//* ------------------------------------------------------------------------- *//* The Level one LXT971 is used on some of my custom boards                  */#ifdef CONFIG_FEC_LXT971/* register definitions for the 971 */#define MII_LXT971_PCR       16  /* Port Control Register     */#define MII_LXT971_SR2       17  /* Status Register 2         */#define MII_LXT971_IER       18  /* Interrupt Enable Register */#define MII_LXT971_ISR       19  /* Interrupt Status Register */#define MII_LXT971_LCR       20  /* LED Control Register      */#define MII_LXT971_TCR       30  /* Transmit Control Register *//* * I had some nice ideas of running the MDIO faster... * The 971 should support 8MHz and I tried it, but things acted really * weird, so 2.5 MHz ought to be enough for anyone... */static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev){	struct fec_enet_private *fep = dev->priv;	volatile uint *s = &(fep->phy_status);	*s &= ~(PHY_STAT_SPMASK);	if (mii_reg & 0x4000) {		if (mii_reg & 0x0200)			*s |= PHY_STAT_100FDX;		else			*s |= PHY_STAT_100HDX;	}	else {		if (mii_reg & 0x0200)			*s |= PHY_STAT_10FDX;		else			*s |= PHY_STAT_10HDX;	}	if (mii_reg & 0x0008)		*s |= PHY_STAT_FAULT;}static phy_info_t phy_info_lxt971 = {	0x0001378e,	"LXT971",	(const phy_cmd_t []) {  /* config *///		{ mk_mii_write(MII_REG_ANAR, 0x021), NULL }, /* 10  Mbps, HD */		{ mk_mii_read(MII_REG_CR), mii_parse_cr },		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },		{ mk_mii_end, }	},	(const phy_cmd_t []) {  /* startup - enable interrupts */		{ mk_mii_write(MII_LXT971_IER, 0x00f2), NULL },		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */		/* Somehow does the 971 tell me that the link is down		 * the first read after power-up.		 * read here to get a valid value in ack_int */		{ mk_mii_read(MII_REG_SR), mii_parse_sr },		{ mk_mii_end, }	},	(const phy_cmd_t []) { /* ack_int */		/* find out the current status */		{ mk_mii_read(MII_REG_SR), mii_parse_sr },		{ mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },		/* we only need to read ISR to acknowledge */		{ mk_mii_read(MII_LXT971_ISR), NULL },		{ mk_mii_end, }	},	(const phy_cmd_t []) {  /* shutdown - disable interrupts */		{ mk_mii_write(MII_LXT971_IER, 0x0000), NULL },		{ mk_mii_end, }	},};#endif /* CONFIG_FEC_LXT970 *//* ------------------------------------------------------------------------- *//* The Quality Semiconductor QS6612 is used on the RPX CLLF                  */#ifdef CONFIG_FEC_QS6612/* register definitions */#define MII_QS6612_MCR       17  /* Mode Control Register      */#define MII_QS6612_FTR       27  /* Factory Test Register      */#define MII_QS6612_MCO       28  /* Misc. Control Register     */#define MII_QS6612_ISR       29  /* Interrupt Source Register  */#define MII_QS6612_IMR       30  /* Interrupt Mask Register    */#define MII_QS6612_PCR       31  /* 100BaseTx PHY Control Reg. */static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev){	struct fec_enet_private *fep = dev->priv;	volatile uint *s = &(fep->phy_status);	*s &= ~(PHY_STAT_SPMASK);	switch((mii_reg >> 2) & 7) {	case 1: *s |= PHY_STAT_10HDX; break;	case 2: *s |= PHY_STAT_100HDX; break;	case 5: *s |= PHY_STAT_10FDX; break;	case 6: *s |= PHY_STAT_100FDX; break;	}}static phy_info_t phy_info_qs6612 = {	0x00181440,	"QS6612",	(const phy_cmd_t []) {  /* config *///	{ mk_mii_write(MII_REG_ANAR, 0x061), NULL }, /* 10  Mbps */		/* The PHY powers up isolated on the RPX,		 * so send a command to allow operation.		 */		{ mk_mii_write(MII_QS6612_PCR, 0x0dc0), NULL },		/* parse cr and anar to get some info */		{ mk_mii_read(MII_REG_CR), mii_parse_cr },		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },		{ mk_mii_end, }	},	(const phy_cmd_t []) {  /* startup - enable interrupts */		{ mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */		{ mk_mii_end, }	},	(const phy_cmd_t []) { /* ack_int */		/* we need to read ISR, SR and ANER to acknowledge */		{ mk_mii_read(MII_QS6612_ISR), NULL },		{ mk_mii_read(MII_REG_SR), mii_parse_sr },		{ mk_mii_read(MII_REG_ANER), NULL },		/* read pcr to get info */		{ mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr },		{ mk_mii_end, }	},	(const phy_cmd_t []) {  /* shutdown - disable interrupts */		{ mk_mii_write(MII_QS6612_IMR, 0x0000), NULL },		{ mk_mii_end, }	},};#endif /* CONFIG_FEC_QS6612 */static phy_info_t *phy_info[] = {#ifdef CONFIG_FEC_LXT970	&phy_info_lxt970,#endif /* CONFIG_FEC_LXT970 */#ifdef CONFIG_FEC_LXT971	&phy_info_lxt971,#endif /* CONFIG_FEC_LXT971 */#ifdef CONFIG_FEC_QS6612	&phy_info_qs6612,#endif /* CONFIG_FEC_LXT971 */	NULL};static void mii_display_status(struct net_device *dev){	struct fec_enet_private *fep = dev->priv;	volatile uint *s = &(fep->phy_status);	if (!fep->link && !fep->old_link) {		/* Link is still down - don't print anything */		return;	}	printk("%s: status: ", dev->name);	if (!fep->link) {		printk("link down");	} else {		printk("link up");		switch(*s & PHY_STAT_SPMASK) {		case PHY_STAT_100FDX: printk(", 100 Mbps Full Duplex"); break;		case PHY_STAT_100HDX: printk(", 100 Mbps Half Duplex"); break;		case PHY_STAT_10FDX: printk(", 10 Mbps Full Duplex"); break;		case PHY_STAT_10HDX: printk(", 10 Mbps Half Duplex"); break;		default:			printk(", Unknown speed/duplex");		}		if (*s & PHY_STAT_ANC)			printk(", auto-negotiation complete");	}	if (*s & PHY_STAT_FAULT)		printk(", remote fault");	printk(".\n");}static void mii_display_config(struct net_device *dev){	struct fec_enet_private *fep = dev->priv;	volatile uint *s = &(fep->phy_status);	printk("%s: config: auto-negotiation ", dev->name);	if (*s & PHY_CONF_ANE)		printk("on");	else		printk("off");	if (*s & PHY_CONF_100FDX)		printk(", 100FDX");	if (*s & PHY_CONF_100HDX)		printk(", 100HDX");	if (*s & PHY_CONF_10FDX)		printk(", 10FDX");	if (*s & PHY_CONF_10HDX)		printk(", 10HDX");	if (!(*s & PHY_CONF_SPMASK))		printk(", No speed/duplex selected?");	if (*s & PHY_CONF_LOOP)		printk(", loopback enabled");	printk(".\n");	fep->sequence_done = 1;}static void mii_relink(struct net_device *dev){	struct fec_enet_private *fep = dev->priv;	int duplex;	fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0;	mii_display_status(dev);	fep->old_link = fep->link;	if (fep->link) {		duplex = 0;		if (fep->phy_status		    & (PHY_STAT_100FDX | PHY_STAT_10FDX))			duplex = 1;		fec_restart(dev, duplex);	}	else		fec_stop(dev);#if 0	enable_irq(fep->mii_irq);#endif}static void mii_queue_relink(uint mii_reg, struct net_device *dev){	struct fec_enet_private *fep = dev->priv;	fep->phy_task.routine = (void *)mii_relink;	fep->phy_task.data = dev;	schedule_task(&fep->phy_task);}static void mii_queue_config(uint mii_reg, struct net_device *dev){	struct fec_enet_private *fep = dev->priv;	fep->phy_task.routine = (void *)mii_display_config;	fep->phy_task.data = dev;	schedule_task(&fep->phy_task);}phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_REG_CR), mii_queue_relink },			       { mk_mii_end, } };phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_REG_CR), mii_queue_config },			       { mk_mii_end, } };/* Read remainder of PHY ID.*/static voidmii_discover_phy3(uint mii_reg, struct net_device *dev){	struct fec_enet_private *fep;	int	i;	fep = dev->priv;	fep->phy_id |= (mii_reg & 0xffff);	for(i = 0; phy_info[i]; i++)		if(phy_info[i]->id == (fep->phy_id >> 4))			break;	if(!phy_info[i])		panic("%s: PHY id 0x%08x is not supported!\n",		      dev->name, fep->phy_id);	fep->phy = phy_info[i];	fep->phy_id_done = 1;	printk("%s: Phy @ 0x%x, type %s (0x%08x)\n",		dev->name, fep->phy_addr, fep->phy->name, fep->phy_id);}/* Scan all of the MII PHY addresses looking for someone to respond * with a valid ID.  This usually happens quickly. */static voidmii_discover_phy(uint mii_reg, struct net_device *dev){	struct fec_enet_private *fep;	uint	phytype;	fep = dev->priv;	if ((phytype = (mii_reg & 0xffff)) != 0xffff) {		/* Got first part of ID, now get remainder.		*/		fep->phy_id = phytype << 16;		mii_queue(dev, mk_mii_read(MII_REG_PHYIR2), mii_discover_phy3);	} else {		fep->phy_addr++;		if (fep->phy_addr < 32) {			mii_queue(dev, mk_mii_read(MII_REG_PHYIR1),							mii_discover_phy);		} else {			printk("fec: No PHY device found.\n");		}	}}#endif	/* CONFIG_USE_MDIO *//* This interrupt occurs when the PHY detects a link change.*/static void#ifdef CONFIG_RPXCLASSICmii_link_interrupt(void *dev_id)#elsemii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)#endif{#ifdef	CONFIG_USE_MDIO	struct	net_device *dev = dev_id;	struct fec_enet_private *fep = dev->priv;	volatile immap_t *immap = (immap_t *)IMAP_ADDR;	volatile fec_t *fecp = &(immap->im_cpm.cp_fec);	unsigned int ecntrl = fecp->fec_ecntrl;	/* We need the FEC enabled to access the MII	*/	if ((ecntrl & FEC_ECNTRL_ETHER_EN) == 0) {		fecp->fec_ecntrl |= FEC_ECNTRL_ETHER_EN;	}#endif	/* CONFIG_USE_MDIO */#if 0	disable_irq(fep->mii_irq);  /* disable now, enable later */#endif#ifdef	CONFIG_USE_MDIO	mii_do_cmd(dev, fep->phy->ack_int);	mii_do_cmd(dev, phy_cmd_relink);  /* restart and display status */	if ((ecntrl & FEC_ECNTRL_ETHER_EN) == 0) {		fecp->fec_ecntrl = ecntrl;	/* restore old settings */	}#elseprintk("%s[%d] %s: unexpected Link interrupt\n", __FILE__,__LINE__,__FUNCTION__);#endif	/* CONFIG_USE_MDIO */}static intfec_enet_open(struct net_device *dev){	struct fec_enet_private *fep = dev->priv;	/* I should reset the ring buffers here, but I don't yet know	 * a simple way to do that.	 */#ifdef	CONFIG_USE_MDIO	fep->sequence_done = 0;	fep->link = 0;	if (fep->phy) {		mii_do_cmd(dev, fep->phy->ack_int);		mii_do_cmd(dev, fep->phy->config);		mii_do_cmd(dev, phy_cmd_config);  /* display configuration */		while(!fep->sequence_done)			schedule();		mii_do_cmd(dev, fep->phy->startup);		netif_start_queue(dev);		return 0;		/* Success */	}	return -ENODEV;		/* No PHY we understand */#else	fep->link = 1;	netif_start_queue(dev);	return 0;	/* Success */#endif	/* CONFIG_USE_MDIO */}static intfec_enet_close(struct net_device *dev){	/* Don't know what to do yet.	*/	netif_stop_queue(dev);	fec_stop(dev);	return 0;}static struct net_device_stats *fec_enet_get_stats(struct net_device *dev){	struct fec_enet_private *fep = (struct fec_enet_private *)dev->priv;	return &fep->stats;}/* Set or clear the multicast filter for this adaptor. * Skeleton taken from sunlance driver. * The CPM Ethernet implementation allows Multicast as well as individual * MAC address filtering.  Some of the drivers check to make sure it is * a group multicast address, and discard those that are not.  I guess I * will do the same for now, but just remove the test if you want * individual filtering as well (do the upper net layers want or support * this kind of feature?). */static void set_multicast_list(struct net_device *dev){	struct	fec_enet_private *fep;	volatile fec_t *ep;

⌨️ 快捷键说明

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