Пример #1
0
static void z8530_dma_rx(struct z8530_channel *chan)
{
	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);
	}
}
Пример #2
0
static void z8530_status(struct z8530_channel *chan)
{
	u8 status, altered;

	status = read_zsreg(chan, R0);
	altered = chan->status ^ status;

	chan->status = status;

	if (status & TxEOM) {
/*		printk("%s: Tx underrun.\n", chan->dev->name); */
		chan->netdevice->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)
				netif_carrier_on(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);
			if (chan->netdevice)
				netif_carrier_off(chan->netdevice);
		}

	}
	write_zsctrl(chan, RES_EXT_INT);
	write_zsctrl(chan, RES_H_IUS);
}
Пример #3
0
static void z8530_tx(struct z8530_channel *c)
{
	while(c->txcount) {
		/* FIFO full ? */
		if(!(read_zsreg(c, R0)&4))
			return;
		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);
}
Пример #4
0
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);
}
Пример #5
0
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);
        }
    }

    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);
}
Пример #6
0
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);
}
Пример #7
0
static void z8530_tx_clear(struct z8530_channel *c)
{
	write_zsctrl(c, RES_Tx_P);
	write_zsctrl(c, RES_H_IUS);
}
Пример #8
0
static void z8530_rx(struct z8530_channel *c)
{
	u8 ch,stat;

	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);
}
Пример #9
0
static void z8530_tx_begin(struct z8530_channel *c)
{
	unsigned long flags;
	if(c->tx_skb)
		return;

	c->tx_skb=c->tx_next_skb;
	c->tx_next_skb=NULL;
	c->tx_ptr=c->tx_next_ptr;

	if(c->tx_skb==NULL)
	{
		/* Idle on */
		if(c->dma_tx)
		{
			flags=claim_dma_lock();
			disable_dma(c->txdma);
			/*
			 *	Check if we crapped out.
			 */
			if (get_dma_residue(c->txdma))
			{
				c->netdevice->stats.tx_dropped++;
				c->netdevice->stats.tx_fifo_errors++;
			}
			release_dma_lock(flags);
		}
		c->txcount=0;
	}
	else
	{
		c->txcount=c->tx_skb->len;


		if(c->dma_tx)
		{
			/*
			 *	FIXME. DMA is broken for the original 8530,
			 *	on the older parts we need to set a flag and
			 *	wait for a further TX interrupt to fire this
			 *	stage off
			 */

			flags=claim_dma_lock();
			disable_dma(c->txdma);

			/*
			 *	These two are needed by the 8530/85C30
			 *	and must be issued when idling.
			 */

			if(c->dev->type!=Z85230)
			{
				write_zsctrl(c, RES_Tx_CRC);
				write_zsctrl(c, RES_EOM_L);
			}
			write_zsreg(c, R10, c->regs[10]&~ABUNDER);
			clear_dma_ff(c->txdma);
			set_dma_addr(c->txdma, virt_to_bus(c->tx_ptr));
			set_dma_count(c->txdma, c->txcount);
			enable_dma(c->txdma);
			release_dma_lock(flags);
			write_zsctrl(c, RES_EOM_L);
			write_zsreg(c, R5, c->regs[R5]|TxENAB);
		}
		else
		{

			/* ABUNDER off */
			write_zsreg(c, R10, c->regs[10]);
			write_zsctrl(c, RES_Tx_CRC);

			while(c->txcount && (read_zsreg(c,R0)&Tx_BUF_EMP))
			{
				write_zsreg(c, R8, *c->tx_ptr++);
				c->txcount--;
			}

		}
	}
	/*
	 *	Since we emptied tx_skb we can ask for more
	 */
	netif_wake_queue(c->netdevice);
}