linux/drivers/net/wan/farsync.c

// 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    <[email protected]>
 *      Maintainer:  Kevin Curtis  <[email protected]>
 */

#define pr_fmt(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();
MODULE_DESCRIPTION();
MODULE_LICENSE();

/*      Driver configuration and global parameters
 *      ==========================================
 */

/*      Number of ports (per card) and cards supported
 */
#define FST_MAX_PORTS
#define FST_MAX_CARDS

/*      Default parameters for the link
 */
#define FST_TX_QUEUE_LEN
#define FST_TXQ_DEPTH
#define FST_HIGH_WATER_MARK
#define FST_LOW_WATER_MARK
#define FST_MAX_MTU
#define FST_DEF_MTU

#define FST_TX_TIMEOUT

#ifdef ARPHRD_RAWHDLC
#define ARPHRD_MYTYPE
#else
#define ARPHRD_MYTYPE
#endif

/* Modules parameters and associated variables
 */
static int fst_txq_low =;
static int fst_txq_high =;
static int fst_max_reads =;
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();

/*      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

#define FST_MEMSIZE

#define SMC_BASE
#define BFM_BASE

#define LEN_TX_BUFFER
#define LEN_RX_BUFFER

#define LEN_SMALL_TX_BUFFER
#define LEN_SMALL_RX_BUFFER

#define NUM_TX_BUFFER
#define NUM_RX_BUFFER

/* Interrupt retry time in milliseconds */
#define INT_RETRY_TIME

/*      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 {};

struct rxdesc {};

/* 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)

/* Status and config bits for the above */
#define DMA_OWN
#define TX_STP
#define TX_ENP
#define RX_ERR
#define RX_FRAM
#define RX_OFLO
#define RX_CRC
#define RX_HBUF
#define RX_STP
#define RX_ENP

/* 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

struct cirbuff {};

/* Interrupt event codes.
 * Where appropriate the two low order bits indicate the port number
 */
#define CTLA_CHG
#define CTLB_CHG
#define CTLC_CHG
#define CTLD_CHG

#define INIT_CPLT
#define INIT_FAIL

#define ABTA_SENT
#define ABTB_SENT
#define ABTC_SENT
#define ABTD_SENT

#define TXA_UNDF
#define TXB_UNDF
#define TXC_UNDF
#define TXD_UNDF

#define F56_INT
#define M32_INT

#define TE1_ALMA

/* Port physical configuration. See farsync.h for field values */
struct port_cfg {};

/* TE1 port physical configuration */
struct su_config {};

/* TE1 Status */
struct su_status {};

/* 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 {};

/* endOfSmcSignature value */
#define END_SIG

/* Mailbox values. (portMailbox) */
#define NOP
#define ACK
#define NAK
#define STARTPORT
#define STOPPORT
#define ABORTTX
#define SETV24O

/* PLX Chip Register Offsets */
#define CNTRL_9052
#define CNTRL_9054

#define INTCSR_9052
#define INTCSR_9054

/* 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
#define DMAPADR0
#define DMALADR0
#define DMASIZ0
#define DMADPR0
#define DMAMODE1
#define DMAPADR1
#define DMALADR1
#define DMASIZ1
#define DMADPR1
#define DMACSR0
#define DMACSR1
#define DMAARB
#define DMATHR
#define DMADAC0
#define DMADAC1
#define DMAMARBR

#define FST_MIN_DMA_LEN
#define FST_RX_DMA_INT
#define FST_TX_DMA_INT
#define FST_CARD_INT

/* Larger buffers are positioned in memory at offset BFM_BASE */
struct buf_window {};

/* Calculate offset of a buffer object within the shared memory window */
#define BUF_OFFSET(X)

#pragma pack()

/*      Device driver private information
 *      =================================
 */
/*      Per port (line or channel) information
 */
struct fst_port_info {};

/*      Per card information
 */
struct fst_card_info {};

/* Convert an HDLC device pointer into a port info pointer and similar */
#define dev_to_port(D)
#define port_to_dev(P)

/*      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)

#define FST_RDB(C, E)
#define FST_RDW(C, E)
#define FST_RDL(C, E)

#define FST_WRB(C, E, B)
#define FST_WRW(C, E, W)
#define FST_WRL(C, E, L)

/*      Debug support
 */
#if FST_DEBUG

static int fst_debug_mask = { FST_DEBUG };

/* Most common debug activity is to print something if the corresponding bit
 * is set in the debug mask. Note: this uses a non-ANSI extension in GCC to
 * support variable numbers of macro parameters. The inverted if prevents us
 * eating someone else's else clause.
 */
#define dbg
#else
#define dbg(F, fmt, args...)
#endif

/*      PCI ID lookup table
 */
static const struct pci_device_id fst_pci_dev_id[] =;

MODULE_DEVICE_TABLE(pci, fst_pci_dev_id);

/*      Device Driver Work Queues
 *
 *      So that we don't spend too much time processing events in the
 *      Interrupt Service routine, we will declare a work queue per Card
 *      and make the ISR schedule a task in the queue for later execution.
 *      In the 2.4 Kernel we used to use the immediate queue for BH's
 *      Now that they are gone, tasklets seem to be much better than work
 *      queues.
 */

static void do_bottom_half_tx(struct fst_card_info *card);
static void do_bottom_half_rx(struct fst_card_info *card);
static void fst_process_tx_work_q(struct tasklet_struct *unused);
static void fst_process_int_work_q(struct tasklet_struct *unused);

static DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q);
static DECLARE_TASKLET(fst_int_task, fst_process_int_work_q);

static struct fst_card_info *fst_card_array[FST_MAX_CARDS];
static DEFINE_SPINLOCK(fst_work_q_lock);
static u64 fst_work_txq;
static u64 fst_work_intq;

static void
fst_q_work_item(u64 *queue, int card_index)
{}

static void
fst_process_tx_work_q(struct tasklet_struct *unused)
{}

static void
fst_process_int_work_q(struct tasklet_struct *unused)
{}

/*      Card control functions
 *      ======================
 */
/*      Place the processor in reset state
 *
 * Used to be a simple write to card control space but a glitch in the latest
 * AMD Am186CH processor means that we now have to do it by asserting and de-
 * asserting the PLX chip PCI Adapter Software Reset. Bit 30 in CNTRL register
 * at offset 9052_CNTRL.  Note the updates for the TXU.
 */
static inline void
fst_cpureset(struct fst_card_info *card)
{}

/*      Release the processor from reset
 */
static inline void
fst_cpurelease(struct fst_card_info *card)
{}

/*      Clear the cards interrupt flag
 */
static inline void
fst_clear_intr(struct fst_card_info *card)
{}

/*      Enable card interrupts
 */
static inline void
fst_enable_intr(struct fst_card_info *card)
{}

/*      Disable card interrupts
 */
static inline void
fst_disable_intr(struct fst_card_info *card)
{}

/*      Process the result of trying to pass a received frame up the stack
 */
static void
fst_process_rx_status(int rx_status, char *name)
{}

/*      Initilaise DMA for PLX 9054
 */
static inline void
fst_init_dma(struct fst_card_info *card)
{}

/*      Tx dma complete interrupt
 */
static void
fst_tx_dma_complete(struct fst_card_info *card, struct fst_port_info *port,
		    int len, int txpos)
{}

/* Mark it for our own raw sockets interface
 */
static __be16 farsync_type_trans(struct sk_buff *skb, struct net_device *dev)
{}

/*      Rx dma complete interrupt
 */
static void
fst_rx_dma_complete(struct fst_card_info *card, struct fst_port_info *port,
		    int len, struct sk_buff *skb, int rxp)
{}

/*      Receive a frame through the DMA
 */
static inline void
fst_rx_dma(struct fst_card_info *card, dma_addr_t dma, u32 mem, int len)
{}

/*      Send a frame through the DMA
 */
static inline void
fst_tx_dma(struct fst_card_info *card, dma_addr_t dma, u32 mem, int len)
{}

/*      Issue a Mailbox command for a port.
 *      Note we issue them on a fire and forget basis, not expecting to see an
 *      error and not waiting for completion.
 */
static void
fst_issue_cmd(struct fst_port_info *port, unsigned short cmd)
{}

/*      Port output signals control
 */
static inline void
fst_op_raise(struct fst_port_info *port, unsigned int outputs)
{}

static inline void
fst_op_lower(struct fst_port_info *port, unsigned int outputs)
{}

/*      Setup port Rx buffers
 */
static void
fst_rx_config(struct fst_port_info *port)
{}

/*      Setup port Tx buffers
 */
static void
fst_tx_config(struct fst_port_info *port)
{}

/*      TE1 Alarm change interrupt event
 */
static void
fst_intr_te1_alarm(struct fst_card_info *card, struct fst_port_info *port)
{}

/*      Control signal change interrupt event
 */
static void
fst_intr_ctlchg(struct fst_card_info *card, struct fst_port_info *port)
{}

/*      Log Rx Errors
 */
static void
fst_log_rx_error(struct fst_card_info *card, struct fst_port_info *port,
		 unsigned char dmabits, int rxp, unsigned short len)
{}

/*      Rx Error Recovery
 */
static void
fst_recover_rx_error(struct fst_card_info *card, struct fst_port_info *port,
		     unsigned char dmabits, int rxp, unsigned short len)
{}

/*      Rx complete interrupt
 */
static void
fst_intr_rx(struct fst_card_info *card, struct fst_port_info *port)
{}

/*      The bottom half to the ISR
 *
 */

static void
do_bottom_half_tx(struct fst_card_info *card)
{}

static void
do_bottom_half_rx(struct fst_card_info *card)
{}

/*      The interrupt service routine
 *      Dev_id is our fst_card_info pointer
 */
static irqreturn_t
fst_intr(int dummy, void *dev_id)
{}

/*      Check that the shared memory configuration is one that we can handle
 *      and that some basic parameters are correct
 */
static void
check_started_ok(struct fst_card_info *card)
{}

static int
set_conf_from_info(struct fst_card_info *card, struct fst_port_info *port,
		   struct fstioc_info *info)
{}

static void
gather_conf_info(struct fst_card_info *card, struct fst_port_info *port,
		 struct fstioc_info *info)
{}

static int
fst_set_iface(struct fst_card_info *card, struct fst_port_info *port,
	      struct if_settings *ifs)
{}

static int
fst_get_iface(struct fst_card_info *card, struct fst_port_info *port,
	      struct if_settings *ifs)
{}

static int
fst_siocdevprivate(struct net_device *dev, struct ifreq *ifr, void __user *data, int cmd)
{}

static int
fst_ioctl(struct net_device *dev, struct if_settings *ifs)
{}

static void
fst_openport(struct fst_port_info *port)
{}

static void
fst_closeport(struct fst_port_info *port)
{}

static int
fst_open(struct net_device *dev)
{}

static int
fst_close(struct net_device *dev)
{}

static int
fst_attach(struct net_device *dev, unsigned short encoding, unsigned short parity)
{}

static void
fst_tx_timeout(struct net_device *dev, unsigned int txqueue)
{}

static netdev_tx_t
fst_start_xmit(struct sk_buff *skb, struct net_device *dev)
{}

/*      Card setup having checked hardware resources.
 *      Should be pretty bizarre if we get an error here (kernel memory
 *      exhaustion is one possibility). If we do see a problem we report it
 *      via a printk and leave the corresponding interface and all that follow
 *      disabled.
 */
static char *type_strings[] =;

static int
fst_init_card(struct fst_card_info *card)
{}

static const struct net_device_ops fst_ops =;

/*      Initialise card when detected.
 *      Returns 0 to indicate success, or errno otherwise.
 */
static int
fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{}

/*      Cleanup and close down a card
 */
static void
fst_remove_one(struct pci_dev *pdev)
{}

static struct pci_driver fst_driver =;

static int __init
fst_init(void)
{}

static void __exit
fst_cleanup_module(void)
{}

module_init();
module_exit(fst_cleanup_module);