📄 farsync.c
字号:
/* * 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 * * 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. * * Author: R.J.Dunlop <bob.dunlop@farsite.co.uk> * Maintainer: Kevin Curtis <kevin.curtis@farsite.co.uk> */#include <linux/module.h>#include <linux/kernel.h>#include <linux/version.h>#include <linux/pci.h>#include <linux/ioport.h>#include <linux/init.h>#include <linux/if.h>#include <linux/hdlc.h>#include <asm/io.h>#include <asm/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_PARM(fst_txq_low, "i");MODULE_PARM(fst_txq_high, "i");MODULE_PARM(fst_max_reads, "i");MODULE_PARM(fst_excluded_cards, "i");MODULE_PARM(fst_excluded_list, "0-32i");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, the syncppp module forces * this down assuming a slower line I * guess. */#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 varaibles */int fst_txq_low = FST_LOW_WATER_MARK;int fst_txq_high = FST_HIGH_WATER_MARK;int fst_max_reads = 7;int fst_excluded_cards = 0;int fst_excluded_list[FST_MAX_CARDS];/* 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: http://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 32struct 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) ((unsigned int)&(((struct buf_window *)BFM_BASE)->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 *mem; /* Card memory mapped to kernel space */ char *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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -