📄 z85230.c
字号:
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 + -