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

📄 bmac.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
#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 device *dev){	unsigned short         data;	unsigned short         val;	bmwrite(dev, SROMCSR, ChipSelect | Clk);	udelay(DelayValue);    	data = bmread(dev, SROMCSR);	udelay(DelayValue);	val = (data >> SD0ShiftCount) & 1;	bmwrite(dev, SROMCSR, ChipSelect);	udelay(DelayValue);    	return val;}static voidbmac_clock_in_bit(struct device *dev, unsigned int val){	unsigned short		data;    	if (val != 0 && val != 1) return;    	data = (val << SDIShiftCount);	bmwrite(dev, SROMCSR, data | ChipSelect  );	udelay(DelayValue);    	bmwrite(dev, SROMCSR, data | ChipSelect | Clk );	udelay(DelayValue);	bmwrite(dev, SROMCSR, data | ChipSelect);	udelay(DelayValue);}static voidreset_and_select_srom(struct device *dev){	/* first reset */	bmwrite(dev, SROMCSR, 0);	udelay(DelayValue);    	/* send it the read command (110) */	bmac_clock_in_bit(dev, 1);	bmac_clock_in_bit(dev, 1);	bmac_clock_in_bit(dev, 0);}static unsigned shortread_srom(struct device *dev, unsigned int addr, unsigned int addr_len){	unsigned short data, val;	int i;    	/* send out the address we want to read from */	for (i = 0; i < addr_len; i++)	{		val = addr >> (addr_len-i-1);		bmac_clock_in_bit(dev, val & 1);	}    	/* Now read in the 16-bit data */	data = 0;	for (i = 0; i < 16; i++)	{		val = bmac_clock_out_bit(dev);		data <<= 1;		data |= val;	}	bmwrite(dev, SROMCSR, 0);    	return data;}/* * It looks like Cogent and SMC use different methods for calculating * checksums. What a pain..  */static intbmac_verify_checksum(struct device *dev){	unsigned short data, storedCS;    	reset_and_select_srom(dev);	data = read_srom(dev, 3, SROMAddressBits);	storedCS = ((data >> 8) & 0x0ff) | ((data << 8) & 0xff00);    	return 0;}static voidbmac_get_station_address(struct device *dev, unsigned char *ea){	int i;	unsigned short data;	for (i = 0; i < 6; i++)			{			reset_and_select_srom(dev);			data = read_srom(dev, i + EnetAddressOffset/2, SROMAddressBits);			ea[2*i]   = bitrev(data & 0x0ff);			ea[2*i+1] = bitrev((data >> 8) & 0x0ff);		}}static int bmac_reset_and_enable(struct device *dev, int enable){	struct bmac_data *bp = dev->priv;	unsigned long flags;	struct sk_buff *skb;	unsigned char *data;	save_flags(flags); cli();	bp->reset_and_enabled = 0;	bmac_reset_chip(dev);	if (enable) {		if (!bmac_init_tx_ring(bp) || !bmac_init_rx_ring(bp)) return 0;		if (!bmac_init_chip(dev)) return 0;		bmac_start_chip(dev);		bmwrite(dev, INTDISABLE, EnableNormal);		bp->reset_and_enabled = 1;		/*		 * It seems that the bmac can't receive until it's transmitted		 * a packet.  So we give it a dummy packet to transmit.		 */		skb = dev_alloc_skb(ETHERMINPACKET);		data = skb_put(skb, ETHERMINPACKET);		memset(data, 0, ETHERMINPACKET);		memcpy(data, dev->dev_addr, 6);		memcpy(data+6, dev->dev_addr, 6);		bmac_transmit_packet(skb, dev);	}	restore_flags(flags);	return 1;}intbmac_probe(struct device *dev){	int j, rev;	struct bmac_data *bp;	struct device_node *bmacs;	unsigned char *addr;	static struct device_node *all_bmacs = NULL, *next_bmac;	if (all_bmacs == NULL) {		all_bmacs = find_devices("bmac");		is_bmac_plus = 0;		if (all_bmacs == NULL) {			all_bmacs = find_compatible_devices("network", "bmac+");			if (all_bmacs)				is_bmac_plus = 1;		}		next_bmac = all_bmacs;	}	bmacs = next_bmac;	if (bmacs == NULL) return -ENODEV;	next_bmac = bmacs->next;	bmac_devs = dev; /* KLUDGE!! */	if (bmacs->n_addrs != 3 || bmacs->n_intrs != 3) {		printk(KERN_ERR "can't use BMAC %s: expect 3 addrs and 3 intrs\n",		       bmacs->full_name);		return -EINVAL;	}	if (dev == NULL) {		dev = init_etherdev(NULL, PRIV_BYTES);		bmac_devs = dev;  /*KLUDGE!!*/	} else {		/* XXX this doesn't look right (but it's never used :-) */		dev->priv = kmalloc(PRIV_BYTES, GFP_KERNEL);		if (dev->priv == 0) return -ENOMEM;	}#ifdef MODULE	bmac_devs = dev;#endif    	dev->base_addr = (unsigned long)		ioremap(bmacs->addrs[0].address, bmacs->addrs[0].size);	dev->irq = bmacs->intrs[0].line;	bmwrite(dev, INTDISABLE, DisableAll);    	addr = get_property(bmacs, "mac-address", NULL);	if (addr == NULL) {		addr = get_property(bmacs, "local-mac-address", NULL);		if (addr == NULL) {			printk(KERN_ERR "Can't get mac-address for BMAC at %lx\n",			       dev->base_addr);			return -EAGAIN;		}	}    	printk(KERN_INFO "%s: BMAC%s at", dev->name, (is_bmac_plus? "+": ""));	rev = addr[0] == 0 && addr[1] == 0xA0;	for (j = 0; j < 6; ++j) {		dev->dev_addr[j] = rev? bitrev(addr[j]): addr[j];		printk("%c%.2x", (j? ':': ' '), dev->dev_addr[j]);	}	XXDEBUG((", base_addr=%#0lx", dev->base_addr));	printk("\n");    	dev->open = bmac_open;	dev->stop = bmac_close;	dev->hard_start_xmit = bmac_output;	dev->get_stats = bmac_stats;	dev->set_multicast_list = bmac_set_multicast;	dev->set_mac_address = bmac_set_address;	bmac_get_station_address(dev, addr);	if (bmac_verify_checksum(dev) != 0) return -EINVAL;    	ether_setup(dev);    	bp = (struct bmac_data *) dev->priv;	memset(bp, 0, sizeof(struct bmac_data));	bp->tx_dma = (volatile struct dbdma_regs *)		ioremap(bmacs->addrs[1].address, bmacs->addrs[1].size);	bp->tx_dma_intr = bmacs->intrs[1].line;	bp->rx_dma = (volatile struct dbdma_regs *)		ioremap(bmacs->addrs[2].address, bmacs->addrs[2].size);	bp->rx_dma_intr = bmacs->intrs[2].line;    	bp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(bp + 1);	bp->rx_cmds = bp->tx_cmds + N_TX_RING + 1;	bp->queue = (struct sk_buff_head *)(bp->rx_cmds + N_RX_RING + 1);	skb_queue_head_init(bp->queue);    	bp->node = bmacs;	memset(&bp->stats, 0, sizeof(bp->stats));	memset((char *) bp->tx_cmds, 0,	       (N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd));	/*     init_timer(&bp->tx_timeout); */	/*     bp->timeout_active = 0; */	if (request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev)) {		printk(KERN_ERR "BMAC: can't get irq %d\n", dev->irq);		return -EAGAIN;	}	if (request_irq(bmacs->intrs[1].line, bmac_txdma_intr, 0, "BMAC-txdma",			dev)) {		printk(KERN_ERR "BMAC: can't get irq %d\n", bmacs->intrs[1].line);		return -EAGAIN;	}	if (request_irq(bmacs->intrs[2].line, bmac_rxdma_intr, 0, "BMAC-rxdma",			dev)) {		printk(KERN_ERR "BMAC: can't get irq %d\n", bmacs->intrs[2].line);		return -EAGAIN;	}    	if (!bmac_reset_and_enable(dev, 0)) return -ENOMEM;    #ifdef CONFIG_PROC_FS	proc_net_register(&(struct proc_dir_entry) {		PROC_NET_BMAC, 4, "bmac",			S_IFREG | S_IRUGO, 1, 0, 0,			0, &proc_net_inode_operations,			bmac_proc_info			});#endif	return 0;}static int bmac_open(struct device *dev){	/* XXDEBUG(("bmac: enter open\n")); */	/* reset the chip */	bmac_reset_and_enable(dev, 1);	dev->flags |= IFF_UP | IFF_RUNNING;	return 0;}static int bmac_close(struct device *dev){	struct bmac_data *bp = (struct bmac_data *) dev->priv;	volatile struct dbdma_regs *rd = bp->rx_dma;	volatile struct dbdma_regs *td = bp->tx_dma;	unsigned short config;	int i;	dev->flags &= ~(IFF_UP | IFF_RUNNING);	/* disable rx and tx */	config = bmread(dev, RXCFG);	bmwrite(dev, RXCFG, (config & ~RxMACEnable));	config = bmread(dev, TXCFG);	bmwrite(dev, TXCFG, (config & ~TxMACEnable));	bmwrite(dev, INTDISABLE, DisableAll); /* disable all intrs */	/* disable rx and tx dma */	st_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE));	/* clear run bit */	st_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE));	/* clear run bit */	/* free some skb's */	XXDEBUG(("bmac: free rx bufs\n"));	for (i=0; i<N_RX_RING; i++) {		if (bp->rx_bufs[i] != NULL) {			dev_kfree_skb(bp->rx_bufs[i]);			bp->rx_bufs[i] = NULL;		}	}	bp->rx_allocated = 0;	XXDEBUG(("bmac: free tx bufs\n"));	for (i = 0; i<N_TX_RING; i++) {		if (bp->tx_bufs[i] != NULL) {			dev_kfree_skb(bp->tx_bufs[i]);			bp->tx_bufs[i] = NULL;		}	}	bp->reset_and_enabled = 0;	XXDEBUG(("bmac: all bufs freed\n"));	return 0;}static voidbmac_start(struct device *dev){	struct bmac_data *bp = dev->priv;	int i;	struct sk_buff *skb;	unsigned long flags;    	save_flags(flags); cli();	while (1) {		i = bp->tx_fill + 1;		if (i >= N_TX_RING) i = 0;		if (i == bp->tx_empty) break;		skb = skb_dequeue(bp->queue);		if (skb == NULL) break;		bmac_transmit_packet(skb, dev);	}	restore_flags(flags);}static intbmac_output(struct sk_buff *skb, struct device *dev){	struct bmac_data *bp = dev->priv;	skb_queue_tail(bp->queue, skb);	bmac_start(dev);	return 0;}static void bmac_tx_timeout(unsigned long data){	struct device *dev = (struct device *) data;	struct bmac_data *bp = (struct bmac_data *) dev->priv;	volatile struct dbdma_regs *td = bp->tx_dma;	volatile struct dbdma_regs *rd = bp->rx_dma;	volatile struct dbdma_cmd *cp;	unsigned long flags;	unsigned short config, oldConfig;	int i;	XXDEBUG(("bmac: tx_timeout called\n"));	save_flags(flags); cli();	bp->timeout_active = 0;	/* update various counters *//*     	bmac_handle_misc_intrs(bp, 0); */	cp = &bp->tx_cmds[bp->tx_empty];/*	XXDEBUG((KERN_DEBUG "bmac: tx dmastat=%x %x runt=%d pr=%x fs=%x fc=%x\n", *//* 	   ld_le32(&td->status), ld_le16(&cp->xfer_status), bp->tx_bad_runt, *//* 	   mb->pr, mb->xmtfs, mb->fifofc)); */	/* turn off both tx and rx and reset the chip */	config = bmread(dev, RXCFG);	bmwrite(dev, RXCFG, (config & ~RxMACEnable));	config = bmread(dev, TXCFG);	bmwrite(dev, TXCFG, (config & ~TxMACEnable));	out_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE|ACTIVE|DEAD));	printk(KERN_ERR "bmac: transmit timeout - resetting\n");	bmac_reset_chip(dev);	/* restart rx dma */	cp = bus_to_virt(ld_le32(&rd->cmdptr));	out_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE|ACTIVE|DEAD));	out_le16(&cp->xfer_status, 0);	out_le32(&rd->cmdptr, virt_to_bus(cp));	out_le32(&rd->control, DBDMA_SET(RUN|WAKE));	/* fix up the transmit side */	XXDEBUG((KERN_DEBUG "bmac: tx empty=%d fill=%d fullup=%d\n",		 bp->tx_empty, bp->tx_fill, bp->tx_fullup));	i = bp->tx_empty;	++bp->stats.tx_errors;	if (i != bp->tx_fill) {		dev_kfree_skb(bp->tx_bufs[i]);		bp->tx_bufs[i] = NULL;		if (++i >= N_TX_RING) i = 0;		bp->tx_empty = i;	}	bp->tx_fullup = 0;	dev->tbusy = 0;	mark_bh(NET_BH);	XXDEBUG((KERN_DEBUG "bmac: clearing tbusy\n"));	if (i != bp->tx_fill) {		cp = &bp->tx_cmds[i];		out_le16(&cp->xfer_status, 0);		out_le16(&cp->command, OUTPUT_LAST);		out_le32(&td->cmdptr, virt_to_bus(cp));		out_le32(&td->control, DBDMA_SET(RUN));		/* 	bmac_set_timeout(dev); */		XXDEBUG((KERN_DEBUG "bmac: starting %d\n", i));	}	/* turn it back on */	oldConfig = bmread(dev, RXCFG);			bmwrite(dev, RXCFG, oldConfig | RxMACEnable ); 	oldConfig = bmread(dev, TXCFG);			bmwrite(dev, TXCFG, oldConfig | TxMACEnable );  	restore_flags(flags);}#if 0static void dump_dbdma(volatile struct dbdma_cmd *cp,int count){	int i,*ip;		for (i=0;i< count;i++) {		ip = (int*)(cp+i);			printk("dbdma req 0x%x addr 0x%x baddr 0x%x xfer/res 0x%x\n",		       ld_le32(ip+0),		       ld_le32(ip+1),		       ld_le32(ip+2),		       ld_le32(ip+3));	}}#endifstatic intbmac_proc_info(char *buffer, char **start, off_t offset, int length, int dummy){	int len = 0;	off_t pos   = 0;	off_t begin = 0;	int i;	if (bmac_devs == NULL) return (-ENOSYS);	len += sprintf(buffer, "BMAC counters & registers\n");	for (i = 0; i<N_REG_ENTRIES; i++) {		len += sprintf(buffer + len, "%s: %#08x\n",			       reg_entries[i].name,			       bmread(bmac_devs, reg_entries[i].reg_offset));		pos = begin + len;    		if (pos < offset) {			len = 0;			begin = pos;		}    		if (pos > offset+length) break;	}  	*start = buffer + (offset - begin);	len -= (offset - begin);  	if (len > length) len = length;  	return len;}#ifdef MODULEMODULE_AUTHOR("Randy Gobbel/Paul Mackerras");MODULE_DESCRIPTION("PowerMac BMAC ethernet driver.");int init_module(void){    int res;       if(bmac_devs != NULL)        return -EBUSY;    res = bmac_probe(NULL);    return res;}void cleanup_module(void){    struct bmac_data *bp = (struct bmac_data *) bmac_devs->priv;    unregister_netdev(bmac_devs);    free_irq(bmac_devs->irq, bmac_misc_intr);    free_irq(bp->tx_dma_intr, bmac_txdma_intr);    free_irq(bp->rx_dma_intr, bmac_rxdma_intr);    kfree(bmac_devs);    bmac_devs = NULL;}#endif

⌨️ 快捷键说明

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