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

📄 z85230.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	write_zsctrl(chan, RES_EXT_INT);	write_zsctrl(chan, RES_H_IUS);	spin_unlock(chan->lock);}struct z8530_irqhandler z8530_dma_sync={	z8530_dma_rx,	z8530_dma_tx,	z8530_dma_status};EXPORT_SYMBOL(z8530_dma_sync);struct z8530_irqhandler z8530_txdma_sync={	z8530_rx,	z8530_dma_tx,	z8530_dma_status};EXPORT_SYMBOL(z8530_txdma_sync);/** *	z8530_rx_clear - Handle RX events from a stopped chip *	@c: Z8530 channel to shut up * *	Receive interrupt vectors for a Z8530 that is in 'parked' mode. *	For machines with PCI Z85x30 cards, or level triggered interrupts *	(eg the MacII) we must clear the interrupt cause or die. */static void z8530_rx_clear(struct z8530_channel *c){	/*	 *	Data and status bytes	 */	u8 stat;	read_zsdata(c);	stat=read_zsreg(c, R1);		if(stat&END_FR)		write_zsctrl(c, RES_Rx_CRC);	/*	 *	Clear irq	 */	write_zsctrl(c, ERR_RES);	write_zsctrl(c, RES_H_IUS);}/** *	z8530_tx_clear - Handle TX events from a stopped chip *	@c: Z8530 channel to shut up * *	Transmit interrupt vectors for a Z8530 that is in 'parked' mode. *	For machines with PCI Z85x30 cards, or level triggered interrupts *	(eg the MacII) we must clear the interrupt cause or die. */static void z8530_tx_clear(struct z8530_channel *c){	write_zsctrl(c, RES_Tx_P);	write_zsctrl(c, RES_H_IUS);}/** *	z8530_status_clear - Handle status events from a stopped chip *	@chan: Z8530 channel to shut up * *	Status interrupt vectors for a Z8530 that is in 'parked' mode. *	For machines with PCI Z85x30 cards, or level triggered interrupts *	(eg the MacII) we must clear the interrupt cause or die. */static void z8530_status_clear(struct z8530_channel *chan){	u8 status=read_zsreg(chan, R0);	if(status&TxEOM)		write_zsctrl(chan, ERR_RES);	write_zsctrl(chan, RES_EXT_INT);	write_zsctrl(chan, RES_H_IUS);}struct z8530_irqhandler z8530_nop={	z8530_rx_clear,	z8530_tx_clear,	z8530_status_clear};EXPORT_SYMBOL(z8530_nop);/** *	z8530_interrupt - Handle an interrupt from a Z8530 *	@irq: 	Interrupt number *	@dev_id: The Z8530 device that is interrupting. *	@regs: unused * *	A Z85[2]30 device has stuck its hand in the air for attention. *	We scan both the channels on the chip for events and then call *	the channel specific call backs for each channel that has events. *	We have to use callback functions because the two channels can be *	in different modes. * *	Locking is done for the handlers. Note that locking is done *	at the chip level (the 5uS delay issue is per chip not per *	channel). c->lock for both channels points to dev->lock */irqreturn_t z8530_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct z8530_dev *dev=dev_id;	u8 intr;	static volatile int locker=0;	int work=0;	struct z8530_irqhandler *irqs;		if(locker)	{		printk(KERN_ERR "IRQ re-enter\n");		return IRQ_NONE;	}	locker=1;	spin_lock(&dev->lock);	while(++work<5000)	{		intr = read_zsreg(&dev->chanA, R3);		if(!(intr & (CHARxIP|CHATxIP|CHAEXT|CHBRxIP|CHBTxIP|CHBEXT)))			break;			/* This holds the IRQ status. On the 8530 you must read it from chan 		   A even though it applies to the whole chip */				/* Now walk the chip and see what it is wanting - it may be		   an IRQ for someone else remember */		   		irqs=dev->chanA.irqs;		if(intr & (CHARxIP|CHATxIP|CHAEXT))		{			if(intr&CHARxIP)				irqs->rx(&dev->chanA);			if(intr&CHATxIP)				irqs->tx(&dev->chanA);			if(intr&CHAEXT)				irqs->status(&dev->chanA);		}		irqs=dev->chanB.irqs;		if(intr & (CHBRxIP|CHBTxIP|CHBEXT))		{			if(intr&CHBRxIP)				irqs->rx(&dev->chanB);			if(intr&CHBTxIP)				irqs->tx(&dev->chanB);			if(intr&CHBEXT)				irqs->status(&dev->chanB);		}	}	spin_unlock(&dev->lock);	if(work==5000)		printk(KERN_ERR "%s: interrupt jammed - abort(0x%X)!\n", dev->name, intr);	/* Ok all done */	locker=0;	return IRQ_HANDLED;}EXPORT_SYMBOL(z8530_interrupt);static char reg_init[16]={	0,0,0,0,	0,0,0,0,	0,0,0,0,	0x55,0,0,0};/** *	z8530_sync_open - Open a Z8530 channel for PIO *	@dev:	The network interface we are using *	@c:	The Z8530 channel to open in synchronous PIO mode * *	Switch a Z8530 into synchronous mode without DMA assist. We *	raise the RTS/DTR and commence network operation. */ int z8530_sync_open(struct net_device *dev, struct z8530_channel *c){	unsigned long flags;	spin_lock_irqsave(c->lock, flags);	c->sync = 1;	c->mtu = dev->mtu+64;	c->count = 0;	c->skb = NULL;	c->skb2 = NULL;	c->irqs = &z8530_sync;	/* This loads the double buffer up */	z8530_rx_done(c);	/* Load the frame ring */	z8530_rx_done(c);	/* Load the backup frame */	z8530_rtsdtr(c,1);	c->dma_tx = 0;	c->regs[R1]|=TxINT_ENAB;	write_zsreg(c, R1, c->regs[R1]);	write_zsreg(c, R3, c->regs[R3]|RxENABLE);	spin_unlock_irqrestore(c->lock, flags);	return 0;}EXPORT_SYMBOL(z8530_sync_open);/** *	z8530_sync_close - Close a PIO Z8530 channel *	@dev: Network device to close *	@c: Z8530 channel to disassociate and move to idle * *	Close down a Z8530 interface and switch its interrupt handlers *	to discard future events. */ int z8530_sync_close(struct net_device *dev, struct z8530_channel *c){	u8 chk;	unsigned long flags;		spin_lock_irqsave(c->lock, flags);	c->irqs = &z8530_nop;	c->max = 0;	c->sync = 0;		chk=read_zsreg(c,R0);	write_zsreg(c, R3, c->regs[R3]);	z8530_rtsdtr(c,0);	spin_unlock_irqrestore(c->lock, flags);	return 0;}EXPORT_SYMBOL(z8530_sync_close);/** *	z8530_sync_dma_open - Open a Z8530 for DMA I/O *	@dev: The network device to attach *	@c: The Z8530 channel to configure in sync DMA mode. * *	Set up a Z85x30 device for synchronous DMA in both directions. Two *	ISA DMA channels must be available for this to work. We assume ISA *	DMA driven I/O and PC limits on access. */ int z8530_sync_dma_open(struct net_device *dev, struct z8530_channel *c){	unsigned long cflags, dflags;		c->sync = 1;	c->mtu = dev->mtu+64;	c->count = 0;	c->skb = NULL;	c->skb2 = NULL;	/*	 *	Load the DMA interfaces up	 */	c->rxdma_on = 0;	c->txdma_on = 0;		/*	 *	Allocate the DMA flip buffers. Limit by page size.	 *	Everyone runs 1500 mtu or less on wan links so this	 *	should be fine.	 */	 	if(c->mtu  > PAGE_SIZE/2)		return -EMSGSIZE;	 	c->rx_buf[0]=(void *)get_zeroed_page(GFP_KERNEL|GFP_DMA);	if(c->rx_buf[0]==NULL)		return -ENOBUFS;	c->rx_buf[1]=c->rx_buf[0]+PAGE_SIZE/2;		c->tx_dma_buf[0]=(void *)get_zeroed_page(GFP_KERNEL|GFP_DMA);	if(c->tx_dma_buf[0]==NULL)	{		free_page((unsigned long)c->rx_buf[0]);		c->rx_buf[0]=NULL;		return -ENOBUFS;	}	c->tx_dma_buf[1]=c->tx_dma_buf[0]+PAGE_SIZE/2;	c->tx_dma_used=0;	c->dma_tx = 1;	c->dma_num=0;	c->dma_ready=1;		/*	 *	Enable DMA control mode	 */	spin_lock_irqsave(c->lock, cflags);	 	/*	 *	TX DMA via DIR/REQ	 */	 	c->regs[R14]|= DTRREQ;	write_zsreg(c, R14, c->regs[R14]);     	c->regs[R1]&= ~TxINT_ENAB;	write_zsreg(c, R1, c->regs[R1]);		/*	 *	RX DMA via W/Req	 */	 	c->regs[R1]|= WT_FN_RDYFN;	c->regs[R1]|= WT_RDY_RT;	c->regs[R1]|= INT_ERR_Rx;	c->regs[R1]&= ~TxINT_ENAB;	write_zsreg(c, R1, c->regs[R1]);	c->regs[R1]|= WT_RDY_ENAB;	write_zsreg(c, R1, c->regs[R1]);            		/*	 *	DMA interrupts	 */	 	/*	 *	Set up the DMA configuration	 */		 	dflags=claim_dma_lock();	 	disable_dma(c->rxdma);	clear_dma_ff(c->rxdma);	set_dma_mode(c->rxdma, DMA_MODE_READ|0x10);	set_dma_addr(c->rxdma, virt_to_bus(c->rx_buf[0]));	set_dma_count(c->rxdma, c->mtu);	enable_dma(c->rxdma);	disable_dma(c->txdma);	clear_dma_ff(c->txdma);	set_dma_mode(c->txdma, DMA_MODE_WRITE);	disable_dma(c->txdma);		release_dma_lock(dflags);		/*	 *	Select the DMA interrupt handlers	 */	c->rxdma_on = 1;	c->txdma_on = 1;	c->tx_dma_used = 1;	 	c->irqs = &z8530_dma_sync;	z8530_rtsdtr(c,1);	write_zsreg(c, R3, c->regs[R3]|RxENABLE);	spin_unlock_irqrestore(c->lock, cflags);		return 0;}EXPORT_SYMBOL(z8530_sync_dma_open);/** *	z8530_sync_dma_close - Close down DMA I/O *	@dev: Network device to detach *	@c: Z8530 channel to move into discard mode * *	Shut down a DMA mode synchronous interface. Halt the DMA, and *	free the buffers. */ int z8530_sync_dma_close(struct net_device *dev, struct z8530_channel *c){	u8 chk;	unsigned long flags;		c->irqs = &z8530_nop;	c->max = 0;	c->sync = 0;		/*	 *	Disable the PC DMA channels	 */		flags=claim_dma_lock(); 	disable_dma(c->rxdma);	clear_dma_ff(c->rxdma);		c->rxdma_on = 0;		disable_dma(c->txdma);	clear_dma_ff(c->txdma);	release_dma_lock(flags);		c->txdma_on = 0;	c->tx_dma_used = 0;	spin_lock_irqsave(c->lock, flags);	/*	 *	Disable DMA control mode	 */	 	c->regs[R1]&= ~WT_RDY_ENAB;	write_zsreg(c, R1, c->regs[R1]);            	c->regs[R1]&= ~(WT_RDY_RT|WT_FN_RDYFN|INT_ERR_Rx);	c->regs[R1]|= INT_ALL_Rx;	write_zsreg(c, R1, c->regs[R1]);	c->regs[R14]&= ~DTRREQ;	write_zsreg(c, R14, c->regs[R14]);   		if(c->rx_buf[0])	{		free_page((unsigned long)c->rx_buf[0]);		c->rx_buf[0]=NULL;	}	if(c->tx_dma_buf[0])	{		free_page((unsigned  long)c->tx_dma_buf[0]);		c->tx_dma_buf[0]=NULL;	}	chk=read_zsreg(c,R0);	write_zsreg(c, R3, c->regs[R3]);	z8530_rtsdtr(c,0);	spin_unlock_irqrestore(c->lock, flags);	return 0;}EXPORT_SYMBOL(z8530_sync_dma_close);/** *	z8530_sync_txdma_open - Open a Z8530 for TX driven DMA *	@dev: The network device to attach *	@c: The Z8530 channel to configure in sync DMA mode. * *	Set up a Z85x30 device for synchronous DMA tranmission. One *	ISA DMA channel must be available for this to work. The receive *	side is run in PIO mode, but then it has the bigger FIFO. */int z8530_sync_txdma_open(struct net_device *dev, struct z8530_channel *c){	unsigned long cflags, dflags;	printk("Opening sync interface for TX-DMA\n");	c->sync = 1;	c->mtu = dev->mtu+64;	c->count = 0;	c->skb = NULL;	c->skb2 = NULL;		/*	 *	Allocate the DMA flip buffers. Limit by page size.	 *	Everyone runs 1500 mtu or less on wan links so this	 *	should be fine.	 */	 	if(c->mtu  > PAGE_SIZE/2)		return -EMSGSIZE;	 	c->tx_dma_buf[0]=(void *)get_zeroed_page(GFP_KERNEL|GFP_DMA);	if(c->tx_dma_buf[0]==NULL)		return -ENOBUFS;	c->tx_dma_buf[1] = c->tx_dma_buf[0] + PAGE_SIZE/2;	spin_lock_irqsave(c->lock, cflags);	/*	 *	Load the PIO receive ring	 */	z8530_rx_done(c);	z8530_rx_done(c); 	/*	 *	Load the DMA interfaces up	 */	c->rxdma_on = 0;	c->txdma_on = 0;		c->tx_dma_used=0;	c->dma_num=0;	c->dma_ready=1;	c->dma_tx = 1; 	/*	 *	Enable DMA control mode	 */ 	/*	 *	TX DMA via DIR/REQ 	 */	c->regs[R14]|= DTRREQ;	write_zsreg(c, R14, c->regs[R14]);     		c->regs[R1]&= ~TxINT_ENAB;	write_zsreg(c, R1, c->regs[R1]);		/*	 *	Set up the DMA configuration	 */		 	dflags = claim_dma_lock();	disable_dma(c->txdma);	clear_dma_ff(c->txdma);	set_dma_mode(c->txdma, DMA_MODE_WRITE);	disable_dma(c->txdma);	release_dma_lock(dflags);		/*	 *	Select the DMA interrupt handlers	 */	c->rxdma_on = 0;	c->txdma_on = 1;	c->tx_dma_used = 1;	 	c->irqs = &z8530_txdma_sync;	z8530_rtsdtr(c,1);	write_zsreg(c, R3, c->regs[R3]|RxENABLE);	spin_unlock_irqrestore(c->lock, cflags);		return 0;}EXPORT_SYMBOL(z8530_sync_txdma_open);/** *	z8530_sync_txdma_close - Close down a TX driven DMA channel *	@dev: Network device to detach *	@c: Z8530 channel to move into discard mode * *	Shut down a DMA/PIO split mode synchronous interface. Halt the DMA,  *	and  free the buffers. */int z8530_sync_txdma_close(struct net_device *dev, struct z8530_channel *c){	unsigned long dflags, cflags;	u8 chk;		spin_lock_irqsave(c->lock, cflags);		c->irqs = &z8530_nop;	c->max = 0;	c->sync = 0;		/*	 *	Disable the PC DMA channels	 */	 	dflags = claim_dma_lock();	disable_dma(c->txdma);	clear_dma_ff(c->txdma);	c->txdma_on = 0;	c->tx_dma_used = 0;	release_dma_lock(dflags);	/*	 *	Disable DMA control mode	 */	 	c->regs[R1]&= ~WT_RDY_ENAB;	write_zsreg(c, R1, c->regs[R1]);            	c->regs[R1]&= ~(WT_RDY_RT|WT_FN_RDYFN|INT_ERR_Rx);	c->regs[R1]|= INT_ALL_Rx;	write_zsreg(c, R1, c->regs[R1]);	c->regs[R14]&= ~DTRREQ;	write_zsreg(c, R14, c->regs[R14]);   		if(c->tx_dma_buf[0])	{		free_page((unsigned long)c->tx_dma_buf[0]);		c->tx_dma_buf[0]=NULL;	}	chk=read_zsreg(c,R0);	write_zsreg(c, R3, c->regs[R3]);	z8530_rtsdtr(c,0);	spin_unlock_irqrestore(c->lock, cflags);	return 0;}EXPORT_SYMBOL(z8530_sync_txdma_close);/* *	Name strings for Z8530 chips. SGI claim to have a 130, Zilog deny *	it exists... */ static char *z8530_type_name[]={	"Z8530",

⌨️ 快捷键说明

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