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

📄 z85230.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *	This program is free software; you can redistribute it and/or *	modify it under the terms of the GNU General Public License *	as published by the Free Software Foundation; either version *	2 of the License, or (at your option) any later version. * *	(c) Copyright 1998 Alan Cox <alan@lxorguk.ukuu.org.uk> *	(c) Copyright 2000, 2001 Red Hat Inc * *	Development of this driver was funded by Equiinet Ltd *			http://www.equiinet.com * *	ChangeLog: * *	Asynchronous mode dropped for 2.2. For 2.5 we will attempt the *	unification of all the Z85x30 asynchronous drivers for real. * *	DMA now uses get_free_page as kmalloc buffers may span a 64K  *	boundary. * *	Modified for SMP safety and SMP locking by Alan Cox <alan@redhat.com> * *	Performance * *	Z85230: *	Non DMA you want a 486DX50 or better to do 64Kbits. 9600 baud *	X.25 is not unrealistic on all machines. DMA mode can in theory *	handle T1/E1 quite nicely. In practice the limit seems to be about *	512Kbit->1Mbit depending on motherboard. * *	Z85C30: *	64K will take DMA, 9600 baud X.25 should be ok. * *	Z8530: *	Synchronous mode without DMA is unlikely to pass about 2400 baud. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/net.h>#include <linux/skbuff.h>#include <linux/netdevice.h>#include <linux/if_arp.h>#include <linux/delay.h>#include <linux/ioport.h>#include <linux/init.h>#include <asm/dma.h>#include <asm/io.h>#define RT_LOCK#define RT_UNLOCK#include <linux/spinlock.h>#include <net/syncppp.h>#include "z85230.h"/** *	z8530_read_port - Architecture specific interface function *	@p: port to read * *	Provided port access methods. The Comtrol SV11 requires no delays *	between accesses and uses PC I/O. Some drivers may need a 5uS delay *	 *	In the longer term this should become an architecture specific *	section so that this can become a generic driver interface for all *	platforms. For now we only handle PC I/O ports with or without the *	dread 5uS sanity delay. * *	The caller must hold sufficient locks to avoid violating the horrible *	5uS delay rule. */static inline int z8530_read_port(unsigned long p){	u8 r=inb(Z8530_PORT_OF(p));	if(p&Z8530_PORT_SLEEP)	/* gcc should figure this out efficiently ! */		udelay(5);	return r;}/** *	z8530_write_port - Architecture specific interface function *	@p: port to write *	@d: value to write * *	Write a value to a port with delays if need be. Note that the *	caller must hold locks to avoid read/writes from other contexts *	violating the 5uS rule * *	In the longer term this should become an architecture specific *	section so that this can become a generic driver interface for all *	platforms. For now we only handle PC I/O ports with or without the *	dread 5uS sanity delay. */static inline void z8530_write_port(unsigned long p, u8 d){	outb(d,Z8530_PORT_OF(p));	if(p&Z8530_PORT_SLEEP)		udelay(5);}static void z8530_rx_done(struct z8530_channel *c);static void z8530_tx_done(struct z8530_channel *c);/** *	read_zsreg - Read a register from a Z85230  *	@c: Z8530 channel to read from (2 per chip) *	@reg: Register to read *	FIXME: Use a spinlock. *	 *	Most of the Z8530 registers are indexed off the control registers. *	A read is done by writing to the control register and reading the *	register back.  The caller must hold the lock */ static inline u8 read_zsreg(struct z8530_channel *c, u8 reg){	if(reg)		z8530_write_port(c->ctrlio, reg);	return z8530_read_port(c->ctrlio);}/** *	read_zsdata - Read the data port of a Z8530 channel *	@c: The Z8530 channel to read the data port from * *	The data port provides fast access to some things. We still *	have all the 5uS delays to worry about. */static inline u8 read_zsdata(struct z8530_channel *c){	u8 r;	r=z8530_read_port(c->dataio);	return r;}/** *	write_zsreg - Write to a Z8530 channel register *	@c: The Z8530 channel *	@reg: Register number *	@val: Value to write * *	Write a value to an indexed register. The caller must hold the lock *	to honour the irritating delay rules. We know about register 0 *	being fast to access. * *      Assumes c->lock is held. */static inline void write_zsreg(struct z8530_channel *c, u8 reg, u8 val){	if(reg)		z8530_write_port(c->ctrlio, reg);	z8530_write_port(c->ctrlio, val);}/** *	write_zsctrl - Write to a Z8530 control register *	@c: The Z8530 channel *	@val: Value to write * *	Write directly to the control register on the Z8530 */static inline void write_zsctrl(struct z8530_channel *c, u8 val){	z8530_write_port(c->ctrlio, val);}/** *	write_zsdata - Write to a Z8530 control register *	@c: The Z8530 channel *	@val: Value to write * *	Write directly to the data register on the Z8530 */static inline void write_zsdata(struct z8530_channel *c, u8 val){	z8530_write_port(c->dataio, val);}/* *	Register loading parameters for a dead port */ u8 z8530_dead_port[]={	255};EXPORT_SYMBOL(z8530_dead_port);/* *	Register loading parameters for currently supported circuit types *//* *	Data clocked by telco end. This is the correct data for the UK *	"kilostream" service, and most other similar services. */ u8 z8530_hdlc_kilostream[]={	4,	SYNC_ENAB|SDLC|X1CLK,	2,	0,	/* No vector */	1,	0,	3,	ENT_HM|RxCRC_ENAB|Rx8,	5,	TxCRC_ENAB|RTS|TxENAB|Tx8|DTR,	9,	0,		/* Disable interrupts */	6,	0xFF,	7,	FLAG,	10,	ABUNDER|NRZ|CRCPS,/*MARKIDLE ??*/	11,	TCTRxCP,	14,	DISDPLL,	15,	DCDIE|SYNCIE|CTSIE|TxUIE|BRKIE,	1,	EXT_INT_ENAB|TxINT_ENAB|INT_ALL_Rx,	9,	NV|MIE|NORESET,	255};EXPORT_SYMBOL(z8530_hdlc_kilostream);/* *	As above but for enhanced chips. */ u8 z8530_hdlc_kilostream_85230[]={	4,	SYNC_ENAB|SDLC|X1CLK,	2,	0,	/* No vector */	1,	0,	3,	ENT_HM|RxCRC_ENAB|Rx8,	5,	TxCRC_ENAB|RTS|TxENAB|Tx8|DTR,	9,	0,		/* Disable interrupts */	6,	0xFF,	7,	FLAG,	10,	ABUNDER|NRZ|CRCPS,	/* MARKIDLE?? */	11,	TCTRxCP,	14,	DISDPLL,	15,	DCDIE|SYNCIE|CTSIE|TxUIE|BRKIE,	1,	EXT_INT_ENAB|TxINT_ENAB|INT_ALL_Rx,	9,	NV|MIE|NORESET,	23,	3,		/* Extended mode AUTO TX and EOM*/		255};EXPORT_SYMBOL(z8530_hdlc_kilostream_85230);/** *	z8530_flush_fifo - Flush on chip RX FIFO *	@c: Channel to flush * *	Flush the receive FIFO. There is no specific option for this, we  *	blindly read bytes and discard them. Reading when there is no data *	is harmless. The 8530 has a 4 byte FIFO, the 85230 has 8 bytes. *	 *	All locking is handled for the caller. On return data may still be *	present if it arrived during the flush. */ static void z8530_flush_fifo(struct z8530_channel *c){	read_zsreg(c, R1);	read_zsreg(c, R1);	read_zsreg(c, R1);	read_zsreg(c, R1);	if(c->dev->type==Z85230)	{		read_zsreg(c, R1);		read_zsreg(c, R1);		read_zsreg(c, R1);		read_zsreg(c, R1);	}}	/** *	z8530_rtsdtr - Control the outgoing DTS/RTS line *	@c: The Z8530 channel to control; *	@set: 1 to set, 0 to clear * *	Sets or clears DTR/RTS on the requested line. All locking is handled *	by the caller. For now we assume all boards use the actual RTS/DTR *	on the chip. Apparently one or two don't. We'll scream about them *	later. */static void z8530_rtsdtr(struct z8530_channel *c, int set){	if (set)		c->regs[5] |= (RTS | DTR);	else		c->regs[5] &= ~(RTS | DTR);	write_zsreg(c, R5, c->regs[5]);}/** *	z8530_rx - Handle a PIO receive event *	@c: Z8530 channel to process * *	Receive handler for receiving in PIO mode. This is much like the  *	async one but not quite the same or as complex * *	Note: Its intended that this handler can easily be separated from *	the main code to run realtime. That'll be needed for some machines *	(eg to ever clock 64kbits on a sparc ;)). * *	The RT_LOCK macros don't do anything now. Keep the code covered *	by them as short as possible in all circumstances - clocks cost *	baud. The interrupt handler is assumed to be atomic w.r.t. to *	other code - this is true in the RT case too. * *	We only cover the sync cases for this. If you want 2Mbit async *	do it yourself but consider medical assistance first. This non DMA  *	synchronous mode is portable code. The DMA mode assumes PCI like  *	ISA DMA * *	Called with the device lock held */ static void z8530_rx(struct z8530_channel *c){	u8 ch,stat;	spin_lock(c->lock); 	while(1)	{		/* FIFO empty ? */		if(!(read_zsreg(c, R0)&1))			break;		ch=read_zsdata(c);		stat=read_zsreg(c, R1);			/*		 *	Overrun ?		 */		if(c->count < c->max)		{			*c->dptr++=ch;			c->count++;		}		if(stat&END_FR)		{					/*			 *	Error ?			 */			if(stat&(Rx_OVR|CRC_ERR))			{				/* Rewind the buffer and return */				if(c->skb)					c->dptr=c->skb->data;				c->count=0;				if(stat&Rx_OVR)				{					printk(KERN_WARNING "%s: overrun\n", c->dev->name);					c->rx_overrun++;				}				if(stat&CRC_ERR)				{					c->rx_crc_err++;					/* printk("crc error\n"); */				}				/* Shove the frame upstream */			}			else			{				/*				 *	Drop the lock for RX processing, or		 		 *	there are deadlocks		 		 */				z8530_rx_done(c);				write_zsctrl(c, RES_Rx_CRC);			}		}	}	/*	 *	Clear irq	 */	write_zsctrl(c, ERR_RES);	write_zsctrl(c, RES_H_IUS);	spin_unlock(c->lock);}/** *	z8530_tx - Handle a PIO transmit event *	@c: Z8530 channel to process * *	Z8530 transmit interrupt handler for the PIO mode. The basic *	idea is to attempt to keep the FIFO fed. We fill as many bytes *	in as possible, its quite possible that we won't keep up with the *	data rate otherwise. */ static void z8530_tx(struct z8530_channel *c){	spin_lock(c->lock);	while(c->txcount) {		/* FIFO full ? */		if(!(read_zsreg(c, R0)&4))			break;		c->txcount--;		/*		 *	Shovel out the byte		 */		write_zsreg(c, R8, *c->tx_ptr++);		write_zsctrl(c, RES_H_IUS);		/* We are about to underflow */		if(c->txcount==0)		{			write_zsctrl(c, RES_EOM_L);			write_zsreg(c, R10, c->regs[10]&~ABUNDER);		}	}		/*	 *	End of frame TX - fire another one	 */	 	write_zsctrl(c, RES_Tx_P);	z8530_tx_done(c);	 	write_zsctrl(c, RES_H_IUS);	spin_unlock(c->lock);}/** *	z8530_status - Handle a PIO status exception *	@chan: Z8530 channel to process * *	A status event occurred in PIO synchronous mode. There are several *	reasons the chip will bother us here. A transmit underrun means we *	failed to feed the chip fast enough and just broke a packet. A DCD *	change is a line up or down. We communicate that back to the protocol *	layer for synchronous PPP to renegotiate. */static void z8530_status(struct z8530_channel *chan){	u8 status, altered;	spin_lock(chan->lock);	status=read_zsreg(chan, R0);	altered=chan->status^status;		chan->status=status;		if(status&TxEOM)	{/*		printk("%s: Tx underrun.\n", chan->dev->name); */		chan->stats.tx_fifo_errors++;		write_zsctrl(chan, ERR_RES);		z8530_tx_done(chan);	}			if(altered&chan->dcdcheck)	{		if(status&chan->dcdcheck)		{			printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);			write_zsreg(chan, R3, chan->regs[3]|RxENABLE);			if(chan->netdevice &&			    ((chan->netdevice->type == ARPHRD_HDLC) ||			    (chan->netdevice->type == ARPHRD_PPP)))				sppp_reopen(chan->netdevice);		}		else		{			printk(KERN_INFO "%s: DCD lost\n", chan->dev->name);			write_zsreg(chan, R3, chan->regs[3]&~RxENABLE);			z8530_flush_fifo(chan);		}			}		write_zsctrl(chan, RES_EXT_INT);	write_zsctrl(chan, RES_H_IUS);	spin_unlock(chan->lock);}struct z8530_irqhandler z8530_sync={	z8530_rx,	z8530_tx,	z8530_status};EXPORT_SYMBOL(z8530_sync);/** *	z8530_dma_rx - Handle a DMA RX event *	@chan: Channel to handle * *	Non bus mastering DMA interfaces for the Z8x30 devices. This *	is really pretty PC specific. The DMA mode means that most receive *	events are handled by the DMA hardware. We get a kick here only if *	a frame ended. */ static void z8530_dma_rx(struct z8530_channel *chan){	spin_lock(chan->lock);	if(chan->rxdma_on)	{		/* Special condition check only */		u8 status;			read_zsreg(chan, R7);		read_zsreg(chan, R6);				status=read_zsreg(chan, R1);			if(status&END_FR)		{			z8530_rx_done(chan);	/* Fire up the next one */		}				write_zsctrl(chan, ERR_RES);		write_zsctrl(chan, RES_H_IUS);	}	else	{		/* DMA is off right now, drain the slow way */		z8530_rx(chan);	}		spin_unlock(chan->lock);}/** *	z8530_dma_tx - Handle a DMA TX event *	@chan:	The Z8530 channel to handle * *	We have received an interrupt while doing DMA transmissions. It *	shouldn't happen. Scream loudly if it does. */ static void z8530_dma_tx(struct z8530_channel *chan){	spin_lock(chan->lock);	if(!chan->dma_tx)	{		printk(KERN_WARNING "Hey who turned the DMA off?\n");		z8530_tx(chan);		return;	}	/* This shouldnt occur in DMA mode */	printk(KERN_ERR "DMA tx - bogus event!\n");	z8530_tx(chan);	spin_unlock(chan->lock);}/** *	z8530_dma_status - Handle a DMA status exception *	@chan: Z8530 channel to process *	 *	A status event occurred on the Z8530. We receive these for two reasons *	when in DMA mode. Firstly if we finished a packet transfer we get one *	and kick the next packet out. Secondly we may see a DCD change and *	have to poke the protocol layer. * */ static void z8530_dma_status(struct z8530_channel *chan){	u8 status, altered;	status=read_zsreg(chan, R0);	altered=chan->status^status;		chan->status=status;	if(chan->dma_tx)	{		if(status&TxEOM)		{			unsigned long flags;				flags=claim_dma_lock();			disable_dma(chan->txdma);			clear_dma_ff(chan->txdma);				chan->txdma_on=0;			release_dma_lock(flags);			z8530_tx_done(chan);		}	}	spin_lock(chan->lock);	if(altered&chan->dcdcheck)	{		if(status&chan->dcdcheck)		{			printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);			write_zsreg(chan, R3, chan->regs[3]|RxENABLE);			if(chan->netdevice &&			    ((chan->netdevice->type == ARPHRD_HDLC) ||			    (chan->netdevice->type == ARPHRD_PPP)))				sppp_reopen(chan->netdevice);		}		else		{			printk(KERN_INFO "%s:DCD lost\n", chan->dev->name);			write_zsreg(chan, R3, chan->regs[3]&~RxENABLE);			z8530_flush_fifo(chan);		}	}	

⌨️ 快捷键说明

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