linux/drivers/net/ethernet/8390/lib8390.c

// SPDX-License-Identifier: GPL-1.0+

/* 8390.c: A general NS8390 ethernet driver core for linux. */
/*
	Written 1992-94 by Donald Becker.

	Copyright 1993 United States Government as represented by the
	Director, National Security Agency.

	The author may be reached as [email protected], or C/O
	Scyld Computing Corporation
	410 Severn Ave., Suite 210
	Annapolis MD 21403


  This is the chip-specific code for many 8390-based ethernet adaptors.
  This is not a complete driver, it must be combined with board-specific
  code such as ne.c, wd.c, 3c503.c, etc.

  Seeing how at least eight drivers use this code, (not counting the
  PCMCIA ones either) it is easy to break some card by what seems like
  a simple innocent change. Please contact me or Donald if you think
  you have found something that needs changing. -- PG


  Changelog:

  Paul Gortmaker	: remove set_bit lock, other cleanups.
  Paul Gortmaker	: add ei_get_8390_hdr() so we can pass skb's to
			  ei_block_input() for eth_io_copy_and_sum().
  Paul Gortmaker	: exchange static int ei_pingpong for a #define,
			  also add better Tx error handling.
  Paul Gortmaker	: rewrite Rx overrun handling as per NS specs.
  Alexey Kuznetsov	: use the 8390's six bit hash multicast filter.
  Paul Gortmaker	: tweak ANK's above multicast changes a bit.
  Paul Gortmaker	: update packet statistics for v2.1.x
  Alan Cox		: support arbitrary stupid port mappings on the
			  68K Macintosh. Support >16bit I/O spaces
  Paul Gortmaker	: add kmod support for auto-loading of the 8390
			  module by all drivers that require it.
  Alan Cox		: Spinlocking work, added 'BUG_83C690'
  Paul Gortmaker	: Separate out Tx timeout code from Tx path.
  Paul Gortmaker	: Remove old unused single Tx buffer code.
  Hayato Fujiwara	: Add m32r support.
  Paul Gortmaker	: use skb_padto() instead of stack scratch area

  Sources:
  The National Semiconductor LAN Databook, and the 3Com 3c503 databook.

  */

#include <linux/build_bug.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/bitops.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <asm/irq.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/in.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/crc32.h>

#include <linux/netdevice.h>
#include <linux/etherdevice.h>

#define NS8390_CORE
#include "8390.h"

#define BUG_83C690

/* These are the operational function interfaces to board-specific
   routines.
	void reset_8390(struct net_device *dev)
		Resets the board associated with DEV, including a hardware reset of
		the 8390.  This is only called when there is a transmit timeout, and
		it is always followed by 8390_init().
	void block_output(struct net_device *dev, int count, const unsigned char *buf,
					  int start_page)
		Write the COUNT bytes of BUF to the packet buffer at START_PAGE.  The
		"page" value uses the 8390's 256-byte pages.
	void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page)
		Read the 4 byte, page aligned 8390 header. *If* there is a
		subsequent read, it will be of the rest of the packet.
	void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
		Read COUNT bytes from the packet buffer into the skb data area. Start
		reading from RING_OFFSET, the address as the 8390 sees it.  This will always
		follow the read of the 8390 header.
*/
#define ei_reset_8390
#define ei_block_output
#define ei_block_input
#define ei_get_8390_hdr

/* Index to functions. */
static void ei_tx_intr(struct net_device *dev);
static void ei_tx_err(struct net_device *dev);
static void ei_receive(struct net_device *dev);
static void ei_rx_overrun(struct net_device *dev);

/* Routines generic to NS8390-based boards. */
static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
								int start_page);
static void do_set_multicast_list(struct net_device *dev);
static void __NS8390_init(struct net_device *dev, int startp);

static unsigned version_printed;
static int msg_enable;
static const int default_msg_level =;
module_param(msg_enable, int, 0444);
MODULE_PARM_DESC();

/*
 *	SMP and the 8390 setup.
 *
 *	The 8390 isn't exactly designed to be multithreaded on RX/TX. There is
 *	a page register that controls bank and packet buffer access. We guard
 *	this with ei_local->page_lock. Nobody should assume or set the page other
 *	than zero when the lock is not held. Lock holders must restore page 0
 *	before unlocking. Even pure readers must take the lock to protect in
 *	page 0.
 *
 *	To make life difficult the chip can also be very slow. We therefore can't
 *	just use spinlocks. For the longer lockups we disable the irq the device
 *	sits on and hold the lock. We must hold the lock because there is a dual
 *	processor case other than interrupts (get stats/set multicast list in
 *	parallel with each other and transmit).
 *
 *	Note: in theory we can just disable the irq on the card _but_ there is
 *	a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs"
 *	enter lock, take the queued irq. So we waddle instead of flying.
 *
 *	Finally by special arrangement for the purpose of being generally
 *	annoying the transmit function is called bh atomic. That places
 *	restrictions on the user context callers as disable_irq won't save
 *	them.
 *
 *	Additional explanation of problems with locking by Alan Cox:
 *
 *	"The author (me) didn't use spin_lock_irqsave because the slowness of the
 *	card means that approach caused horrible problems like losing serial data
 *	at 38400 baud on some chips. Remember many 8390 nics on PCI were ISA
 *	chips with FPGA front ends.
 *
 *	Ok the logic behind the 8390 is very simple:
 *
 *	Things to know
 *		- IRQ delivery is asynchronous to the PCI bus
 *		- Blocking the local CPU IRQ via spin locks was too slow
 *		- The chip has register windows needing locking work
 *
 *	So the path was once (I say once as people appear to have changed it
 *	in the mean time and it now looks rather bogus if the changes to use
 *	disable_irq_nosync_irqsave are disabling the local IRQ)
 *
 *
 *		Take the page lock
 *		Mask the IRQ on chip
 *		Disable the IRQ (but not mask locally- someone seems to have
 *			broken this with the lock validator stuff)
 *			[This must be _nosync as the page lock may otherwise
 *				deadlock us]
 *		Drop the page lock and turn IRQs back on
 *
 *		At this point an existing IRQ may still be running but we can't
 *		get a new one
 *
 *		Take the lock (so we know the IRQ has terminated) but don't mask
 *	the IRQs on the processor
 *		Set irqlock [for debug]
 *
 *		Transmit (slow as ****)
 *
 *		re-enable the IRQ
 *
 *
 *	We have to use disable_irq because otherwise you will get delayed
 *	interrupts on the APIC bus deadlocking the transmit path.
 *
 *	Quite hairy but the chip simply wasn't designed for SMP and you can't
 *	even ACK an interrupt without risking corrupting other parallel
 *	activities on the chip." [lkml, 25 Jul 2007]
 */



/**
 * ei_open - Open/initialize the board.
 * @dev: network device to initialize
 *
 * This routine goes all-out, setting everything
 * up anew at each open, even though many of these registers should only
 * need to be set once at boot.
 */
static int __ei_open(struct net_device *dev)
{}

/**
 * ei_close - shut down network device
 * @dev: network device to close
 *
 * Opposite of ei_open(). Only used when "ifconfig <devname> down" is done.
 */
static int __ei_close(struct net_device *dev)
{}

/**
 * ei_tx_timeout - handle transmit time out condition
 * @dev: network device which has apparently fallen asleep
 *
 * Called by kernel when device never acknowledges a transmit has
 * completed (or failed) - i.e. never posted a Tx related interrupt.
 */

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

/**
 * ei_start_xmit - begin packet transmission
 * @skb: packet to be sent
 * @dev: network device to which packet is sent
 *
 * Sends a packet to an 8390 network device.
 */

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

/**
 * ei_interrupt - handle the interrupts from an 8390
 * @irq: interrupt number
 * @dev_id: a pointer to the net_device
 *
 * Handle the ether interface interrupts. We pull packets from
 * the 8390 via the card specific functions and fire them at the networking
 * stack. We also handle transmit completions and wake the transmit path if
 * necessary. We also update the counters and do other housekeeping as
 * needed.
 */

static irqreturn_t __ei_interrupt(int irq, void *dev_id)
{}

#ifdef CONFIG_NET_POLL_CONTROLLER
static void __ei_poll(struct net_device *dev)
{}
#endif

/**
 * ei_tx_err - handle transmitter error
 * @dev: network device which threw the exception
 *
 * A transmitter error has happened. Most likely excess collisions (which
 * is a fairly normal condition). If the error is one where the Tx will
 * have been aborted, we try and send another one right away, instead of
 * letting the failed packet sit and collect dust in the Tx buffer. This
 * is a much better solution as it avoids kernel based Tx timeouts, and
 * an unnecessary card reset.
 *
 * Called with lock held.
 */

static void ei_tx_err(struct net_device *dev)
{}

/**
 * ei_tx_intr - transmit interrupt handler
 * @dev: network device for which tx intr is handled
 *
 * We have finished a transmit: check for errors and then trigger the next
 * packet to be sent. Called with lock held.
 */

static void ei_tx_intr(struct net_device *dev)
{}

/**
 * ei_receive - receive some packets
 * @dev: network device with which receive will be run
 *
 * We have a good packet(s), get it/them out of the buffers.
 * Called with lock held.
 */

static void ei_receive(struct net_device *dev)
{}

/**
 * ei_rx_overrun - handle receiver overrun
 * @dev: network device which threw exception
 *
 * We have a receiver overrun: we have to kick the 8390 to get it started
 * again. Problem is that you have to kick it exactly as NS prescribes in
 * the updated datasheets, or "the NIC may act in an unpredictable manner."
 * This includes causing "the NIC to defer indefinitely when it is stopped
 * on a busy network."  Ugh.
 * Called with lock held. Don't call this with the interrupts off or your
 * computer will hate you - it takes 10ms or so.
 */

static void ei_rx_overrun(struct net_device *dev)
{}

/*
 *	Collect the stats. This is called unlocked and from several contexts.
 */

static struct net_device_stats *__ei_get_stats(struct net_device *dev)
{}

/*
 * Form the 64 bit 8390 multicast table from the linked list of addresses
 * associated with this dev structure.
 */

static inline void make_mc_bits(u8 *bits, struct net_device *dev)
{}

/**
 * do_set_multicast_list - set/clear multicast filter
 * @dev: net device for which multicast filter is adjusted
 *
 *	Set or clear the multicast filter for this adaptor. May be called
 *	from a BH in 2.1.x. Must be called with lock held.
 */

static void do_set_multicast_list(struct net_device *dev)
{}

/*
 *	Called without lock held. This is invoked from user context and may
 *	be parallel to just about everything else. Its also fairly quick and
 *	not called too often. Must protect against both bh and irq users
 */

static void __ei_set_multicast_list(struct net_device *dev)
{}

/**
 * ethdev_setup - init rest of 8390 device struct
 * @dev: network device structure to init
 *
 * Initialize the rest of the 8390 device structure.  Do NOT __init
 * this, as it is used by 8390 based modular drivers too.
 */

static void ethdev_setup(struct net_device *dev)
{}

/**
 * alloc_ei_netdev - alloc_etherdev counterpart for 8390
 * @size: extra bytes to allocate
 *
 * Allocate 8390-specific net_device.
 */
static struct net_device *____alloc_ei_netdev(int size)
{}




/* This page of functions should be 8390 generic */
/* Follow National Semi's recommendations for initializing the "NIC". */

/**
 * NS8390_init - initialize 8390 hardware
 * @dev: network device to initialize
 * @startp: boolean.  non-zero value to initiate chip processing
 *
 *	Must be called with lock held.
 */

static void __NS8390_init(struct net_device *dev, int startp)
{}

/* Trigger a transmit start, assuming the length is valid.
   Always called with the page lock held */

static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
								int start_page)
{}