svn commit: r272094 - head/sys/dev/lmc

Gleb Smirnoff glebius at FreeBSD.org
Thu Sep 25 06:47:38 UTC 2014


Author: glebius
Date: Thu Sep 25 06:47:38 2014
New Revision: 272094
URL: http://svnweb.freebsd.org/changeset/base/272094

Log:
  Run through unifdef(1) with slight hand-editing after. It is obvious,
  that the driver is not going to be ever improved in terms of hardware
  support, it is going to be only maintained as our kernel APIs change.
  Carrying all the compatibility with ancient versions of NetBSD, OpenBSD,
  Linux and BSDI, as well as obsoleted FreeBSD versions has no reason.

Modified:
  head/sys/dev/lmc/if_lmc.c
  head/sys/dev/lmc/if_lmc.h

Modified: head/sys/dev/lmc/if_lmc.c
==============================================================================
--- head/sys/dev/lmc/if_lmc.c	Thu Sep 25 06:00:31 2014	(r272093)
+++ head/sys/dev/lmc/if_lmc.c	Thu Sep 25 06:47:38 2014	(r272094)
@@ -71,7 +71,6 @@
  *
  * Send bug reports and improvements to <boggs at boggs.palo-alto.ca.us>.
  */
-#ifdef __FreeBSD__
 # include <sys/param.h>	/* OS version */
 # define  IFNET 1
 # include "opt_inet.h"	/* INET */
@@ -90,15 +89,9 @@
 #  define NETGRAPH 0
 # endif
 # define  P2P 0		/* not in FreeBSD */
-# if (__FreeBSD_version >= 500000)
-#  define NSPPP 1	/* No count devices in FreeBSD 5 */
-#  include "opt_bpf.h"	/* DEV_BPF */
-#  define NBPFILTER DEV_BPF
-# else  /* FreeBSD-4 */
-# include "sppp.h"	/* NSPPP */
-#  include "bpf.h"	/* NBPF */
-#  define NBPFILTER NBPF
-# endif
+# define NSPPP 1	/* No count devices in FreeBSD 5 */
+# include "opt_bpf.h"	/* DEV_BPF */
+# define NBPFILTER DEV_BPF
 # define  GEN_HDLC 0	/* not in FreeBSD */
 #
 # include <sys/systm.h>
@@ -121,16 +114,9 @@
 # include <sys/rman.h>
 # include <vm/vm.h>
 # include <vm/pmap.h>
-# if (__FreeBSD_version >= 700000)
-#  include <sys/priv.h>
-# endif
-# if (__FreeBSD_version >= 500000)
+# include <sys/priv.h>
 #  include <sys/mutex.h>
 #  include <dev/pci/pcivar.h>
-# else /* FreeBSD-4 */
-#  include <sys/proc.h>
-#  include <pci/pcivar.h>
-# endif
 # if NETGRAPH
 #  include <netgraph/ng_message.h>
 #  include <netgraph/netgraph.h>
@@ -147,180 +133,10 @@
 # endif
 /* and finally... */
 # include <dev/lmc/if_lmc.h>
-#endif /*__FreeBSD__*/
 
-#ifdef __NetBSD__
-# include <sys/param.h>	/* OS version */
-# define  IFNET 1
-# include "opt_inet.h"	/* INET6, INET */
-# define  NETGRAPH 0	/* not in NetBSD */
-# include "sppp.h"	/* NSPPP */
-# define  P2P 0		/* not in NetBSD */
-# include "opt_altq_enabled.h" /* ALTQ */
-# include "bpfilter.h"	/* NBPFILTER */
-# define  GEN_HDLC 0	/* not in NetBSD */
-#
-# include <sys/systm.h>
-# include <sys/kernel.h>
-# include <sys/lkm.h>
-# include <sys/mbuf.h>
-# include <sys/socket.h>
-# include <sys/sockio.h>
-# include <sys/device.h>
-# include <sys/lock.h>
-# include <net/if.h>
-# include <net/if_var.h>
-# include <net/if_types.h>
-# include <net/if_media.h>
-# include <net/netisr.h>
-# include <machine/bus.h>
-# include <machine/intr.h>
-# include <dev/pci/pcivar.h>
-# if (__NetBSD_Version__ >= 106000000)
-#  include <uvm/uvm_extern.h>
-# else
-#  include <vm/vm.h>
-# endif
-# if (INET || INET6)
-#  include <netinet/in.h>
-#  include <netinet/in_var.h>
-# endif
-# if NSPPP
-#  if (__NetBSD_Version__ >= 106000000)
-#   include <net/if_spppvar.h>
-#  else
-#   include <net/if_sppp.h>
-#  endif
-# endif
-# if NBPFILTER
-#  include <net/bpf.h>
-# endif
-/* and finally... */
-# include "if_lmc.h"
-#endif /*__NetBSD__*/
 
-#ifdef __OpenBSD__
-# include <sys/param.h>	/* OS version */
-# define  IFNET 1
-/* -DINET  is passed on the compiler command line */
-/* -DINET6 is passed on the compiler command line */
-# define  NETGRAPH 0	/* not in OpenBSD */
-# include "sppp.h"	/* NSPPP */
-# define  P2P 0		/* not in OpenBSD */
-/* -DALTQ  is passed on the compiler command line */
-# include "bpfilter.h"	/* NBPFILTER */
-# define  GEN_HDLC 0	/* not in OpenBSD */
-#
-# include <sys/systm.h>
-# include <sys/kernel.h>
-# include <sys/conf.h>
-# include <sys/exec.h>
-# include <sys/lkm.h>
-# include <sys/mbuf.h>
-# include <sys/socket.h>
-# include <sys/sockio.h>
-# include <sys/device.h>
-# include <sys/lock.h>
-# include <net/if.h>
-# include <net/if_types.h>
-# include <net/if_media.h>
-# include <net/netisr.h>
-# include <machine/bus.h>
-# include <machine/intr.h>
-# include <dev/pci/pcivar.h>
-# if (OpenBSD >= 200206)
-#  include <uvm/uvm_extern.h>
-# else
-#  include <vm/vm.h>
-# endif
-# if (INET || INET6)
-#  include <netinet/in.h>
-#  include <netinet/in_var.h>
-# endif
-# if NSPPP
-#  include <net/if_sppp.h>
-# endif
-# if NBPFILTER
-#  include <net/bpf.h>
-# endif
-/* and finally... */
-# include "if_lmc.h"
-#endif /*__OpenBSD__*/
 
-#ifdef __bsdi__
-# include <sys/param.h>	/* OS version */
-# define  IFNET 1
-/* -DINET  is passed on the compiler command line */
-/* -DINET6 is passed on the compiler command line */
-# define  NETGRAPH 0	/* not in BSD/OS */
-# define  NSPPP 0	/* not in BSD/OS */
-/* -DPPP   is passed on the compiler command line */
-/* -DCISCO_HDLC is passed on the compiler command line */
-/* -DFR    is passed on the compiler command line */
-# if (PPP || CISCO_HDLC || FR)
-#  define P2P 1
-# else
-#  define P2P 0
-# endif
-# define  ALTQ 0	/* not in BSD/OS */
-# include "bpfilter.h"	/* NBPFILTER */
-# define  GEN_HDLC 0	/* not in BSD/OS */
-#
-# include <sys/kernel.h>
-# include <sys/malloc.h>
-# include <sys/mbuf.h>
-# include <sys/socket.h>
-# include <sys/sockio.h>
-# include <sys/device.h>
-# include <sys/lock.h>
-# include <net/if.h>
-# include <net/if_types.h>
-# include <net/if_media.h>
-# include <net/netisr.h>
-# include <vm/vm.h>
-# include <i386/isa/dma.h>
-# include <i386/isa/isavar.h>
-# include <i386/include/cpu.h>
-# include <i386/pci/pci.h>
-# if (INET || INET6)
-#  include <netinet/in.h>
-#  include <netinet/in_var.h>
-# endif
-# if P2P
-#  include <net/if_p2p.h>
-#  include <sys/ttycom.h>
-# endif
-# if NBPFILTER
-#  include <net/bpf.h>
-# endif
-/* and finally... */
-# include "if_lmc.h"
-#endif /*__bsdi__*/
 
-#ifdef __linux__
-# include <linux/config.h>
-# if (CONFIG_HDLC || CONFIG_HDLC_MODULE)
-#  define GEN_HDLC 1
-# else
-#  define GEN_HDLC 0
-# endif
-# define IFNET 0	/* different in Linux */
-# define NETGRAPH 0	/* not in Linux */
-# define NSPPP 0	/* different in Linux */
-# define P2P 0		/* not in Linux */
-# define ALTQ 0		/* different in Linux */
-# define NBPFILTER 0	/* different in Linux */
-#
-# include <linux/pci.h>
-# include <linux/delay.h>
-# include <linux/netdevice.h>
-# include <linux/if_arp.h>
-# if GEN_HDLC
-#  include <linux/hdlc.h>
-# endif
-/* and finally... */
-# include "if_lmc.h"
-#endif /* __linux__ */
 
 /* The SROM is a generic 93C46 serial EEPROM (64 words by 16 bits). */
 /* Data is set up before the RISING edge of CLK; CLK is parked low. */
@@ -2484,44 +2300,6 @@ struct card t1_card =
 
 /* RAWIP is raw IP packets (v4 or v6) in HDLC frames with NO HEADERS. */
 /* No HDLC Address/Control fields!  No line control protocol at all!  */
-/* This code is BSD/ifnet-specific; Linux and Netgraph also do RAWIP. */
-
-#if IFNET
-
-# if ((defined(__FreeBSD__) && (__FreeBSD_version < 500000)) ||\
-        defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__))
-static void
-netisr_dispatch(int isr, struct mbuf *mbuf)
-  {
-  struct ifqueue *intrq = NULL;
-  int qfull = 0;
-
-#if INET
-  if (isr == NETISR_IP)   intrq = &ipintrq;
-#endif
-#if INET6
-  if (isr == NETISR_IPV6) intrq = &ip6intrq;
-#endif
-
-  if ((intrq != NULL) && ((qfull = IF_QFULL(intrq)) == 0))
-    {
-    /* rxintr_cleanup() ENQUEUES in a hard interrupt. */
-    /* networking code DEQUEUES in a soft interrupt. */
-    /* Some BSD QUEUE routines are not interrupt-safe. */
-    DISABLE_INTR; /* noop in FreeBSD */
-    IF_ENQUEUE(intrq, mbuf);
-    ENABLE_INTR;
-    schednetisr(isr); /* schedule a soft interrupt */
-    }
-  else
-    {
-    m_freem(mbuf);
-    if ((intrq != NULL) && (qfull != 0))
-      IF_DROP(intrq);
-    }
-  }
-# endif /* ((__FreeBSD__ && (__FreeBSD_version < 500000)) || */
-           /* __NetBSD__ || __OpenBSD__ || __bsdi__) */
 
 /* rxintr_cleanup calls this to give a newly arrived pkt to higher levels. */
 static void
@@ -2549,20 +2327,12 @@ lmc_raw_input(struct ifnet *ifp, struct 
     }
   }
 
-#endif /* IFNET */
-
-/* There are TWO VERSIONS of interrupt/DMA code: Linux & BSD.
- * Handling Linux and the BSDs with CPP directives would
- *  make the code unreadable, so there are two versions.
- * Conceptually, the two versions do the same thing and
- *  core_interrupt() doesn't know they are different.
- *
+/*
  * We are "standing on the head of a pin" in these routines.
  * Tulip CSRs can be accessed, but nothing else is interrupt-safe!
  * Do NOT access: MII, GPIO, SROM, BIOSROM, XILINX, SYNTH, or DAC.
  */
 
-#if BSD /* BSD version of interrupt/DMA code */
 
 /* Singly-linked tail-queues hold mbufs with active DMA.
  * For RX, single mbuf clusters; for TX, mbuf chains are queued.
@@ -2593,7 +2363,6 @@ mbuf_dequeue(struct desc_ring *ring)
   return m;
   }
 
-# ifdef __FreeBSD__
 static void /* *** FreeBSD ONLY *** Callout from bus_dmamap_load() */
 fbsd_dmamap_load(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
   {
@@ -2602,7 +2371,6 @@ fbsd_dmamap_load(void *arg, bus_dma_segm
   ring->segs[0] = segs[0];
   ring->segs[1] = segs[1];
   }
-# endif
 
 /* Initialize a DMA descriptor ring. */
 static int  /* BSD version */
@@ -2620,15 +2388,12 @@ create_ring(softc_t *sc, struct desc_rin
     return EINVAL;
     }
 
-#ifdef __FreeBSD__
 
   /* Create a DMA tag for descriptors and buffers. */
   if ((error = bus_dma_tag_create(bus_get_dma_tag(sc->dev),
    4, 0, BUS_SPACE_MAXADDR_32BIT,
    BUS_SPACE_MAXADDR, NULL, NULL, PAGE_SIZE, 2, PAGE_SIZE, BUS_DMA_ALLOCNOW,
-# if (__FreeBSD_version >= 502000)
    NULL, NULL,
-# endif
    &ring->tag)))
     {
     printf("%s: bus_dma_tag_create() failed: error %d\n", NAME_UNIT, error);
@@ -2662,70 +2427,6 @@ create_ring(softc_t *sc, struct desc_rin
       return error;
       }
 
-#elif (defined(__NetBSD__) || defined(__OpenBSD__))
-
-  /* Use the DMA tag passed to attach() for descriptors and buffers. */
-  ring->tag = sc->pa_dmat;
-
-  /* Allocate wired physical memory for DMA descriptor array. */
-  if ((error = bus_dmamem_alloc(ring->tag, size_descs, PAGE_SIZE, 0,
-   ring->segs, 1, &ring->nsegs, BUS_DMA_NOWAIT)))
-    {
-    printf("%s: bus_dmamem_alloc() failed; error %d\n", NAME_UNIT, error);
-    return error;
-    }
-
-  /* Map physical address to kernel virtual address. */
-  if ((error = bus_dmamem_map(ring->tag, ring->segs, ring->nsegs,
-   size_descs, (caddr_t *)&ring->first, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)))
-    {
-    printf("%s: bus_dmamem_map() failed; error %d\n", NAME_UNIT, error);
-    return error;
-    }
-  descs = ring->first; /* suppress compiler warning about aliasing */
-  memset(descs, 0, size_descs);
-
-  /* Allocate dmamap for PCI access to DMA descriptor array. */
-  if ((error = bus_dmamap_create(ring->tag, size_descs, 1,
-   size_descs, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ring->map)))
-    {
-    printf("%s: bus_dmamap_create() failed; error %d\n", NAME_UNIT, error);
-    return error;
-    }
-
-  /* Map kernel virtual address to PCI address for DMA descriptor array. */
-  if ((error = bus_dmamap_load(ring->tag, ring->map, descs, size_descs,
-   0, BUS_DMA_NOWAIT)))
-    {
-    printf("%s: bus_dmamap_load() failed; error %d\n", NAME_UNIT, error);
-    return error;
-    }
-  ring->dma_addr = ring->map->dm_segs[0].ds_addr;
-
-  /* Allocate dmamaps for each DMA descriptor. */
-  for (i=0; i<num_descs; i++)
-    if ((error = bus_dmamap_create(ring->tag, MAX_DESC_LEN, 2,
-     MAX_CHUNK_LEN, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &descs[i].map)))
-      {
-      printf("%s: bus_dmamap_create() failed; error %d\n", NAME_UNIT, error);
-      return error;
-      }
-
-#elif defined(__bsdi__)
-
-  /* Allocate wired physical memory for DMA descriptor array. */
-  if ((ring->first = malloc(size_descs, M_DEVBUF, M_NOWAIT)) == NULL)
-    {
-    printf("%s: malloc() failed for DMA descriptor array\n", NAME_UNIT);
-    return ENOMEM;
-    }
-  descs = ring->first;
-  memset(descs, 0, size_descs);
-
-  /* Map kernel virtual address to PCI address for DMA descriptor array. */
-  ring->dma_addr = vtophys(descs); /* Relax! BSD/OS only. */
-
-#endif
 
   ring->read  = descs;
   ring->write = descs;
@@ -2765,7 +2466,6 @@ destroy_ring(softc_t *sc, struct desc_ri
     if (ring->read++ == ring->last) ring->read = ring->first;
     }
 
-#ifdef __FreeBSD__
 
   /* Free the dmamaps of all DMA descriptors. */
   for (desc=ring->first; desc!=ring->last+1; desc++)
@@ -2782,33 +2482,6 @@ destroy_ring(softc_t *sc, struct desc_ri
   if (ring->tag != NULL)
     bus_dma_tag_destroy(ring->tag);
 
-#elif (defined(__NetBSD__) || defined(__OpenBSD__))
-
-  /* Free the dmamaps of all DMA descriptors. */
-  for (desc=ring->first; desc!=ring->last+1; desc++)
-    if (desc->map != NULL)
-      bus_dmamap_destroy(ring->tag, desc->map);
-
-  /* Unmap PCI address for DMA descriptor array. */
-  if (ring->dma_addr != 0)
-    bus_dmamap_unload(ring->tag, ring->map);
-  /* Free dmamap for DMA descriptor array. */
-  if (ring->map != NULL)
-    bus_dmamap_destroy(ring->tag, ring->map);
-  /* Unmap kernel address for DMA descriptor array. */
-  if (ring->first != NULL)
-    bus_dmamem_unmap(ring->tag, (caddr_t)ring->first, ring->size_descs);
-  /* Free kernel memory for DMA descriptor array. */
-  if (ring->segs[0].ds_addr != 0)
-    bus_dmamem_free(ring->tag, ring->segs, ring->nsegs);
-
-#elif defined(__bsdi__)
-
-  /* Free kernel memory for DMA descriptor array. */
-  if (ring->first != NULL)
-    free(ring->first, M_DEVBUF);
-
-#endif
   }
 
 /* Clean up after a packet has been received. */
@@ -2821,7 +2494,7 @@ rxintr_cleanup(softc_t *sc)
   struct mbuf *new_mbuf;
   int pkt_len, desc_len;
 
-#if (defined(__FreeBSD__) && defined(DEVICE_POLLING))
+#if defined(DEVICE_POLLING)
   /* Input packet flow control (livelock prevention): */
   /* Give pkts to higher levels only if quota is > 0. */
   if (sc->quota <= 0) return 0;
@@ -2890,11 +2563,7 @@ rxintr_cleanup(softc_t *sc)
       {
       first_mbuf = new_mbuf;
       first_mbuf->m_pkthdr.len   = pkt_len; /* total pkt length */
-#if IFNET
       first_mbuf->m_pkthdr.rcvif = sc->ifp; /* how it got here */
-#else
-      first_mbuf->m_pkthdr.rcvif = NULL;
-#endif
       }
     else /* 2) link mbufs. */
       {
@@ -2933,11 +2602,9 @@ rxintr_cleanup(softc_t *sc)
     /* Include CRC and one flag byte in input byte count. */
     sc->status.cntrs.ibytes += first_mbuf->m_pkthdr.len + sc->config.crc_len +1;
     sc->status.cntrs.ipackets++;
-#if IFNET
     sc->ifp->if_ipackets++;
     LMC_BPF_MTAP(first_mbuf);
-#endif
-#if (defined(__FreeBSD__) && defined(DEVICE_POLLING))
+#if defined(DEVICE_POLLING)
     sc->quota--;
 #endif
 
@@ -2945,12 +2612,8 @@ rxintr_cleanup(softc_t *sc)
 #if NETGRAPH
     if (sc->ng_hook != NULL) /* is hook connected? */
       {
-# if (__FreeBSD_version >= 500000)
       int error;  /* ignore error */
       NG_SEND_DATA_ONLY(error, sc->ng_hook, first_mbuf);
-# else /* FreeBSD-4 */
-      ng_queue_data(sc->ng_hook, first_mbuf, NULL);
-# endif
       return 1;  /* did something */
       }
 #endif /* NETGRAPH */
@@ -3053,13 +2716,7 @@ rxintr_setup(softc_t *sc)
   DMA_SYNC(desc->map, desc_len, BUS_DMASYNC_PREREAD);
 
   /* Set up the DMA descriptor. */
-#ifdef __FreeBSD__
   desc->address1 = ring->segs[0].ds_addr;
-#elif (defined(__NetBSD__) || defined(__OpenBSD__))
-  desc->address1 = desc->map->dm_segs[0].ds_addr;
-#elif defined(__bsdi__)
-  desc->address1 = vtophys(m->m_data); /* Relax! BSD/OS only. */
-#endif
   desc->length1  = desc_len>>1;
   desc->address2 = desc->address1 + desc->length1;
   desc->length2  = desc_len>>1;
@@ -3108,10 +2765,8 @@ txintr_cleanup(softc_t *sc)
       /* Include CRC and one flag byte in output byte count. */
       sc->status.cntrs.obytes += m->m_pkthdr.len + sc->config.crc_len +1;
       sc->status.cntrs.opackets++;
-#if IFNET
       sc->ifp->if_opackets++;
       LMC_BPF_MTAP(m);
-#endif
       /* The only bad TX status is fifo underrun. */
       if ((desc->status & TLP_DSTS_TX_UNDERRUN) != 0)
         sc->status.cntrs.fifo_under++;
@@ -3181,15 +2836,9 @@ txintr_setup_mbuf(softc_t *sc, struct mb
       /* Prevent wild fetches if mapping fails (nsegs==0). */
       desc->length1  = desc->length2  = 0;
       desc->address1 = desc->address2 = 0;
-#if (defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))
         {
-# ifdef __FreeBSD__
         bus_dma_segment_t *segs = ring->segs;
         int nsegs = ring->nsegs;
-# elif (defined(__NetBSD__) || defined(__OpenBSD__))
-        bus_dma_segment_t *segs = desc->map->dm_segs;
-        int nsegs = desc->map->dm_nsegs;
-# endif
         if (nsegs >= 1)
           {
           desc->address1 = segs[0].ds_addr;
@@ -3201,10 +2850,6 @@ txintr_setup_mbuf(softc_t *sc, struct mb
           desc->length2  = segs[1].ds_len;
           }
         }
-#elif defined(__bsdi__)
-      desc->address1 = vtophys(data); /* Relax! BSD/OS only. */
-      desc->length1  = desc_len;
-#endif
 
       data   += desc_len;
       length -= desc_len;
@@ -3296,737 +2941,201 @@ txintr_setup(softc_t *sc)
   return 1; /* did something */
   }
 
-#endif /* BSD */
-
-#ifdef __linux__
-/* NOTE: this is the LINUX version of the interrupt/DMA code, */
-
-/* Singly-linked tail-queues hold sk_buffs with active DMA.
- * skbuffs are linked through their sk_buff.next field.
- * Callers must hold sc->bottom_lock; not otherwise locked.
- */
-
-/* Put an skbuff on the tail of the descriptor ring queue. */
-static void  /* Linux version */
-skbuff_enqueue(struct desc_ring *ring, struct sk_buff *skb)
-  {
-  skb->next = NULL;
-  if (ring->tail == NULL)
-    ring->head = skb;
-  else
-    ring->tail->next = skb;
-  ring->tail = skb;
-  }
-
-/* Get an skbuff from the head of the descriptor ring queue. */
-static struct sk_buff*  /* Linux version */
-skbuff_dequeue(struct desc_ring *ring)
-  {
-  struct sk_buff *skb = ring->head;
-  if (skb != NULL)
-    if ((ring->head = skb->next) == NULL)
-      ring->tail = NULL;
-  return skb;
-  }
-
-/* Initialize a DMA descriptor ring. */
-static int  /* Linux version */
-create_ring(softc_t *sc, struct desc_ring *ring, int num_descs)
-  {
-  struct dma_desc *descs;
-  int size_descs = sizeof(struct dma_desc)*num_descs;
-
-  /* Allocate and map memory for DMA descriptor array. */
-  if ((descs = pci_alloc_consistent(sc->pci_dev, size_descs,
-   &ring->dma_addr)) == NULL)
-    {
-    printk("%s: pci_alloc_consistent() failed\n", NAME_UNIT);
-    return ENOMEM;
-    }
-  memset(descs, 0, size_descs);
-
-  ring->read  = descs;
-  ring->write = descs;
-  ring->first = descs;
-  ring->last  = descs + num_descs -1;
-  ring->last->control = TLP_DCTL_END_RING;
-  ring->num_descs = num_descs;
-  ring->size_descs = size_descs;
-  ring->head = NULL;
-  ring->tail = NULL;
 
-  return 0;
-  }
 
-/* Destroy a DMA descriptor ring */
-static void  /* Linux version */
-destroy_ring(softc_t *sc, struct desc_ring *ring)
+static void
+check_intr_status(softc_t *sc)
   {
-  struct sk_buff *skb;
+  u_int32_t status, cfcs, op_mode;
+  u_int32_t missed, overruns;
 
-  /* Free queued skbuffs. */
-  while ((skb = skbuff_dequeue(ring)) != NULL)
-    dev_kfree_skb(skb);
+  /* Check for four unusual events:
+   *  1) fatal PCI bus errors       - some are recoverable
+   *  2) transmitter FIFO underruns - increase fifo threshold
+   *  3) receiver FIFO overruns     - clear potential hangup
+   *  4) no receive descs or bufs   - count missed packets
+   */
 
-  /* TX may have one pkt that is not on any queue. */
-  if (sc->tx_skb != NULL)
+  /* 1) A fatal bus error causes a Tulip to stop initiating bus cycles. */
+  /* Module unload/load or boot are the only fixes for Parity Errors. */
+  /* Master and Target Aborts can be cleared and life may continue. */
+  status = READ_CSR(TLP_STATUS);
+  if ((status & TLP_STAT_FATAL_ERROR) != 0)
     {
-    dev_kfree_skb(sc->tx_skb);
-    sc->tx_skb = NULL;
+    u_int32_t fatal = (status & TLP_STAT_FATAL_BITS)>>TLP_STAT_FATAL_SHIFT;
+    printf("%s: FATAL PCI BUS ERROR: %s%s%s%s\n", NAME_UNIT,
+     (fatal == 0) ? "PARITY ERROR" : "",
+     (fatal == 1) ? "MASTER ABORT" : "",
+     (fatal == 2) ? "TARGET ABORT" : "",
+     (fatal >= 3) ? "RESERVED (?)" : "");
+    cfcs = READ_PCI_CFG(sc, TLP_CFCS);  /* try to clear it */
+    cfcs &= ~(TLP_CFCS_MSTR_ABORT | TLP_CFCS_TARG_ABORT);
+    WRITE_PCI_CFG(sc, TLP_CFCS, cfcs);
     }
 
-  if (ring->first != NULL)
+  /* 2) If the transmitter fifo underruns, increase the transmit fifo */
+  /*  threshold: the number of bytes required to be in the fifo */
+  /*  before starting the transmitter (cost: increased tx delay). */
+  /* The TX_FSM must be stopped to change this parameter. */
+  if ((status & TLP_STAT_TX_UNDERRUN) != 0)
     {
-    /* Unmap active DMA descriptors. */
-    while (ring->read != ring->write)
+    op_mode = READ_CSR(TLP_OP_MODE);
+    /* enable store-and-forward mode if tx_threshold tops out? */
+    if ((op_mode & TLP_OP_TX_THRESH) < TLP_OP_TX_THRESH)
       {
-      pci_unmap_single(sc->pci_dev, ring->read->address1,
-       ring->read->length1 + ring->read->length2, PCI_DMA_BIDIRECTIONAL);
-      if (ring->read++ == ring->last) ring->read = ring->first;
+      op_mode += 0x4000;  /* increment TX_THRESH field; can't overflow */
+      WRITE_CSR(TLP_OP_MODE, op_mode & ~TLP_OP_TX_RUN);
+      /* Wait for the TX FSM to stop; it might be processing a pkt. */
+      while (READ_CSR(TLP_STATUS) & TLP_STAT_TX_FSM); /* XXX HANG */
+      WRITE_CSR(TLP_OP_MODE, op_mode); /* restart tx */
+      if (DRIVER_DEBUG)
+        printf("%s: tx underrun; tx fifo threshold now %d bytes\n",
+         NAME_UNIT, 128<<((op_mode>>TLP_OP_TR_SHIFT)&3));
       }
-
-    /* Unmap and free memory for DMA descriptor array. */
-    pci_free_consistent(sc->pci_dev, ring->size_descs, ring->first,
-     ring->dma_addr);
     }
-  }
-
-static int  /* Linux version */
-rxintr_cleanup(softc_t *sc)
-  {
-  struct desc_ring *ring = &sc->rxring;
-  struct dma_desc *first_desc, *last_desc;
-  struct sk_buff *first_skb=NULL, *last_skb=NULL;
-  struct sk_buff *new_skb;
-  int pkt_len, desc_len;
 
-  /* Input packet flow control (livelock prevention): */
-  /* Give pkts to higher levels only if quota is > 0. */
-  if (sc->quota <= 0) return 0;
-
-  /* This looks complicated, but remember: packets up to 4032 */
-  /*  bytes long fit in one skbuff and use one DMA descriptor. */
-
-  first_desc = last_desc = ring->read;
-
-  /* ASSERTION: If there is a descriptor in the ring and the hardware has */
-  /*  finished with it, then that descriptor will have RX_FIRST_DESC set. */
-  if ((ring->read != ring->write) && /* descriptor ring not empty */
-     ((ring->read->status & TLP_DSTS_OWNER) == 0) && /* hardware done */
-     ((ring->read->status & TLP_DSTS_RX_FIRST_DESC) == 0)) /* should be set */
-    panic("%s: rxintr_cleanup: rx-first-descriptor not set.\n", NAME_UNIT);
-
-  /* First decide if a complete packet has arrived. */
-  /* Run down DMA descriptors looking for one marked "last". */
-  /* Bail out if an active descriptor is encountered. */
-  /* Accumulate most significant bits of packet length. */
-  pkt_len = 0;
-  for (;;)
-    {
-    if (last_desc == ring->write) return 0;  /* no more descs */
-    if (last_desc->status & TLP_DSTS_OWNER) return 0; /* still active */
-    if (last_desc->status & TLP_DSTS_RX_LAST_DESC) break; /* end of packet */
-    pkt_len += last_desc->length1 + last_desc->length2; /* entire desc filled */
-    if (last_desc++->control & TLP_DCTL_END_RING) last_desc = ring->first; /* ring wrap */
-    }
-
-  /* A complete packet has arrived; how long is it? */
-  /* H/w ref man shows RX pkt length as a 14-bit field. */
-  /* An experiment found that only the 12 LSBs work. */
-  if (((last_desc->status>>16)&0xFFF) == 0) pkt_len += 4096; /* carry-bit */
-  pkt_len = (pkt_len & 0xF000) + ((last_desc->status>>16) & 0x0FFF);
-  /* Subtract the CRC length unless doing so would underflow. */
-  if (pkt_len >= sc->config.crc_len) pkt_len -= sc->config.crc_len;
-
-  /* Run down DMA descriptors again doing the following:
-   *  1) put pkt info in hdr of first skbuff.
-   *  2) put additional skbuffs on frag_list.
-   *  3) set skbuff lengths.
-   */
-  first_desc = ring->read;
-  do
+  /* 3) Errata memo from Digital Equipment Corp warns that 21140A */
+  /* receivers through rev 2.2 can hang if the fifo overruns. */
+  /* Recommended fix: stop and start the RX FSM after an overrun. */
+  missed = READ_CSR(TLP_MISSED);
+  if ((overruns = ((missed & TLP_MISS_OVERRUN)>>TLP_OVERRUN_SHIFT)) != 0)
     {
-    /* Read a DMA descriptor from the ring. */
-    last_desc = ring->read;
-    /* Advance the ring read pointer. */
-    if (ring->read++ == ring->last) ring->read = ring->first;
-
-    /* Dequeue the corresponding skbuff. */
-    new_skb = skbuff_dequeue(ring);
-    if (new_skb == NULL)
-      panic("%s: rxintr_cleanup: expected an skbuff\n", NAME_UNIT);
-
-    desc_len = last_desc->length1 + last_desc->length2;
-    /* Unmap kernel virtual addresss to PCI address. */
-    pci_unmap_single(sc->pci_dev, last_desc->address1,
-     desc_len, PCI_DMA_FROMDEVICE);
-
-    /* Set skbuff length. */
-    skb_put(new_skb, (pkt_len >= desc_len) ? desc_len : pkt_len);
-    pkt_len -= new_skb->len;
-
-    /* 1) Put pkt info in hdr of first skbuff. */
-    if (last_desc == first_desc)
+    if (DRIVER_DEBUG)
+      printf("%s: rx overrun cntr=%d\n", NAME_UNIT, overruns);
+    sc->status.cntrs.overruns += overruns;
+    if ((READ_PCI_CFG(sc, TLP_CFRV) & 0xFF) <= 0x22)
       {
-      first_skb = new_skb;
-      if (sc->config.line_pkg == PKG_RAWIP)
-        {
-        if      (first_skb->data[0]>>4 == 4)
-          first_skb->protocol = htons(ETH_P_IP);
-        else if (first_skb->data[0]>>4 == 6)
-          first_skb->protocol = htons(ETH_P_IPV6);
-	}
-      else
-#if GEN_HDLC
-        first_skb->protocol = hdlc_type_trans(first_skb, sc->net_dev);
-#else
-        first_skb->protocol = htons(ETH_P_HDLC);
-#endif
-      first_skb->mac.raw = first_skb->data;
-      first_skb->dev = sc->net_dev;
-      do_gettimeofday(&first_skb->stamp);
-      sc->net_dev->last_rx = jiffies;
-      }
-    else /* 2) link skbuffs. */
-      {
-      /* Put this skbuff on the frag_list of the first skbuff. */
-      new_skb->next = NULL;
-      if (skb_shinfo(first_skb)->frag_list == NULL)
-        skb_shinfo(first_skb)->frag_list = new_skb;
-      else
-        last_skb->next = new_skb;
-      /* 3) set skbuff lengths. */
-      first_skb->len      += new_skb->len;
-      first_skb->data_len += new_skb->len;
+      op_mode = READ_CSR(TLP_OP_MODE);
+      WRITE_CSR(TLP_OP_MODE, op_mode & ~TLP_OP_RX_RUN);
+      /* Wait for the RX FSM to stop; it might be processing a pkt. */
+      while (READ_CSR(TLP_STATUS) & TLP_STAT_RX_FSM); /* XXX HANG */
+      WRITE_CSR(TLP_OP_MODE, op_mode);  /* restart rx */
       }
-    last_skb = new_skb;
-    } while ((last_desc->status & TLP_DSTS_RX_LAST_DESC) == 0);
-
-  /* Decide whether to accept or to discard this packet. */
-  /* RxHDLC sets MIIERR for bad CRC, abort and partial byte at pkt end. */
-  if (((last_desc->status & TLP_DSTS_RX_BAD) == 0) &&
-   (sc->status.oper_status == STATUS_UP) &&
-   (first_skb->len > 0))
-    {
-    /* Optimization: copy a small pkt into a small skbuff. */
-    if (first_skb->len <= COPY_BREAK)
-      if ((new_skb = skb_copy(first_skb, GFP_ATOMIC)) != NULL)
-        {
-        dev_kfree_skb_any(first_skb);
-        first_skb = new_skb;
-	}
-
-    /* Include CRC and one flag byte in input byte count. */
-    sc->status.cntrs.ibytes += first_skb->len + sc->config.crc_len +1;
-    sc->status.cntrs.ipackets++;
-
-    /* Give this good packet to the network stacks. */
-    netif_receive_skb(first_skb);  /* NAPI */
-    sc->quota--;
-    }
-  else if (sc->status.oper_status != STATUS_UP)
-    {
-    /* If the link is down, this packet is probably noise. */
-    sc->status.cntrs.idiscards++;
-    dev_kfree_skb_any(first_skb);
-    if (DRIVER_DEBUG)
-      printk("%s: rxintr_cleanup: rx pkt discarded: link down\n", NAME_UNIT);
     }
-  else /* Log and discard this bad packet. */
+
+  /* 4) When the receiver is enabled and a packet arrives, but no DMA */
+  /*  descriptor is available, the packet is counted as 'missed'. */
+  /* The receiver should never miss packets; warn if it happens. */
+  if ((missed = (missed & TLP_MISS_MISSED)) != 0)
     {
     if (DRIVER_DEBUG)
-      printk("%s: RX bad pkt; len=%d %s%s%s%s\n",
-       NAME_UNIT, first_skb->len,
-       (last_desc->status & TLP_DSTS_RX_MII_ERR)  ? " miierr"  : "",
-       (last_desc->status & TLP_DSTS_RX_DRIBBLE)  ? " dribble" : "",
-       (last_desc->status & TLP_DSTS_RX_DESC_ERR) ? " descerr" : "",
-       (last_desc->status & TLP_DSTS_RX_OVERRUN)  ? " overrun" : "");
-    if (last_desc->status & TLP_DSTS_RX_OVERRUN)
-      sc->status.cntrs.fifo_over++;
-    else
-      sc->status.cntrs.ierrors++;
-    dev_kfree_skb_any(first_skb);
+      printf("%s: rx missed %d pkts\n", NAME_UNIT, missed);
+    sc->status.cntrs.missed += missed;
     }
-
-  return 1; /* did something */
   }
 
-/* Setup (prepare) to receive a packet. */
-/* Try to keep the RX descriptor ring full of empty buffers. */
-static int  /* Linux version */
-rxintr_setup(softc_t *sc)
+static void /* This is where the work gets done. */
+core_interrupt(void *arg, int check_status)
   {
-  struct desc_ring *ring = &sc->rxring;
-  struct dma_desc *desc;
-  struct sk_buff *skb;
-  u_int32_t dma_addr;
-
-  /* Ring is full if (wrap(write+1)==read) */
-  if (((ring->write == ring->last) ? ring->first : ring->write+1) == ring->read)
-    return 0;  /* ring is full; nothing to do */
+  softc_t *sc = arg;
+  int activity;
 
-  /* Allocate an skbuff. */
-  if ((skb = dev_alloc_skb(MAX_DESC_LEN)) == NULL)
+  /* If any CPU is inside this critical section, then */
+  /* other CPUs should go away without doing anything. */
+  if (BOTTOM_TRYLOCK == 0)
     {
-    sc->status.cntrs.rxdma++;
-    if (DRIVER_DEBUG)
-      printk("%s: rxintr_setup: dev_alloc_skb() failed\n", NAME_UNIT);
-    return 0;
+    sc->status.cntrs.lck_intr++;
+    return;
     }
-  skb->dev = sc->net_dev;
 
-  /* Queue the skbuff for later processing by rxintr_cleanup. */
-  skbuff_enqueue(ring, skb);
-
-  /* Write a DMA descriptor into the ring. */
-  /* Hardware won't see it until the OWNER bit is set. */
-  desc = ring->write;
-  /* Advance the ring write pointer. */
-  if (ring->write++ == ring->last) ring->write = ring->first;
+  /* Clear pending card interrupts. */
+  WRITE_CSR(TLP_STATUS, READ_CSR(TLP_STATUS));
 
-  /* Map kernel virtual addresses to PCI addresses. */
-  dma_addr = pci_map_single(sc->pci_dev, skb->data,
-   MAX_DESC_LEN, PCI_DMA_FROMDEVICE);
-  /* Set up the DMA descriptor. */
-  desc->address1 = dma_addr;
-  desc->length1  = MAX_CHUNK_LEN;
-  desc->address2 = desc->address1 + desc->length1;
-  desc->length2  = MAX_CHUNK_LEN;
+  /* In Linux, pci_alloc_consistent() means DMA descriptors */
+  /*  don't need explicit syncing. */
+  {
+  struct desc_ring *ring = &sc->txring;
+  DMA_SYNC(sc->txring.map, sc->txring.size_descs,
+   BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+  ring = &sc->rxring;
+  DMA_SYNC(sc->rxring.map, sc->rxring.size_descs,
+   BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+  }
 
-  /* Before setting the OWNER bit, flush the cache (memory barrier). */
-  wmb(); /* write memory barrier */
+  do  /* This is the main loop for interrupt processing. */
+    {
+    activity  = txintr_cleanup(sc);
+    activity += txintr_setup(sc);
+    activity += rxintr_cleanup(sc);
+    activity += rxintr_setup(sc);
+    } while (activity);
 
-  /* Commit the DMA descriptor to the hardware. */
-  desc->status = TLP_DSTS_OWNER;
+  {
+  struct desc_ring *ring = &sc->txring;
+  DMA_SYNC(sc->txring.map, sc->txring.size_descs,
+   BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+  ring = &sc->rxring;
+  DMA_SYNC(sc->rxring.map, sc->rxring.size_descs,
+   BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+  }
 
-  /* Notify the receiver that there is another buffer available. */
-  WRITE_CSR(TLP_RX_POLL, 1);
+  /* As the interrupt is dismissed, check for four unusual events. */
+  if (check_status) check_intr_status(sc);
 
-  return 1; /* did something */
+  BOTTOM_UNLOCK;
   }
 
-/* Clean up after a packet has been transmitted. */
-/* Free the sk_buff and update the DMA descriptor ring. */
-static int  /* Linux version */
-txintr_cleanup(softc_t *sc)
+/* user_interrupt() may be called from a syscall or a softirq */
+static void
+user_interrupt(softc_t *sc, int check_status)
   {
-  struct desc_ring *ring = &sc->txring;
-  struct dma_desc *desc;
-
-  while ((ring->read != ring->write) && /* ring is not empty */
-        ((ring->read->status & TLP_DSTS_OWNER) == 0))
-    {
-    /* Read a DMA descriptor from the ring. */
-    desc = ring->read;
-    /* Advance the ring read pointer. */
-    if (ring->read++ == ring->last) ring->read = ring->first;
-    /* Unmap kernel virtual address to PCI address. */
-    pci_unmap_single(sc->pci_dev, desc->address1,
-     desc->length1 + desc->length2, PCI_DMA_TODEVICE);
+  DISABLE_INTR; /* noop on FreeBSD-5 and Linux */
+  core_interrupt(sc, check_status);
+  ENABLE_INTR;  /* noop on FreeBSD-5 and Linux */
+  }
 
-    /* If this descriptor is the last segment of a packet, */
-    /*  then dequeue and free the corresponding skbuff. */
-    if ((desc->control & TLP_DCTL_TX_LAST_SEG) != 0)
-      {
-      struct sk_buff *skb;
-      if ((skb = skbuff_dequeue(ring)) == NULL)
-        panic("%s: txintr_cleanup: expected an sk_buff\n", NAME_UNIT);
 
-      /* Include CRC and one flag byte in output byte count. */
-      sc->status.cntrs.obytes += skb->len + sc->config.crc_len +1;
-      sc->status.cntrs.opackets++;
+# if defined(DEVICE_POLLING)
 
-      /* The only bad TX status is fifo underrun. */
-      if ((desc->status & TLP_DSTS_TX_UNDERRUN) != 0)
-        {
-        sc->status.cntrs.fifo_under++; /* also increment oerrors? */
-        if (DRIVER_DEBUG)
-          printk("%s: txintr_cleanup: tx fifo underrun\n", NAME_UNIT);
-	}
+/* Service the card from the kernel idle loop without interrupts. */
+static int

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list