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