// 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 supportLines 1–500 of 2592. Load more
// 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