2592 lines · 69.0 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/*      FarSync WAN driver for Linux (2.6.x kernel version) * *      Actually sync driver for X.21, V.35 and V.24 on FarSync T-series cards * *      Copyright (C) 2001-2004 FarSite Communications Ltd. *      www.farsite.co.uk * *      Author:      R.J.Dunlop    <bob.dunlop@farsite.co.uk> *      Maintainer:  Kevin Curtis  <kevin.curtis@farsite.co.uk> */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/module.h>#include <linux/kernel.h>#include <linux/version.h>#include <linux/pci.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/ioport.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/delay.h>#include <linux/if.h>#include <linux/hdlc.h>#include <asm/io.h>#include <linux/uaccess.h> #include "farsync.h" /*      Module info */MODULE_AUTHOR("R.J.Dunlop <bob.dunlop@farsite.co.uk>");MODULE_DESCRIPTION("FarSync T-Series WAN driver. FarSite Communications Ltd.");MODULE_LICENSE("GPL"); /*      Driver configuration and global parameters *      ========================================== */ /*      Number of ports (per card) and cards supported */#define FST_MAX_PORTS           4#define FST_MAX_CARDS           32 /*      Default parameters for the link */#define FST_TX_QUEUE_LEN        100	/* At 8Mbps a longer queue length is					 * useful					 */#define FST_TXQ_DEPTH           16	/* This one is for the buffering					 * of frames on the way down to the card					 * so that we can keep the card busy					 * and maximise throughput					 */#define FST_HIGH_WATER_MARK     12	/* Point at which we flow control					 * network layer					 */#define FST_LOW_WATER_MARK      8	/* Point at which we remove flow					 * control from network layer					 */#define FST_MAX_MTU             8000	/* Huge but possible */#define FST_DEF_MTU             1500	/* Common sane value */ #define FST_TX_TIMEOUT          (2 * HZ) #ifdef ARPHRD_RAWHDLC#define ARPHRD_MYTYPE   ARPHRD_RAWHDLC	/* Raw frames */#else#define ARPHRD_MYTYPE   ARPHRD_HDLC	/* Cisco-HDLC (keepalives etc) */#endif /* Modules parameters and associated variables */static int fst_txq_low = FST_LOW_WATER_MARK;static int fst_txq_high = FST_HIGH_WATER_MARK;static int fst_max_reads = 7;static int fst_excluded_cards;static int fst_excluded_list[FST_MAX_CARDS]; module_param(fst_txq_low, int, 0);module_param(fst_txq_high, int, 0);module_param(fst_max_reads, int, 0);module_param(fst_excluded_cards, int, 0);module_param_array(fst_excluded_list, int, NULL, 0); /*      Card shared memory layout *      ========================= */#pragma pack(1) /*      This information is derived in part from the FarSite FarSync Smc.h *      file. Unfortunately various name clashes and the non-portability of the *      bit field declarations in that file have meant that I have chosen to *      recreate the information here. * *      The SMC (Shared Memory Configuration) has a version number that is *      incremented every time there is a significant change. This number can *      be used to check that we have not got out of step with the firmware *      contained in the .CDE files. */#define SMC_VERSION 24 #define FST_MEMSIZE 0x100000	/* Size of card memory (1Mb) */ #define SMC_BASE 0x00002000L	/* Base offset of the shared memory window main				 * configuration structure				 */#define BFM_BASE 0x00010000L	/* Base offset of the shared memory window DMA				 * buffers				 */ #define LEN_TX_BUFFER 8192	/* Size of packet buffers */#define LEN_RX_BUFFER 8192 #define LEN_SMALL_TX_BUFFER 256	/* Size of obsolete buffs used for DOS diags */#define LEN_SMALL_RX_BUFFER 256 #define NUM_TX_BUFFER 2		/* Must be power of 2. Fixed by firmware */#define NUM_RX_BUFFER 8 /* Interrupt retry time in milliseconds */#define INT_RETRY_TIME 2 /*      The Am186CH/CC processors support a SmartDMA mode using circular pools *      of buffer descriptors. The structure is almost identical to that used *      in the LANCE Ethernet controllers. Details available as PDF from the *      AMD web site: https://www.amd.com/products/epd/processors/\ *                    2.16bitcont/3.am186cxfa/a21914/21914.pdf */struct txdesc {			/* Transmit descriptor */	volatile u16 ladr;	/* Low order address of packet. This is a				 * linear address in the Am186 memory space				 */	volatile u8 hadr;	/* High order address. Low 4 bits only, high 4				 * bits must be zero				 */	volatile u8 bits;	/* Status and config */	volatile u16 bcnt;	/* 2s complement of packet size in low 15 bits.				 * Transmit terminal count interrupt enable in				 * top bit.				 */	u16 unused;		/* Not used in Tx */}; struct rxdesc {			/* Receive descriptor */	volatile u16 ladr;	/* Low order address of packet */	volatile u8 hadr;	/* High order address */	volatile u8 bits;	/* Status and config */	volatile u16 bcnt;	/* 2s complement of buffer size in low 15 bits.				 * Receive terminal count interrupt enable in				 * top bit.				 */	volatile u16 mcnt;	/* Message byte count (15 bits) */}; /* Convert a length into the 15 bit 2's complement *//* #define cnv_bcnt(len)   (( ~(len) + 1 ) & 0x7FFF ) *//* Since we need to set the high bit to enable the completion interrupt this * can be made a lot simpler */#define cnv_bcnt(len)   (-(len)) /* Status and config bits for the above */#define DMA_OWN         0x80	/* SmartDMA owns the descriptor */#define TX_STP          0x02	/* Tx: start of packet */#define TX_ENP          0x01	/* Tx: end of packet */#define RX_ERR          0x40	/* Rx: error (OR of next 4 bits) */#define RX_FRAM         0x20	/* Rx: framing error */#define RX_OFLO         0x10	/* Rx: overflow error */#define RX_CRC          0x08	/* Rx: CRC error */#define RX_HBUF         0x04	/* Rx: buffer error */#define RX_STP          0x02	/* Rx: start of packet */#define RX_ENP          0x01	/* Rx: end of packet */ /* Interrupts from the card are caused by various events which are presented * in a circular buffer as several events may be processed on one physical int */#define MAX_CIRBUFF     32 struct cirbuff {	u8 rdindex;		/* read, then increment and wrap */	u8 wrindex;		/* write, then increment and wrap */	u8 evntbuff[MAX_CIRBUFF];}; /* Interrupt event codes. * Where appropriate the two low order bits indicate the port number */#define CTLA_CHG        0x18	/* Control signal changed */#define CTLB_CHG        0x19#define CTLC_CHG        0x1A#define CTLD_CHG        0x1B #define INIT_CPLT       0x20	/* Initialisation complete */#define INIT_FAIL       0x21	/* Initialisation failed */ #define ABTA_SENT       0x24	/* Abort sent */#define ABTB_SENT       0x25#define ABTC_SENT       0x26#define ABTD_SENT       0x27 #define TXA_UNDF        0x28	/* Transmission underflow */#define TXB_UNDF        0x29#define TXC_UNDF        0x2A#define TXD_UNDF        0x2B #define F56_INT         0x2C#define M32_INT         0x2D #define TE1_ALMA        0x30 /* Port physical configuration. See farsync.h for field values */struct port_cfg {	u16 lineInterface;	/* Physical interface type */	u8 x25op;		/* Unused at present */	u8 internalClock;	/* 1 => internal clock, 0 => external */	u8 transparentMode;	/* 1 => on, 0 => off */	u8 invertClock;		/* 0 => normal, 1 => inverted */	u8 padBytes[6];		/* Padding */	u32 lineSpeed;		/* Speed in bps */}; /* TE1 port physical configuration */struct su_config {	u32 dataRate;	u8 clocking;	u8 framing;	u8 structure;	u8 interface;	u8 coding;	u8 lineBuildOut;	u8 equalizer;	u8 transparentMode;	u8 loopMode;	u8 range;	u8 txBufferMode;	u8 rxBufferMode;	u8 startingSlot;	u8 losThreshold;	u8 enableIdleCode;	u8 idleCode;	u8 spare[44];}; /* TE1 Status */struct su_status {	u32 receiveBufferDelay;	u32 framingErrorCount;	u32 codeViolationCount;	u32 crcErrorCount;	u32 lineAttenuation;	u8 portStarted;	u8 lossOfSignal;	u8 receiveRemoteAlarm;	u8 alarmIndicationSignal;	u8 spare[40];}; /* Finally sling all the above together into the shared memory structure. * Sorry it's a hodge podge of arrays, structures and unused bits, it's been * evolving under NT for some time so I guess we're stuck with it. * The structure starts at offset SMC_BASE. * See farsync.h for some field values. */struct fst_shared {	/* DMA descriptor rings */	struct rxdesc rxDescrRing[FST_MAX_PORTS][NUM_RX_BUFFER];	struct txdesc txDescrRing[FST_MAX_PORTS][NUM_TX_BUFFER]; 	/* Obsolete small buffers */	u8 smallRxBuffer[FST_MAX_PORTS][NUM_RX_BUFFER][LEN_SMALL_RX_BUFFER];	u8 smallTxBuffer[FST_MAX_PORTS][NUM_TX_BUFFER][LEN_SMALL_TX_BUFFER]; 	u8 taskStatus;		/* 0x00 => initialising, 0x01 => running,				 * 0xFF => halted				 */ 	u8 interruptHandshake;	/* Set to 0x01 by adapter to signal interrupt,				 * set to 0xEE by host to acknowledge interrupt				 */ 	u16 smcVersion;		/* Must match SMC_VERSION */ 	u32 smcFirmwareVersion;	/* 0xIIVVRRBB where II = product ID, VV = major				 * version, RR = revision and BB = build				 */ 	u16 txa_done;		/* Obsolete completion flags */	u16 rxa_done;	u16 txb_done;	u16 rxb_done;	u16 txc_done;	u16 rxc_done;	u16 txd_done;	u16 rxd_done; 	u16 mailbox[4];		/* Diagnostics mailbox. Not used */ 	struct cirbuff interruptEvent;	/* interrupt causes */ 	u32 v24IpSts[FST_MAX_PORTS];	/* V.24 control input status */	u32 v24OpSts[FST_MAX_PORTS];	/* V.24 control output status */ 	struct port_cfg portConfig[FST_MAX_PORTS]; 	u16 clockStatus[FST_MAX_PORTS];	/* lsb: 0=> present, 1=> absent */ 	u16 cableStatus;	/* lsb: 0=> present, 1=> absent */ 	u16 txDescrIndex[FST_MAX_PORTS];	/* transmit descriptor ring index */	u16 rxDescrIndex[FST_MAX_PORTS];	/* receive descriptor ring index */ 	u16 portMailbox[FST_MAX_PORTS][2];	/* command, modifier */	u16 cardMailbox[4];	/* Not used */ 	/* Number of times the card thinks the host has	 * missed an interrupt by not acknowledging	 * within 2mS (I guess NT has problems)	 */	u32 interruptRetryCount; 	/* Driver private data used as an ID. We'll not	 * use this as I'd rather keep such things	 * in main memory rather than on the PCI bus	 */	u32 portHandle[FST_MAX_PORTS]; 	/* Count of Tx underflows for stats */	u32 transmitBufferUnderflow[FST_MAX_PORTS]; 	/* Debounced V.24 control input status */	u32 v24DebouncedSts[FST_MAX_PORTS]; 	/* Adapter debounce timers. Don't touch */	u32 ctsTimer[FST_MAX_PORTS];	u32 ctsTimerRun[FST_MAX_PORTS];	u32 dcdTimer[FST_MAX_PORTS];	u32 dcdTimerRun[FST_MAX_PORTS]; 	u32 numberOfPorts;	/* Number of ports detected at startup */ 	u16 _reserved[64]; 	u16 cardMode;		/* Bit-mask to enable features:				 * Bit 0: 1 enables LED identify mode				 */ 	u16 portScheduleOffset; 	struct su_config suConfig;	/* TE1 Bits */	struct su_status suStatus; 	u32 endOfSmcSignature;	/* endOfSmcSignature MUST be the last member of				 * the structure and marks the end of shared				 * memory. Adapter code initializes it as				 * END_SIG.				 */}; /* endOfSmcSignature value */#define END_SIG                 0x12345678 /* Mailbox values. (portMailbox) */#define NOP             0	/* No operation */#define ACK             1	/* Positive acknowledgement to PC driver */#define NAK             2	/* Negative acknowledgement to PC driver */#define STARTPORT       3	/* Start an HDLC port */#define STOPPORT        4	/* Stop an HDLC port */#define ABORTTX         5	/* Abort the transmitter for a port */#define SETV24O         6	/* Set V24 outputs */ /* PLX Chip Register Offsets */#define CNTRL_9052      0x50	/* Control Register */#define CNTRL_9054      0x6c	/* Control Register */ #define INTCSR_9052     0x4c	/* Interrupt control/status register */#define INTCSR_9054     0x68	/* Interrupt control/status register */ /* 9054 DMA Registers *//* Note that we will be using DMA Channel 0 for copying rx data * and Channel 1 for copying tx data */#define DMAMODE0        0x80#define DMAPADR0        0x84#define DMALADR0        0x88#define DMASIZ0         0x8c#define DMADPR0         0x90#define DMAMODE1        0x94#define DMAPADR1        0x98#define DMALADR1        0x9c#define DMASIZ1         0xa0#define DMADPR1         0xa4#define DMACSR0         0xa8#define DMACSR1         0xa9#define DMAARB          0xac#define DMATHR          0xb0#define DMADAC0         0xb4#define DMADAC1         0xb8#define DMAMARBR        0xac #define FST_MIN_DMA_LEN 64#define FST_RX_DMA_INT  0x01#define FST_TX_DMA_INT  0x02#define FST_CARD_INT    0x04 /* Larger buffers are positioned in memory at offset BFM_BASE */struct buf_window {	u8 txBuffer[FST_MAX_PORTS][NUM_TX_BUFFER][LEN_TX_BUFFER];	u8 rxBuffer[FST_MAX_PORTS][NUM_RX_BUFFER][LEN_RX_BUFFER];}; /* Calculate offset of a buffer object within the shared memory window */#define BUF_OFFSET(X)   (BFM_BASE + offsetof(struct buf_window, X)) #pragma pack() /*      Device driver private information *      ================================= *//*      Per port (line or channel) information */struct fst_port_info {	struct net_device *dev; /* Device struct - must be first */	struct fst_card_info *card;	/* Card we're associated with */	int index;		/* Port index on the card */	int hwif;		/* Line hardware (lineInterface copy) */	int run;		/* Port is running */	int mode;		/* Normal or FarSync raw */	int rxpos;		/* Next Rx buffer to use */	int txpos;		/* Next Tx buffer to use */	int txipos;		/* Next Tx buffer to check for free */	int start;		/* Indication of start/stop to network */	/* A sixteen entry transmit queue	 */	int txqs;		/* index to get next buffer to tx */	int txqe;		/* index to queue next packet */	struct sk_buff *txq[FST_TXQ_DEPTH];	/* The queue */	int rxqdepth;}; /*      Per card information */struct fst_card_info {	char __iomem *mem;	/* Card memory mapped to kernel space */	char __iomem *ctlmem;	/* Control memory for PCI cards */	unsigned int phys_mem;	/* Physical memory window address */	unsigned int phys_ctlmem;	/* Physical control memory address */	unsigned int irq;	/* Interrupt request line number */	unsigned int nports;	/* Number of serial ports */	unsigned int type;	/* Type index of card */	unsigned int state;	/* State of card */	spinlock_t card_lock;	/* Lock for SMP access */	unsigned short pci_conf;	/* PCI card config in I/O space */	/* Per port info */	struct fst_port_info ports[FST_MAX_PORTS];	struct pci_dev *device;	/* Information about the pci device */	int card_no;		/* Inst of the card on the system */	int family;		/* TxP or TxU */	int dmarx_in_progress;	int dmatx_in_progress;	unsigned long int_count;	unsigned long int_time_ave;	void *rx_dma_handle_host;	dma_addr_t rx_dma_handle_card;	void *tx_dma_handle_host;	dma_addr_t tx_dma_handle_card;	struct sk_buff *dma_skb_rx;	struct fst_port_info *dma_port_rx;	struct fst_port_info *dma_port_tx;	int dma_len_rx;	int dma_len_tx;	int dma_txpos;	int dma_rxpos;}; /* Convert an HDLC device pointer into a port info pointer and similar */#define dev_to_port(D)  (dev_to_hdlc(D)->priv)#define port_to_dev(P)  ((P)->dev) /*      Shared memory window access macros * *      We have a nice memory based structure above, which could be directly *      mapped on i386 but might not work on other architectures unless we use *      the readb,w,l and writeb,w,l macros. Unfortunately these macros take *      physical offsets so we have to convert. The only saving grace is that *      this should all collapse back to a simple indirection eventually. */#define WIN_OFFSET(X)   ((long)&(((struct fst_shared *)SMC_BASE)->X)) #define FST_RDB(C, E)    (readb((C)->mem + WIN_OFFSET(E)))#define FST_RDW(C, E)    (readw((C)->mem + WIN_OFFSET(E)))#define FST_RDL(C, E)    (readl((C)->mem + WIN_OFFSET(E))) #define FST_WRB(C, E, B)  (writeb((B), (C)->mem + WIN_OFFSET(E)))#define FST_WRW(C, E, W)  (writew((W), (C)->mem + WIN_OFFSET(E)))#define FST_WRL(C, E, L)  (writel((L), (C)->mem + WIN_OFFSET(E))) /*      Debug support

Lines 1–500 of 2592.