* 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)
{
- unsigned long flags;
-
- spin_lock_irqsave(c->lock, flags);
-
if(reg)
z8530_write_port(c->ctrlio, reg);
z8530_write_port(c->ctrlio, val);
- spin_unlock_irqrestore(c->lock, flags);
}
/**
static void z8530_rx(struct z8530_channel *c)
{
u8 ch,stat;
+ spin_lock(c->lock);
while(1)
{
*/
write_zsctrl(c, ERR_RES);
write_zsctrl(c, RES_H_IUS);
+ spin_unlock(c->lock);
}
static void z8530_tx(struct z8530_channel *c)
{
+ spin_lock(c->lock);
while(c->txcount) {
/* FIFO full ? */
if(!(read_zsreg(c, R0)&4))
z8530_tx_done(c);
write_zsctrl(c, RES_H_IUS);
+ spin_unlock(c->lock);
}
/**
{
u8 status, altered;
+ spin_lock(chan->lock);
status=read_zsreg(chan, R0);
altered=chan->status^status;
}
write_zsctrl(chan, RES_EXT_INT);
write_zsctrl(chan, RES_H_IUS);
+ spin_unlock(chan->lock);
}
struct z8530_irqhandler z8530_sync=
static void z8530_dma_rx(struct z8530_channel *chan)
{
+ spin_lock(chan->lock);
if(chan->rxdma_on)
{
/* Special condition check only */
/* DMA is off right now, drain the slow way */
z8530_rx(chan);
}
+ spin_unlock(chan->lock);
}
/**
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");
/* This shouldnt occur in DMA mode */
printk(KERN_ERR "DMA tx - bogus event!\n");
z8530_tx(chan);
+ spin_unlock(chan->lock);
}
/**
z8530_tx_done(chan);
}
}
+
+ spin_lock(chan->lock);
if(altered&chan->dcdcheck)
{
if(status&chan->dcdcheck)
z8530_flush_fifo(chan);
}
}
+
write_zsctrl(chan, RES_EXT_INT);
write_zsctrl(chan, RES_H_IUS);
+ spin_unlock(chan->lock);
}
struct z8530_irqhandler z8530_dma_sync=
int z8530_sync_dma_open(struct net_device *dev, struct z8530_channel *c)
{
- unsigned long flags;
+ unsigned long cflags, dflags;
c->sync = 1;
c->mtu = dev->mtu+64;
* Enable DMA control mode
*/
- spin_lock_irqsave(c->lock, flags);
+ spin_lock_irqsave(c->lock, cflags);
/*
* TX DMA via DIR/REQ
* Set up the DMA configuration
*/
- flags=claim_dma_lock();
+ dflags=claim_dma_lock();
disable_dma(c->rxdma);
clear_dma_ff(c->rxdma);
set_dma_mode(c->txdma, DMA_MODE_WRITE);
disable_dma(c->txdma);
- release_dma_lock(flags);
+ release_dma_lock(dflags);
/*
* Select the DMA interrupt handlers
z8530_rtsdtr(c,1);
write_zsreg(c, R3, c->regs[R3]|RxENABLE);
- spin_unlock_irqrestore(c->lock, flags);
+ spin_unlock_irqrestore(c->lock, cflags);
return 0;
}
int z8530_sync_txdma_open(struct net_device *dev, struct z8530_channel *c)
{
- unsigned long flags;
+ unsigned long cflags, dflags;
printk("Opening sync interface for TX-DMA\n");
c->sync = 1;
c->tx_dma_buf[1] = c->tx_dma_buf[0] + PAGE_SIZE/2;
- spin_lock_irqsave(c->lock, flags);
+ spin_lock_irqsave(c->lock, cflags);
/*
* Load the PIO receive ring
* Set up the DMA configuration
*/
- flags = claim_dma_lock();
+ 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(flags);
+ release_dma_lock(dflags);
/*
* Select the DMA interrupt handlers
c->irqs = &z8530_txdma_sync;
z8530_rtsdtr(c,1);
write_zsreg(c, R3, c->regs[R3]|RxENABLE);
- spin_unlock_irqrestore(c->lock, flags);
+ spin_unlock_irqrestore(c->lock, cflags);
return 0;
}
int z8530_sync_txdma_close(struct net_device *dev, struct z8530_channel *c)
{
- unsigned long flags;
+ unsigned long dflags, cflags;
u8 chk;
- spin_lock_irqsave(c->lock, flags);
+ spin_lock_irqsave(c->lock, cflags);
c->irqs = &z8530_nop;
c->max = 0;
* Disable the PC DMA channels
*/
- flags = claim_dma_lock();
+ 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(flags);
+ release_dma_lock(dflags);
/*
* Disable DMA control mode
chk=read_zsreg(c,R0);
write_zsreg(c, R3, c->regs[R3]);
z8530_rtsdtr(c,0);
+
+ spin_unlock_irqrestore(c->lock, cflags);
return 0;
}
* Locked operation part of the z8530 init code
*/
-static int do_z8530_init(struct z8530_dev *dev)
+static inline int do_z8530_init(struct z8530_dev *dev)
{
/* NOP the interrupt handlers first - we might get a
floating IRQ transition when we reset the chip */
dev->chanA.dcdcheck=DCD;
dev->chanB.dcdcheck=DCD;
- /* Set up the chip level lock */
- dev->chanA.lock = &dev->lock;
- dev->chanB.lock = &dev->lock;
-
/* Reset the chip */
write_zsreg(&dev->chanA, R9, 0xC0);
udelay(200);