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

📄 eni.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
		/*		 * Looping a few times in here is probably far cheaper than		 * keeping track of TX completions all the time, so let's poll		 * a bit ...		 */		while (eni_in(MID_TX_RDPTR(eni_vcc->tx->index)) !=		    eni_in(MID_TX_DESCRSTART(eni_vcc->tx->index)))			schedule();		eni_free_mem(eni_dev,eni_vcc->tx->send,eni_vcc->tx->words << 2);		eni_vcc->tx->send = 0;		eni_dev->tx_bw += eni_vcc->tx->reserved;	}	eni_vcc->tx = NULL;}static int start_tx(struct atm_dev *dev){	struct eni_dev *eni_dev;	int i;	eni_dev = ENI_DEV(dev);	eni_dev->lost = 0;	eni_dev->tx_bw = ATM_OC3_PCR;	eni_dev->tx_mult = DEFAULT_TX_MULT;	init_waitqueue_head(&eni_dev->tx_wait);	eni_dev->ubr = NULL;	skb_queue_head_init(&eni_dev->tx_queue);	eni_out(0,MID_DMA_WR_TX);	for (i = 0; i < NR_CHAN; i++) {		eni_dev->tx[i].send = 0;		eni_dev->tx[i].index = i;	}	return 0;}/*--------------------------------- common ----------------------------------*/#if 0 /* may become useful again when tuning things */static void foo(void){printk(KERN_INFO  "tx_complete=%d,dma_complete=%d,queued=%d,requeued=%d,sub=%d,\n"  "backlogged=%d,rx_enqueued=%d,rx_dequeued=%d,putting=%d,pushed=%d\n",  tx_complete,dma_complete,queued,requeued,submitted,backlogged,  rx_enqueued,rx_dequeued,putting,pushed);if (eni_boards) printk(KERN_INFO "loss: %ld\n",ENI_DEV(eni_boards)->lost);}#endifstatic void bug_int(struct atm_dev *dev,unsigned long reason){	struct eni_dev *eni_dev;	DPRINTK(">bug_int\n");	eni_dev = ENI_DEV(dev);	if (reason & MID_DMA_ERR_ACK)		printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA "		    "error\n",dev->number);	if (reason & MID_TX_IDENT_MISM)		printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - ident "		    "mismatch\n",dev->number);	if (reason & MID_TX_DMA_OVFL)		printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA "		    "overflow\n",dev->number);	EVENT("---dump ends here---\n",0,0);	printk(KERN_NOTICE "---recent events---\n");	event_dump();}static void eni_int(int irq,void *dev_id,struct pt_regs *regs){	struct atm_dev *dev;	struct eni_dev *eni_dev;	u32 reason;	DPRINTK(">eni_int\n");	dev = dev_id;	eni_dev = ENI_DEV(dev);	reason = eni_in(MID_ISA);	DPRINTK(DEV_LABEL ": int 0x%lx\n",(unsigned long) reason);	/*	 * Must handle these two right now, because reading ISA doesn't clear	 * them, so they re-occur and we never make it to the tasklet. Since	 * they're rare, we don't mind the occasional invocation of eni_tasklet	 * with eni_dev->events == 0.	 */	if (reason & MID_STAT_OVFL) {		EVENT("stat overflow\n",0,0);		eni_dev->lost += eni_in(MID_STAT) & MID_OVFL_TRASH;	}	if (reason & MID_SUNI_INT) {		EVENT("SUNI int\n",0,0);		dev->phy->interrupt(dev);#if 0		foo();#endif	}	spin_lock(&eni_dev->lock);	eni_dev->events |= reason;	spin_unlock(&eni_dev->lock);	tasklet_schedule(&eni_dev->task);}static void eni_tasklet(unsigned long data){	struct atm_dev *dev = (struct atm_dev *) data;	struct eni_dev *eni_dev = ENI_DEV(dev);	unsigned long flags;	u32 events;	DPRINTK("eni_tasklet (dev %p)\n",dev);	spin_lock_irqsave(&eni_dev->lock,flags);	events = xchg(&eni_dev->events,0);	spin_unlock_irqrestore(&eni_dev->lock,flags);	if (events & MID_RX_DMA_COMPLETE) {		EVENT("INT: RX DMA complete, starting dequeue_rx\n",0,0);		dequeue_rx(dev);		EVENT("dequeue_rx done, starting poll_rx\n",0,0);		poll_rx(dev);		EVENT("poll_rx done\n",0,0);		/* poll_tx ? */	}	if (events & MID_SERVICE) {		EVENT("INT: service, starting get_service\n",0,0);		get_service(dev);		EVENT("get_service done, starting poll_rx\n",0,0);		poll_rx(dev);		EVENT("poll_rx done\n",0,0);	} 	if (events & MID_TX_DMA_COMPLETE) {		EVENT("INT: TX DMA COMPLETE\n",0,0);		dequeue_tx(dev);	}	if (events & MID_TX_COMPLETE) {		EVENT("INT: TX COMPLETE\n",0,0);tx_complete++;		wake_up(&eni_dev->tx_wait);		/* poll_rx ? */	}	if (events & (MID_DMA_ERR_ACK | MID_TX_IDENT_MISM | MID_TX_DMA_OVFL)) {		EVENT("bug interrupt\n",0,0);		bug_int(dev,events);	}	poll_tx(dev);}/*--------------------------------- entries ---------------------------------*/static const char *media_name[] __devinitdata = {    "MMF", "SMF", "MMF", "03?", /*  0- 3 */    "UTP", "05?", "06?", "07?", /*  4- 7 */    "TAXI","09?", "10?", "11?", /*  8-11 */    "12?", "13?", "14?", "15?", /* 12-15 */    "MMF", "SMF", "18?", "19?", /* 16-19 */    "UTP", "21?", "22?", "23?", /* 20-23 */    "24?", "25?", "26?", "27?", /* 24-27 */    "28?", "29?", "30?", "31?"  /* 28-31 */};#define SET_SEPROM \  ({ if (!error && !pci_error) { \    pci_error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,tonga); \    udelay(10); /* 10 usecs */ \  } })#define GET_SEPROM \  ({ if (!error && !pci_error) { \    pci_error = pci_read_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,&tonga); \    udelay(10); /* 10 usecs */ \  } })static int __devinit get_esi_asic(struct atm_dev *dev){	struct eni_dev *eni_dev;	unsigned char tonga;	int error,failed,pci_error;	int address,i,j;	eni_dev = ENI_DEV(dev);	error = pci_error = 0;	tonga = SEPROM_MAGIC | SEPROM_DATA | SEPROM_CLK;	SET_SEPROM;	for (i = 0; i < ESI_LEN && !error && !pci_error; i++) {		/* start operation */		tonga |= SEPROM_DATA;		SET_SEPROM;		tonga |= SEPROM_CLK;		SET_SEPROM;		tonga &= ~SEPROM_DATA;		SET_SEPROM;		tonga &= ~SEPROM_CLK;		SET_SEPROM;		/* send address */		address = ((i+SEPROM_ESI_BASE) << 1)+1;		for (j = 7; j >= 0; j--) {			tonga = (address >> j) & 1 ? tonga | SEPROM_DATA :			    tonga & ~SEPROM_DATA;			SET_SEPROM;			tonga |= SEPROM_CLK;			SET_SEPROM;			tonga &= ~SEPROM_CLK;			SET_SEPROM;		}		/* get ack */		tonga |= SEPROM_DATA;		SET_SEPROM;		tonga |= SEPROM_CLK;		SET_SEPROM;		GET_SEPROM;		failed = tonga & SEPROM_DATA;		tonga &= ~SEPROM_CLK;		SET_SEPROM;		tonga |= SEPROM_DATA;		SET_SEPROM;		if (failed) error = -EIO;		else {			dev->esi[i] = 0;			for (j = 7; j >= 0; j--) {				dev->esi[i] <<= 1;				tonga |= SEPROM_DATA;				SET_SEPROM;				tonga |= SEPROM_CLK;				SET_SEPROM;				GET_SEPROM;				if (tonga & SEPROM_DATA) dev->esi[i] |= 1;				tonga &= ~SEPROM_CLK;				SET_SEPROM;				tonga |= SEPROM_DATA;				SET_SEPROM;			}			/* get ack */			tonga |= SEPROM_DATA;			SET_SEPROM;			tonga |= SEPROM_CLK;			SET_SEPROM;			GET_SEPROM;			if (!(tonga & SEPROM_DATA)) error = -EIO;			tonga &= ~SEPROM_CLK;			SET_SEPROM;			tonga |= SEPROM_DATA;			SET_SEPROM;		}		/* stop operation */		tonga &= ~SEPROM_DATA;		SET_SEPROM;		tonga |= SEPROM_CLK;		SET_SEPROM;		tonga |= SEPROM_DATA;		SET_SEPROM;	}	if (pci_error) {		printk(KERN_ERR DEV_LABEL "(itf %d): error reading ESI "		    "(0x%02x)\n",dev->number,pci_error);		error = -EIO;	}	return error;}#undef SET_SEPROM#undef GET_SEPROMstatic int __devinit get_esi_fpga(struct atm_dev *dev,unsigned long base){	unsigned long mac_base;	int i;	mac_base = base+EPROM_SIZE-sizeof(struct midway_eprom);	for (i = 0; i < ESI_LEN; i++) dev->esi[i] = readb(mac_base+(i^3));	return 0;}static int __devinit eni_do_init(struct atm_dev *dev){	struct midway_eprom *eprom;	struct eni_dev *eni_dev;	struct pci_dev *pci_dev;	unsigned long real_base,base;	unsigned char revision;	int error,i,last;	DPRINTK(">eni_init\n");	dev->ci_range.vpi_bits = 0;	dev->ci_range.vci_bits = NR_VCI_LD;	dev->link_rate = ATM_OC3_PCR;	eni_dev = ENI_DEV(dev);	pci_dev = eni_dev->pci_dev;	real_base = pci_resource_start(pci_dev, 0);	eni_dev->irq = pci_dev->irq;	error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision);	if (error) {		printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%02x\n",		    dev->number,error);		return -EINVAL;	}	if ((error = pci_write_config_word(pci_dev,PCI_COMMAND,	    PCI_COMMAND_MEMORY |	    (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {		printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory "		    "(0x%02x)\n",dev->number,error);		return -EIO;	}	printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%lx,irq=%d,",	    dev->number,revision,real_base,eni_dev->irq);	if (!(base = (unsigned long) ioremap_nocache(real_base,MAP_MAX_SIZE))) {		printk("\n");		printk(KERN_ERR DEV_LABEL "(itf %d): can't set up page "		    "mapping\n",dev->number);		return error;	}	eni_dev->base_diff = real_base-base;	/* id may not be present in ASIC Tonga boards - check this @@@ */	if (!eni_dev->asic) {		eprom = (struct midway_eprom *) (base+EPROM_SIZE-sizeof(struct		    midway_eprom));		if (readl(&eprom->magic) != ENI155_MAGIC) {			printk("\n");			printk(KERN_ERR KERN_ERR DEV_LABEL "(itf %d): bad "			    "magic - expected 0x%x, got 0x%x\n",dev->number,			    ENI155_MAGIC,(unsigned) readl(&eprom->magic));			return -EINVAL;		}	}	eni_dev->phy = base+PHY_BASE;	eni_dev->reg = base+REG_BASE;	eni_dev->ram = base+RAM_BASE;	last = MAP_MAX_SIZE-RAM_BASE;	for (i = last-RAM_INCREMENT; i >= 0; i -= RAM_INCREMENT) {		writel(0x55555555,eni_dev->ram+i);		if (readl(eni_dev->ram+i) != 0x55555555) last = i;		else {			writel(0xAAAAAAAA,eni_dev->ram+i);			if (readl(eni_dev->ram+i) != 0xAAAAAAAA) last = i;			else writel(i,eni_dev->ram+i);		}	}	for (i = 0; i < last; i += RAM_INCREMENT)		if (readl(eni_dev->ram+i) != i) break;	eni_dev->mem = i;	memset_io(eni_dev->ram,0,eni_dev->mem);	/* TODO: should shrink allocation now */	printk("mem=%dkB (",eni_dev->mem >> 10);	/* TODO: check for non-SUNI, check for TAXI ? */	if (!(eni_in(MID_RES_ID_MCON) & 0x200) != !eni_dev->asic) {		printk(")\n");		printk(KERN_ERR DEV_LABEL "(itf %d): ERROR - wrong id 0x%x\n",		    dev->number,(unsigned) eni_in(MID_RES_ID_MCON));		return -EINVAL;	}	error = eni_dev->asic ? get_esi_asic(dev) : get_esi_fpga(dev,base);	if (error) return error;	for (i = 0; i < ESI_LEN; i++)		printk("%s%02X",i ? "-" : "",dev->esi[i]);	printk(")\n");	printk(KERN_NOTICE DEV_LABEL "(itf %d): %s,%s\n",dev->number,	    eni_in(MID_RES_ID_MCON) & 0x200 ? "ASIC" : "FPGA",	    media_name[eni_in(MID_RES_ID_MCON) & DAUGTHER_ID]);	return suni_init(dev);}static int __devinit eni_start(struct atm_dev *dev){	struct eni_dev *eni_dev;	unsigned long buf,buffer_mem;	int error;	DPRINTK(">eni_start\n");	eni_dev = ENI_DEV(dev);	if (request_irq(eni_dev->irq,&eni_int,SA_SHIRQ,DEV_LABEL,dev)) {		printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",		    dev->number,eni_dev->irq);		return -EAGAIN;	}	/* @@@ should release IRQ on error */	pci_set_master(eni_dev->pci_dev);	if ((error = pci_write_config_word(eni_dev->pci_dev,PCI_COMMAND,	    PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |	    (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {		printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+"		    "master (0x%02x)\n",dev->number,error);		return error;	}#ifdef __sparc_v9__ /* copied from drivers/net/sunhme.c */	/* NOTE: Cache line size is in 32-bit word units. */	pci_write_config_byte(eni_dev->pci_dev, PCI_CACHE_LINE_SIZE, 0x10);#endif	if ((error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,	    END_SWAP_DMA))) {		printk(KERN_ERR DEV_LABEL "(itf %d): can't set endian swap "		    "(0x%02x)\n",dev->number,error);		return error;	}	/* determine addresses of internal tables */	eni_dev->vci = eni_dev->ram;	eni_dev->rx_dma = eni_dev->ram+NR_VCI*16;	eni_dev->tx_dma = eni_dev->rx_dma+NR_DMA_RX*8;	eni_dev->service = eni_dev->tx_dma+NR_DMA_TX*8;	buf = eni_dev->service+NR_SERVICE*4;	DPRINTK("vci 0x%lx,rx 0x%lx, tx 0x%lx,srv 0x%lx,buf 0x%lx\n",	     eni_dev->vci,eni_dev->rx_dma,eni_dev->tx_dma,	     eni_dev->service,buf);	spin_lock_init(&eni_dev->lock);	tasklet_init(&eni_dev->task,eni_tasklet,(unsigned long) dev);	eni_dev->events = 0;	/* initialize memory management */	buffer_mem = eni_dev->mem-(buf-eni_dev->ram);	eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2;	eni_dev->free_list = (struct eni_free *) kmalloc(	    sizeof(struct eni_free)*(eni_dev->free_list_size+1),GFP_KERNEL);	if (!eni_dev->free_list) {		printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n",		    dev->number);		return -ENOMEM;	}	eni_dev->free_len = 0;	eni_put_free(eni_dev,buf,buffer_mem);	memset_io(eni_dev->vci,0,16*NR_VCI); /* clear VCI table */	/*	 * byte_addr  free (k)	 * 0x00000000     512  VCI table	 * 0x00004000	  496  RX DMA	 * 0x00005000	  492  TX DMA	 * 0x00006000	  488  service list	 * 0x00007000	  484  buffers	 * 0x00080000	    0  end (512kB)	 */	eni_out(0xffffffff,MID_IE);	error = start_tx(dev);	if (error) return error;	error = start_rx(dev);	if (error) return error;	error = dev->phy->start(dev);	if (error) return error;	eni_out(eni_in(MID_MC_S) | (1 << MID_INT_SEL_SHIFT) |	    MID_TX_LOCK_MODE | MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE,	    MID_MC_S);	    /* Tonga uses SBus INTReq1 */	(void) eni_in(MID_ISA); /* clear Midway interrupts */	return 0;}static void eni_close(struct atm_vcc *vcc){	DPRINTK(">eni_close\n");	if (!ENI_VCC(vcc)) return;	clear_bit(ATM_VF_READY,&vcc->flags);	close_rx(vcc);	close_tx(vcc);	DPRINTK("eni_close: done waiting\n");	/* deallocate memory */	kfree(ENI_VCC(vcc));	ENI_VCC(vcc) = NULL;	clear_bit(ATM_VF_ADDR,&vcc->flags);	/*foo();*/}

⌨️ 快捷键说明

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