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

📄 bmac.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
}static voidbmac_construct_xmt(struct sk_buff *skb, volatile struct dbdma_cmd *cp){	void *vaddr;	unsigned long baddr;	unsigned long len;	len = skb->len;	vaddr = skb->data;	baddr = virt_to_bus(vaddr);	dbdma_setcmd(cp, (OUTPUT_LAST | INTR_ALWAYS | WAIT_IFCLR), len, baddr, 0);}static voidbmac_construct_rxbuff(struct sk_buff *skb, volatile struct dbdma_cmd *cp){	unsigned char *addr = skb? skb->data: bmac_emergency_rxbuf;	dbdma_setcmd(cp, (INPUT_LAST | INTR_ALWAYS), RX_BUFLEN,		     virt_to_bus(addr), 0);}/* Bit-reverse one byte of an ethernet hardware address. */static unsigned charbitrev(unsigned char b){	int d = 0, i;	for (i = 0; i < 8; ++i, b >>= 1)		d = (d << 1) | (b & 1);	return d;}static voidbmac_init_tx_ring(struct bmac_data *bp){	volatile struct dbdma_regs *td = bp->tx_dma;	memset((char *)bp->tx_cmds, 0, (N_TX_RING+1) * sizeof(struct dbdma_cmd));	bp->tx_empty = 0;	bp->tx_fill = 0;	bp->tx_fullup = 0;	/* put a branch at the end of the tx command list */	dbdma_setcmd(&bp->tx_cmds[N_TX_RING],		     (DBDMA_NOP | BR_ALWAYS), 0, 0, virt_to_bus(bp->tx_cmds));	/* reset tx dma */	dbdma_reset(td);	out_le32(&td->wait_sel, 0x00200020);	out_le32(&td->cmdptr, virt_to_bus(bp->tx_cmds));}static intbmac_init_rx_ring(struct bmac_data *bp){	volatile struct dbdma_regs *rd = bp->rx_dma;	int i;	struct sk_buff *skb;	/* initialize list of sk_buffs for receiving and set up recv dma */	memset((char *)bp->rx_cmds, 0,	       (N_RX_RING + 1) * sizeof(struct dbdma_cmd));	for (i = 0; i < N_RX_RING; i++) {		if ((skb = bp->rx_bufs[i]) == NULL) {			bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);			if (skb != NULL)				skb_reserve(skb, 2);		}		bmac_construct_rxbuff(skb, &bp->rx_cmds[i]);	}	bp->rx_empty = 0;	bp->rx_fill = i;	/* Put a branch back to the beginning of the receive command list */	dbdma_setcmd(&bp->rx_cmds[N_RX_RING],		     (DBDMA_NOP | BR_ALWAYS), 0, 0, virt_to_bus(bp->rx_cmds));	/* start rx dma */	dbdma_reset(rd);	out_le32(&rd->cmdptr, virt_to_bus(bp->rx_cmds));	return 1;}static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev){	struct bmac_data *bp = (struct bmac_data *) dev->priv;	volatile struct dbdma_regs *td = bp->tx_dma;	int i;	/* see if there's a free slot in the tx ring */	/* XXDEBUG(("bmac_xmit_start: empty=%d fill=%d\n", */	/* 	     bp->tx_empty, bp->tx_fill)); */	i = bp->tx_fill + 1;	if (i >= N_TX_RING)		i = 0;	if (i == bp->tx_empty) {		netif_stop_queue(dev);		bp->tx_fullup = 1;		XXDEBUG(("bmac_transmit_packet: tx ring full\n"));		return -1;		/* can't take it at the moment */	}	dbdma_setcmd(&bp->tx_cmds[i], DBDMA_STOP, 0, 0, 0);	bmac_construct_xmt(skb, &bp->tx_cmds[bp->tx_fill]);	bp->tx_bufs[bp->tx_fill] = skb;	bp->tx_fill = i;	bp->stats.tx_bytes += skb->len;	dbdma_continue(td);	return 0;}static int rxintcount;static void bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = (struct net_device *) dev_id;	struct bmac_data *bp = (struct bmac_data *) dev->priv;	volatile struct dbdma_regs *rd = bp->rx_dma;	volatile struct dbdma_cmd *cp;	int i, nb, stat;	struct sk_buff *skb;	unsigned int residual;	int last;	unsigned long flags;	save_flags(flags); cli();	if (++rxintcount < 10) {		XXDEBUG(("bmac_rxdma_intr\n"));	}	last = -1;	i = bp->rx_empty;	while (1) {		cp = &bp->rx_cmds[i];		stat = ld_le16(&cp->xfer_status);		residual = ld_le16(&cp->res_count);		if ((stat & ACTIVE) == 0)			break;		nb = RX_BUFLEN - residual - 2;		if (nb < (ETHERMINPACKET - ETHERCRC)) {			skb = NULL;			bp->stats.rx_length_errors++;			bp->stats.rx_errors++;		} else {			skb = bp->rx_bufs[i];			bp->rx_bufs[i] = NULL;		}		if (skb != NULL) {			nb -= ETHERCRC;			skb_put(skb, nb);			skb->dev = dev;			skb->protocol = eth_type_trans(skb, dev);			netif_rx(skb);			dev->last_rx = jiffies;			++bp->stats.rx_packets;			bp->stats.rx_bytes += nb;		} else {			++bp->stats.rx_dropped;		}		dev->last_rx = jiffies;		if ((skb = bp->rx_bufs[i]) == NULL) {			bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);			if (skb != NULL)				skb_reserve(bp->rx_bufs[i], 2);		}		bmac_construct_rxbuff(skb, &bp->rx_cmds[i]);		st_le16(&cp->res_count, 0);		st_le16(&cp->xfer_status, 0);		last = i;		if (++i >= N_RX_RING) i = 0;	}	if (last != -1) {		bp->rx_fill = last;		bp->rx_empty = i;	}	restore_flags(flags);	dbdma_continue(rd);	if (rxintcount < 10) {		XXDEBUG(("bmac_rxdma_intr done\n"));	}}static int txintcount;static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = (struct net_device *) dev_id;	struct bmac_data *bp = (struct bmac_data *) dev->priv;	volatile struct dbdma_cmd *cp;	int stat;	unsigned long flags;	save_flags(flags); cli();	if (txintcount++ < 10) {		XXDEBUG(("bmac_txdma_intr\n"));	}	/*     del_timer(&bp->tx_timeout); */	/*     bp->timeout_active = 0; */	while (1) {		cp = &bp->tx_cmds[bp->tx_empty];		stat = ld_le16(&cp->xfer_status);		if (txintcount < 10) {			XXDEBUG(("bmac_txdma_xfer_stat=%#0x\n", stat));		}		if (!(stat & ACTIVE)) {			/*			 * status field might not have been filled by DBDMA			 */			if (cp == bus_to_virt(in_le32(&bp->tx_dma->cmdptr)))				break;		}		if (bp->tx_bufs[bp->tx_empty]) {			++bp->stats.tx_packets;			dev_kfree_skb_irq(bp->tx_bufs[bp->tx_empty]);		}		bp->tx_bufs[bp->tx_empty] = NULL;		bp->tx_fullup = 0;		netif_wake_queue(dev);		if (++bp->tx_empty >= N_TX_RING)			bp->tx_empty = 0;		if (bp->tx_empty == bp->tx_fill)			break;	}	restore_flags(flags);	if (txintcount < 10) {		XXDEBUG(("bmac_txdma_intr done->bmac_start\n"));	}	bmac_start(dev);}static struct net_device_stats *bmac_stats(struct net_device *dev){	struct bmac_data *p = (struct bmac_data *) dev->priv;	return &p->stats;}#ifndef SUNHME_MULTICAST/* Real fast bit-reversal algorithm, 6-bit values */static int reverse6[64] = {	0x0,0x20,0x10,0x30,0x8,0x28,0x18,0x38,	0x4,0x24,0x14,0x34,0xc,0x2c,0x1c,0x3c,	0x2,0x22,0x12,0x32,0xa,0x2a,0x1a,0x3a,	0x6,0x26,0x16,0x36,0xe,0x2e,0x1e,0x3e,	0x1,0x21,0x11,0x31,0x9,0x29,0x19,0x39,	0x5,0x25,0x15,0x35,0xd,0x2d,0x1d,0x3d,	0x3,0x23,0x13,0x33,0xb,0x2b,0x1b,0x3b,	0x7,0x27,0x17,0x37,0xf,0x2f,0x1f,0x3f};static unsigned intcrc416(unsigned int curval, unsigned short nxtval){	register unsigned int counter, cur = curval, next = nxtval;	register int high_crc_set, low_data_set;	/* Swap bytes */	next = ((next & 0x00FF) << 8) | (next >> 8);	/* Compute bit-by-bit */	for (counter = 0; counter < 16; ++counter) {		/* is high CRC bit set? */		if ((cur & 0x80000000) == 0) high_crc_set = 0;		else high_crc_set = 1;		cur = cur << 1;			if ((next & 0x0001) == 0) low_data_set = 0;		else low_data_set = 1;		next = next >> 1;			/* do the XOR */		if (high_crc_set ^ low_data_set) cur = cur ^ ENET_CRCPOLY;	}	return cur;}static unsigned intbmac_crc(unsigned short *address){		unsigned int newcrc;	XXDEBUG(("bmac_crc: addr=%#04x, %#04x, %#04x\n", *address, address[1], address[2]));	newcrc = crc416(0xffffffff, *address);	/* address bits 47 - 32 */	newcrc = crc416(newcrc, address[1]);	/* address bits 31 - 16 */	newcrc = crc416(newcrc, address[2]);	/* address bits 15 - 0  */	return(newcrc);}/* * Add requested mcast addr to BMac's hash table filter. * */static voidbmac_addhash(struct bmac_data *bp, unsigned char *addr){		unsigned int	 crc;	unsigned short	 mask;	if (!(*addr)) return;	crc = bmac_crc((unsigned short *)addr) & 0x3f; /* Big-endian alert! */	crc = reverse6[crc];	/* Hyperfast bit-reversing algorithm */	if (bp->hash_use_count[crc]++) return; /* This bit is already set */	mask = crc % 16;	mask = (unsigned char)1 << mask;	bp->hash_use_count[crc/16] |= mask;}static voidbmac_removehash(struct bmac_data *bp, unsigned char *addr){		unsigned int crc;	unsigned char mask;	/* Now, delete the address from the filter copy, as indicated */	crc = bmac_crc((unsigned short *)addr) & 0x3f; /* Big-endian alert! */	crc = reverse6[crc];	/* Hyperfast bit-reversing algorithm */	if (bp->hash_use_count[crc] == 0) return; /* That bit wasn't in use! */	if (--bp->hash_use_count[crc]) return; /* That bit is still in use */	mask = crc % 16;	mask = ((unsigned char)1 << mask) ^ 0xffff; /* To turn off bit */	bp->hash_table_mask[crc/16] &= mask;}/* * Sync the adapter with the software copy of the multicast mask *  (logical address filter). */static voidbmac_rx_off(struct net_device *dev){	unsigned short rx_cfg;	rx_cfg = bmread(dev, RXCFG);	rx_cfg &= ~RxMACEnable;	bmwrite(dev, RXCFG, rx_cfg);	do {		rx_cfg = bmread(dev, RXCFG);	}  while (rx_cfg & RxMACEnable);}unsigned shortbmac_rx_on(struct net_device *dev, int hash_enable, int promisc_enable){	unsigned short rx_cfg;	rx_cfg = bmread(dev, RXCFG);	rx_cfg |= RxMACEnable;	if (hash_enable) rx_cfg |= RxHashFilterEnable;	else rx_cfg &= ~RxHashFilterEnable;	if (promisc_enable) rx_cfg |= RxPromiscEnable;	else rx_cfg &= ~RxPromiscEnable;	bmwrite(dev, RXRST, RxResetValue);	bmwrite(dev, RXFIFOCSR, 0);	/* first disable rxFIFO */	bmwrite(dev, RXFIFOCSR, RxFIFOEnable );	bmwrite(dev, RXCFG, rx_cfg );	return rx_cfg;}static voidbmac_update_hash_table_mask(struct net_device *dev, struct bmac_data *bp){	bmwrite(dev, BHASH3, bp->hash_table_mask[0]); /* bits 15 - 0 */	bmwrite(dev, BHASH2, bp->hash_table_mask[1]); /* bits 31 - 16 */	bmwrite(dev, BHASH1, bp->hash_table_mask[2]); /* bits 47 - 32 */	bmwrite(dev, BHASH0, bp->hash_table_mask[3]); /* bits 63 - 48 */}#if 0static voidbmac_add_multi(struct net_device *dev,	       struct bmac_data *bp, unsigned char *addr){	/* XXDEBUG(("bmac: enter bmac_add_multi\n")); */	bmac_addhash(bp, addr);	bmac_rx_off(dev);	bmac_update_hash_table_mask(dev, bp);	bmac_rx_on(dev, 1, (dev->flags & IFF_PROMISC)? 1 : 0);	/* XXDEBUG(("bmac: exit bmac_add_multi\n")); */}static voidbmac_remove_multi(struct net_device *dev,		  struct bmac_data *bp, unsigned char *addr){	bmac_removehash(bp, addr);	bmac_rx_off(dev);	bmac_update_hash_table_mask(dev, bp);	bmac_rx_on(dev, 1, (dev->flags & IFF_PROMISC)? 1 : 0);}#endif/* Set or clear the multicast filter for this adaptor.    num_addrs == -1	Promiscuous mode, receive all packets    num_addrs == 0	Normal mode, clear multicast list    num_addrs > 0	Multicast mode, receive normal and MC packets, and do			best-effort filtering. */static void bmac_set_multicast(struct net_device *dev){	struct dev_mc_list *dmi;	struct bmac_data *bp = (struct bmac_data *) dev->priv;	int num_addrs = dev->mc_count;	unsigned short rx_cfg;	int i;	if (bp->sleeping)		return;	XXDEBUG(("bmac: enter bmac_set_multicast, n_addrs=%d\n", num_addrs));	if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {		for (i=0; i<4; i++) bp->hash_table_mask[i] = 0xffff;		bmac_update_hash_table_mask(dev, bp);		rx_cfg = bmac_rx_on(dev, 1, 0);		XXDEBUG(("bmac: all multi, rx_cfg=%#08x\n"));	} else if ((dev->flags & IFF_PROMISC) || (num_addrs < 0)) {		rx_cfg = bmread(dev, RXCFG);		rx_cfg |= RxPromiscEnable;		bmwrite(dev, RXCFG, rx_cfg);		rx_cfg = bmac_rx_on(dev, 0, 1);		XXDEBUG(("bmac: promisc mode enabled, rx_cfg=%#08x\n", rx_cfg));	} else {		for (i=0; i<4; i++) bp->hash_table_mask[i] = 0;		for (i=0; i<64; i++) bp->hash_use_count[i] = 0;		if (num_addrs == 0) {			rx_cfg = bmac_rx_on(dev, 0, 0);			XXDEBUG(("bmac: multi disabled, rx_cfg=%#08x\n", rx_cfg));		} else {			for (dmi=dev->mc_list; dmi!=NULL; dmi=dmi->next)				bmac_addhash(bp, dmi->dmi_addr);			bmac_update_hash_table_mask(dev, bp);			rx_cfg = bmac_rx_on(dev, 1, 0);			XXDEBUG(("bmac: multi enabled, rx_cfg=%#08x\n", rx_cfg));		}	}	/* XXDEBUG(("bmac: exit bmac_set_multicast\n")); */}#else /* ifdef SUNHME_MULTICAST *//* The version of set_multicast below was lifted from sunhme.c */#define CRC_POLYNOMIAL_BE 0x04c11db7UL  /* Ethernet CRC, big endian */#define CRC_POLYNOMIAL_LE 0xedb88320UL  /* Ethernet CRC, little endian */static void bmac_set_multicast(struct net_device *dev){	struct dev_mc_list *dmi = dev->mc_list;	char *addrs;	int i, j, bit, byte;	unsigned short rx_cfg;	u32 crc, poly = CRC_POLYNOMIAL_LE;	if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {		bmwrite(dev, BHASH0, 0xffff);		bmwrite(dev, BHASH1, 0xffff);		bmwrite(dev, BHASH2, 0xffff);		bmwrite(dev, BHASH3, 0xffff);	} else if(dev->flags & IFF_PROMISC) {		rx_cfg = bmread(dev, RXCFG);		rx_cfg |= RxPromiscEnable;		bmwrite(dev, RXCFG, rx_cfg);	} else {		u16 hash_table[4];			rx_cfg = bmread(dev, RXCFG);		rx_cfg &= ~RxPromiscEnable;		bmwrite(dev, RXCFG, rx_cfg);		for(i = 0; i < 4; i++) hash_table[i] = 0;			for(i = 0; i < dev->mc_count; i++) {			addrs = dmi->dmi_addr;			dmi = dmi->next;			if(!(*addrs & 1))				continue;			crc = 0xffffffffU;			for(byte = 0; byte < 6; byte++) {				for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {					int test;					test = ((bit ^ crc) & 0x01);					crc >>= 1;					if(test)						crc = crc ^ poly;				}			}			crc >>= 26;			hash_table[crc >> 4] |= 1 << (crc & 0xf);		}		bmwrite(dev, BHASH0, hash_table[0]);		bmwrite(dev, BHASH1, hash_table[1]);		bmwrite(dev, BHASH2, hash_table[2]);		bmwrite(dev, BHASH3, hash_table[3]);	}}#endif /* SUNHME_MULTICAST */static int miscintcount;static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = (struct net_device *) dev_id;	struct bmac_data *bp = (struct bmac_data *)dev->priv;	unsigned int status = bmread(dev, STATUS);	if (miscintcount++ < 10) {		XXDEBUG(("bmac_misc_intr\n"));	}	/* XXDEBUG(("bmac_misc_intr, status=%#08x\n", status)); */	/*     bmac_txdma_intr_inner(irq, dev_id, regs); */	/*   if (status & FrameReceived) bp->stats.rx_dropped++; */	if (status & RxErrorMask) bp->stats.rx_errors++;	if (status & RxCRCCntExp) bp->stats.rx_crc_errors++;	if (status & RxLenCntExp) bp->stats.rx_length_errors++;	if (status & RxOverFlow) bp->stats.rx_over_errors++;	if (status & RxAlignCntExp) bp->stats.rx_frame_errors++;	/*   if (status & FrameSent) bp->stats.tx_dropped++; */	if (status & TxErrorMask) bp->stats.tx_errors++;	if (status & TxUnderrun) bp->stats.tx_fifo_errors++;	if (status & TxNormalCollExp) bp->stats.collisions++;}/* * Procedure for reading EEPROM */#define SROMAddressLength	5#define DataInOn		0x0008#define DataInOff		0x0000#define Clk			0x0002#define ChipSelect		0x0001#define SDIShiftCount		3#define SD0ShiftCount		2#define	DelayValue		1000	/* number of microseconds */#define SROMStartOffset		10	/* this is in words */#define SROMReadCount		3	/* number of words to read from SROM */#define SROMAddressBits		6#define EnetAddressOffset	20static unsigned charbmac_clock_out_bit(struct net_device *dev){	unsigned short         data;	unsigned short         val;

⌨️ 快捷键说明

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