summaryrefslogtreecommitdiffstats
path: root/sys/dev/ar
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>1999-10-21 09:06:11 +0000
committerjulian <julian@FreeBSD.org>1999-10-21 09:06:11 +0000
commitc5c63975d538cf48ceb99ba48c341293676d15c0 (patch)
tree722c03ee4d750dd89ed43b028c35302fbfd03bfd /sys/dev/ar
parent028ec91c46f181b4be2318c3bba8d194b5583f87 (diff)
downloadFreeBSD-src-c5c63975d538cf48ceb99ba48c341293676d15c0.zip
FreeBSD-src-c5c63975d538cf48ceb99ba48c341293676d15c0.tar.gz
Whistle's Netgraph link-layer (sometimes more) networking infrastructure.
Been in production for 3 years now. Gives Instant Frame relay to if_sr and if_ar drivers, and PPPOE support soon. See: ftp://ftp.whistle.com/pub/archie/netgraph/index.html for on-line manual pages. Reviewed by: Doug Rabson (dfr@freebsd.org) Obtained from: Whistle CVS tree
Diffstat (limited to 'sys/dev/ar')
-rw-r--r--sys/dev/ar/if_ar.c538
-rw-r--r--sys/dev/ar/if_ar.h23
-rw-r--r--sys/dev/ar/if_ar_isa.c538
3 files changed, 1081 insertions, 18 deletions
diff --git a/sys/dev/ar/if_ar.c b/sys/dev/ar/if_ar.c
index 3e78c79..0eec2cf 100644
--- a/sys/dev/ar/if_ar.c
+++ b/sys/dev/ar/if_ar.c
@@ -45,6 +45,7 @@
*
*/
+#include "opt_netgraph.h"
#include "ar.h"
#include <sys/param.h>
@@ -55,9 +56,16 @@
#include <sys/socket.h>
#include <net/if.h>
+#ifdef NETGRAPH
+#include <netgraph/ng_message.h>
+#include <netgraph/netgraph.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <i386/isa/if_ar.h>
+#else /* NETGRAPH */
#include <net/if_sppp.h>
-
#include <net/bpf.h>
+#endif /* NETGRAPH */
#include <machine/clock.h>
#include <machine/md_var.h>
@@ -66,10 +74,12 @@
#include <i386/isa/ic/hd64570.h>
#include <i386/isa/isa_device.h>
+#ifndef NETGRAPH
#include "sppp.h"
#if NSPPP <= 0
#error device 'ar' require sppp.
-#endif
+#endif /* NSPPP <= 0 */
+#endif /* NETGRAPH */
#ifdef TRACE
#define TRC(x) x
@@ -118,7 +128,9 @@ static int next_ar_unit = 0;
static struct ar_hardc ar_hardc[NAR];
struct ar_softc {
+#ifndef NETGRAPH
struct sppp ifsppp;
+#endif /* NETGRAPH */
int unit; /* With regards to all ar devices */
int subunit; /* With regards to this card */
struct ar_hardc *hc;
@@ -146,8 +158,38 @@ struct ar_softc {
int scano;
int scachan;
sca_regs *sca;
+#ifdef NETGRAPH
+ int running; /* something is attached so we are running */
+ int dcd; /* do we have dcd? */
+ /* ---netgraph bits --- */
+ char nodename[NG_NODELEN + 1]; /* store our node name */
+ int datahooks; /* number of data hooks attached */
+ node_p node; /* netgraph node */
+ hook_p hook; /* data hook */
+ hook_p debug_hook;
+ struct ifqueue xmitq_hipri; /* hi-priority transmit queue */
+ struct ifqueue xmitq; /* transmit queue */
+ int flags; /* state */
+#define SCF_RUNNING 0x01 /* board is active */
+#define SCF_OACTIVE 0x02 /* output is active */
+ int out_dog; /* watchdog cycles output count-down */
+ struct callout_handle handle; /* timeout(9) handle */
+ u_long inbytes, outbytes; /* stats */
+ u_long lastinbytes, lastoutbytes; /* a second ago */
+ u_long inrate, outrate; /* highest rate seen */
+ u_long inlast; /* last input N secs ago */
+ u_long out_deficit; /* output since last input */
+ u_long oerrors, ierrors[6];
+ u_long opackets, ipackets;
+#endif /* NETGRAPH */
};
+#ifdef NETGRAPH
+#define DOG_HOLDOFF 6 /* dog holds off for 6 secs */
+#define QUITE_A_WHILE 300 /* 5 MINUTES */
+#define LOTS_OF_PACKETS 100
+#endif /* NETGRAPH */
+
static int arprobe(struct isa_device *id);
static int arattach_isa(struct isa_device *id);
@@ -184,9 +226,14 @@ void arintr_hc(struct ar_hardc *hc);
static ointhand2_t arintr;
static int arattach(struct ar_hardc *hc);
static void ar_xmit(struct ar_softc *sc);
+#ifndef NETGRAPH
static void arstart(struct ifnet *ifp);
static int arioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
static void arwatchdog(struct ifnet *ifp);
+#else /* NETGRAPH */
+static void arstart(struct ar_softc *sc);
+static void arwatchdog(struct ar_softc *sc);
+#endif /* NETGRAPH */
static int ar_packet_avail(struct ar_softc *sc, int *len, u_char *rxstat);
static void ar_copy_rxbuf(struct mbuf *m, struct ar_softc *sc, int len);
static void ar_eat_packet(struct ar_softc *sc, int single);
@@ -204,6 +251,37 @@ static void ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr);
static void ar_msci_intr(struct ar_hardc *hc, int scano, u_char isr);
static void ar_timer_intr(struct ar_hardc *hc, int scano, u_char isr);
+#ifdef NETGRAPH
+static void ngar_watchdog_frame(void * arg);
+static void ngar_init(void* ignored);
+static int ngar_constructor(node_p *nodep);
+static int ngar_rcvmsg(node_p node, struct ng_mesg *msg,
+ const char *retaddr, struct ng_mesg **resp);
+static int ngar_rmnode(node_p node);
+static int ngar_newhook(node_p node, hook_p hook, const char *name);
+/*static hook_p ngar_findhook(node_p node, char *name);*/
+static int ngar_connect(hook_p hook); /* already PARTLY linked */
+static int ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta);
+static int ngar_disconnect(hook_p hook); /* notify on disconnect */
+
+static struct ng_type typestruct = {
+ NG_VERSION,
+ NG_AR_NODE_TYPE,
+ NULL,
+ ngar_constructor,
+ ngar_rcvmsg,
+ ngar_rmnode,
+ ngar_newhook,
+ NULL,
+ ngar_connect,
+ ngar_rcvdata,
+ ngar_rcvdata,
+ ngar_disconnect
+};
+
+static int ngar_done_init = 0;
+#endif /* NETGRAPH */
+
/*
* Register the Adapter.
* Probe to see if it is there.
@@ -348,7 +426,9 @@ static int
arattach(struct ar_hardc *hc)
{
struct ar_softc *sc;
+#ifndef NETGRAPH
struct ifnet *ifp;
+#endif /* NETGRAPH */
int unit;
char *iface;
@@ -380,6 +460,7 @@ arattach(struct ar_hardc *hc)
ar_init_tx_dmac(sc);
ar_init_msci(sc);
+#ifndef NETGRAPH
ifp = &sc->ifsppp.pp_if;
ifp->if_softc = sc;
@@ -412,6 +493,25 @@ arattach(struct ar_hardc *hc)
if_attach(ifp);
bpfattach(ifp, DLT_PPP, PPP_HEADER_LEN);
+#else /* NETGRAPH */
+ /*
+ * we have found a node, make sure our 'type' is availabe.
+ */
+ if (ngar_done_init == 0) ngar_init(NULL);
+ if (ng_make_node_common(&typestruct, &sc->node) != 0)
+ return (0);
+ sc->node->private = sc;
+ callout_handle_init(&sc->handle);
+ sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
+ sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
+ sprintf(sc->nodename, "%s%d", NG_AR_NODE_TYPE, sc->unit);
+ if (ng_name_node(sc->node, sc->nodename)) {
+ ng_rmnode(sc->node);
+ ng_unref(sc->node);
+ return (0);
+ }
+ sc->running = 0;
+#endif /* NETGRAPH */
}
if(hc->bustype == AR_BUS_ISA)
@@ -511,10 +611,14 @@ arintr_hc(struct ar_hardc *hc)
static void
ar_xmit(struct ar_softc *sc)
{
+#ifndef NETGRAPH
struct ifnet *ifp;
+#endif /* NETGRAPH */
dmac_channel *dmac;
+#ifndef NETGRAPH
ifp = &sc->ifsppp.pp_if;
+#endif /* NETGRAPH */
dmac = &sc->sca->dmac[DMAC_TXCH(sc->scachan)];
if(sc->hc->bustype == AR_BUS_ISA)
@@ -530,7 +634,11 @@ ar_xmit(struct ar_softc *sc)
if(sc->txb_next_tx == AR_TX_BLOCKS)
sc->txb_next_tx = 0;
+#ifndef NETGRAPH
ifp->if_timer = 2; /* Value in seconds. */
+#else /* NETGRAPH */
+ sc->out_dog = DOG_HOLDOFF; /* give ourself some breathing space*/
+#endif /* NETGRAPH */
if(sc->hc->bustype == AR_BUS_ISA)
ARC_SET_OFF(sc->hc->iobase);
}
@@ -549,30 +657,51 @@ ar_xmit(struct ar_softc *sc)
* that clears that should ensure that the transmitter and its DMA is
* in a "good" idle state.
*/
+#ifndef NETGRAPH
static void
arstart(struct ifnet *ifp)
{
struct ar_softc *sc = ifp->if_softc;
+#else /* NETGRAPH */
+static void
+arstart(struct ar_softc *sc)
+{
+#endif /* NETGRAPH */
int i, len, tlen;
struct mbuf *mtx;
u_char *txdata;
sca_descriptor *txdesc;
struct buf_block *blkp;
+#ifndef NETGRAPH
if(!(ifp->if_flags & IFF_RUNNING))
return;
+#else /* NETGRAPH */
+/* XXX */
+#endif /* NETGRAPH */
top_arstart:
/*
* See if we have space for more packets.
*/
+#ifndef NETGRAPH
if(sc->txb_inuse == AR_TX_BLOCKS) {
- ifp->if_flags |= IFF_OACTIVE;
+ ifp->if_flags |= IFF_OACTIVE; /* yes, mark active */
+#else /* NETGRAPH */
+/*XXX*/ /*ifp->if_flags |= IFF_OACTIVE;*/ /* yes, mark active */
+#endif /* NETGRAPH */
return;
}
+#ifndef NETGRAPH
mtx = sppp_dequeue(ifp);
+#else /* NETGRAPH */
+ IF_DEQUEUE(&sc->xmitq_hipri, mtx);
+ if (mtx == NULL) {
+ IF_DEQUEUE(&sc->xmitq, mtx);
+ }
+#endif /* NETGRAPH */
if(!mtx)
return;
@@ -618,10 +747,16 @@ top_arstart:
txdata += AR_BUF_SIZ;
i++;
+#ifndef NETGRAPH
if(ifp->if_bpf)
bpf_mtap(ifp, mtx);
m_freem(mtx);
++sc->ifsppp.pp_if.if_opackets;
+#else /* NETGRAPH */
+ m_freem(mtx);
+ sc->outbytes += len;
+ ++sc->opackets;
+#endif /* NETGRAPH */
/*
* Check if we have space for another mbuf.
@@ -631,7 +766,14 @@ top_arstart:
if((i + 3) >= blkp->txmax)
break;
+#ifndef NETGRAPH
mtx = sppp_dequeue(ifp);
+#else /* NETGRAPH */
+ IF_DEQUEUE(&sc->xmitq_hipri, mtx);
+ if (mtx == NULL) {
+ IF_DEQUEUE(&sc->xmitq, mtx);
+ }
+#endif /* NETGRAPH */
if(!mtx)
break;
}
@@ -670,6 +812,7 @@ top_arstart:
goto top_arstart;
}
+#ifndef NETGRAPH
static int
arioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
@@ -711,18 +854,26 @@ arioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
splx(s);
return 0;
}
+#endif /* NETGRAPH */
/*
* This is to catch lost tx interrupts.
*/
static void
+#ifndef NETGRAPH
arwatchdog(struct ifnet *ifp)
{
struct ar_softc *sc = ifp->if_softc;
+#else /* NETGRAPH */
+arwatchdog(struct ar_softc *sc)
+{
+#endif /* NETGRAPH */
msci_channel *msci = &sc->sca->msci[sc->scachan];
+#ifndef NETGRAPH
if(!(ifp->if_flags & IFF_RUNNING))
return;
+#endif /* NETGRAPH */
if(sc->hc->bustype == AR_BUS_ISA)
ARC_SET_SCA(sc->hc->iobase, sc->scano);
@@ -730,7 +881,7 @@ arwatchdog(struct ifnet *ifp)
/* XXX if(sc->ifsppp.pp_if.if_flags & IFF_DEBUG) */
printf("ar%d: transmit failed, "
"ST0 %x, ST1 %x, ST3 %x, DSR %x.\n",
- ifp->if_unit,
+ sc->unit,
msci->st0,
msci->st1,
msci->st3,
@@ -743,12 +894,20 @@ arwatchdog(struct ifnet *ifp)
}
sc->xmit_busy = 0;
+#ifndef NETGRAPH
ifp->if_flags &= ~IFF_OACTIVE;
+#else /* NETGRAPH */
+ /* XXX ifp->if_flags &= ~IFF_OACTIVE; */
+#endif /* NETGRAPH */
if(sc->txb_inuse && --sc->txb_inuse)
ar_xmit(sc);
+#ifndef NETGRAPH
arstart(ifp);
+#else /* NETGRAPH */
+ arstart(sc);
+#endif /* NETGRAPH */
}
static void
@@ -803,6 +962,11 @@ ar_up(struct ar_softc *sc)
if(sc->hc->bustype == AR_BUS_ISA)
ARC_SET_OFF(sc->hc->iobase);
+#ifdef NETGRAPH
+ untimeout(ngar_watchdog_frame, sc, sc->handle);
+ sc->handle = timeout(ngar_watchdog_frame, sc, hz);
+ sc->running = 1;
+#endif /* NETGRAPH */
}
static void
@@ -814,6 +978,10 @@ ar_down(struct ar_softc *sc)
sca = sc->sca;
msci = &sca->msci[sc->scachan];
+#ifdef NETGRAPH
+ untimeout(ngar_watchdog_frame, sc, sc->handle);
+ sc->running = 0;
+#endif /* NETGRAPH */
/*
* Disable transmitter and receiver.
* Lower DTR and RTS.
@@ -958,9 +1126,12 @@ arc_init(struct ar_hardc *hc)
u_int descneeded;
u_char isr, mar;
- sc = hc->sc = malloc(hc->numports * sizeof(struct ar_softc),
- M_DEVBUF, M_WAITOK);
+ MALLOC(sc, struct ar_softc *,
+ hc->numports * sizeof(struct ar_softc), M_DEVBUF, M_WAITOK);
+ if (sc == NULL)
+ return (ENOMEM);
bzero(sc, hc->numports * sizeof(struct ar_softc));
+ hc->sc = sc;
hc->txc_dtr[0] = AR_TXC_DTR_NOTRESET |
AR_TXC_DTR_DTR0 | AR_TXC_DTR_DTR1;
@@ -1088,7 +1259,6 @@ arc_init(struct ar_hardc *hc)
if(hc->bustype == AR_BUS_PCI)
hc->orbase[AR_PIMCTRL] = AR_PIM_MODEG | AR_PIM_AUTO_LED;
-
}
@@ -1105,7 +1275,6 @@ ar_init_sca(struct ar_hardc *hc, int scano)
sca_regs *sca;
sca = hc->sca[scano];
-
if(hc->bustype == AR_BUS_ISA)
ARC_SET_SCA(hc->iobase, scano);
@@ -1562,7 +1731,13 @@ ar_get_packets(struct ar_softc *sc)
ar_eat_packet(sc, 1);
continue;
}
+#ifndef NETGRAPH
m->m_pkthdr.rcvif = &sc->ifsppp.pp_if;
+#else /* NETGRAPH */
+ m->m_pkthdr.rcvif = NULL;
+ sc->inbytes += len;
+ sc->inlast = 0;
+#endif /* NETGRAPH */
m->m_pkthdr.len = m->m_len = len;
if(len > MHLEN) {
MCLGET(m, M_DONTWAIT);
@@ -1573,10 +1748,15 @@ ar_get_packets(struct ar_softc *sc)
}
}
ar_copy_rxbuf(m, sc, len);
+#ifndef NETGRAPH
if(sc->ifsppp.pp_if.if_bpf)
bpf_mtap(&sc->ifsppp.pp_if, m);
sppp_input(&sc->ifsppp.pp_if, m);
sc->ifsppp.pp_if.if_ipackets++;
+#else /* NETGRAPH */
+ ng_queue_data(sc->hook, m, NULL);
+ sc->ipackets++;
+#endif /* NETGRAPH */
/*
* Update the eda to the previous descriptor.
@@ -1609,7 +1789,11 @@ ar_get_packets(struct ar_softc *sc)
ar_eat_packet(sc, 1);
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_ierrors++;
+#else /* NETGRAPH */
+ sc->ierrors[0]++;
+#endif /* NETGRAPH */
if(sc->hc->bustype == AR_BUS_ISA)
ARC_SET_SCA(sc->hc->iobase, sc->scano);
@@ -1678,8 +1862,13 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
printf("ar%d: TX DMA Counter overflow, "
"txpacket no %lu.\n",
sc->unit,
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_opackets);
sc->ifsppp.pp_if.if_oerrors++;
+#else /* NETGRAPH */
+ sc->opackets);
+ sc->oerrors++;
+#endif /* NETGRAPH */
}
/* Buffer overflow */
@@ -1688,11 +1877,19 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
"txpacket no %lu, dsr %02x, "
"cda %04x, eda %04x.\n",
sc->unit,
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_opackets,
+#else /* NETGRAPH */
+ sc->opackets,
+#endif /* NETGRAPH */
dsr,
dmac->cda,
dmac->eda);
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_oerrors++;
+#else /* NETGRAPH */
+ sc->oerrors++;
+#endif /* NETGRAPH */
}
/* End of Transfer */
@@ -1706,8 +1903,13 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
* there is data to transmit.
*/
sc->xmit_busy = 0;
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_flags &= ~IFF_OACTIVE;
sc->ifsppp.pp_if.if_timer = 0;
+#else /* NETGRAPH */
+ /* XXX c->ifsppp.pp_if.if_flags &= ~IFF_OACTIVE; */
+ sc->out_dog = 0; /* XXX */
+#endif /* NETGRAPH */
if(sc->txb_inuse && --sc->txb_inuse)
ar_xmit(sc);
@@ -1735,7 +1937,11 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
ar_get_packets(sc);
TRC(
+#ifndef NETGRAPH
if(tt == sc->ifsppp.pp_if.if_ipackets) {
+#else /* NETGRAPH */
+ if(tt == sc->ipackets) {
+#endif /* NETGRAPH */
sca_descriptor *rxdesc;
int i;
@@ -1779,8 +1985,13 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
printf("ar%d: RX DMA Counter overflow, "
"rxpkts %lu.\n",
sc->unit,
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_ipackets);
sc->ifsppp.pp_if.if_ierrors++;
+#else /* NETGRAPH */
+ sc->ipackets);
+ sc->ierrors[1]++;
+#endif /* NETGRAPH */
}
/* Buffer overflow */
@@ -1791,7 +2002,11 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
"rxpkts %lu, rxind %d, "
"cda %x, eda %x, dsr %x.\n",
sc->unit,
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_ipackets,
+#else /* NETGRAPH */
+ sc->ipackets,
+#endif /* NETGRAPH */
sc->rxhind,
dmac->cda,
dmac->eda,
@@ -1801,7 +2016,11 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
* Then get the system running again.
*/
ar_eat_packet(sc, 0);
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_ierrors++;
+#else /* NETGRAPH */
+ sc->ierrors[2]++;
+#endif /* NETGRAPH */
if(hc->bustype == AR_BUS_ISA)
ARC_SET_SCA(hc->iobase, scano);
sca->msci[mch].cmd = SCA_CMD_RXMSGREJ;
@@ -1829,8 +2048,13 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
*/
printf("ar%d: RX End of transfer, rxpkts %lu.\n",
sc->unit,
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_ipackets);
sc->ifsppp.pp_if.if_ierrors++;
+#else /* NETGRAPH */
+ sc->ipackets);
+ sc->ierrors[3]++;
+#endif /* NETGRAPH */
}
}
@@ -1846,7 +2070,11 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
for(mch = 0; mch < NCHAN; mch++) {
if(dotxstart & 0x0C) {
sc = &hc->sc[mch + (NCHAN * scano)];
+#ifndef NETGRAPH
arstart(&sc->ifsppp.pp_if);
+#else /* NETGRAPH */
+ arstart(sc);
+#endif /* NETGRAPH */
}
dotxstart >>= 4;
}
@@ -1864,7 +2092,299 @@ ar_timer_intr(struct ar_hardc *hc, int scano, u_char isr2)
printf("arc%d: ARINTR: TIMER\n", hc->cunit);
}
+
+#ifdef NETGRAPH
+/*****************************************
+ * Device timeout/watchdog routine.
+ * called once per second.
+ * checks to see that if activity was expected, that it hapenned.
+ * At present we only look to see if expected output was completed.
+ */
+static void
+ngar_watchdog_frame(void * arg)
+{
+ struct ar_softc * sc = arg;
+ int s;
+ int speed;
+
+ if(sc->running == 0)
+ return; /* if we are not running let timeouts die */
+ /*
+ * calculate the apparent throughputs
+ * XXX a real hack
+ */
+ s = splimp();
+ speed = sc->inbytes - sc->lastinbytes;
+ sc->lastinbytes = sc->inbytes;
+ if ( sc->inrate < speed )
+ sc->inrate = speed;
+ speed = sc->outbytes - sc->lastoutbytes;
+ sc->lastoutbytes = sc->outbytes;
+ if ( sc->outrate < speed )
+ sc->outrate = speed;
+ sc->inlast++;
+ splx(s);
+
+ if ((sc->inlast > QUITE_A_WHILE)
+ && (sc->out_deficit > LOTS_OF_PACKETS)) {
+ log(LOG_ERR, "ar%d: No response from remote end\n", sc->unit);
+ s = splimp();
+ ar_down(sc);
+ ar_up(sc);
+ sc->inlast = sc->out_deficit = 0;
+ splx(s);
+ } else if ( sc->xmit_busy ) { /* no TX -> no TX timeouts */
+ if (sc->out_dog == 0) {
+ log(LOG_ERR, "ar%d: Transmit failure.. no clock?\n",
+ sc->unit);
+ arwatchdog(sc);
+#if 0
+ s = splimp();
+ ar_down(sc);
+ ar_up(sc);
+ splx(s);
+#endif
+ sc->inlast = sc->out_deficit = 0;
+ } else {
+ sc->out_dog--;
+ }
+ }
+ sc->handle = timeout(ngar_watchdog_frame, sc, hz);
+}
+
+/***********************************************************************
+ * This section contains the methods for the Netgraph interface
+ ***********************************************************************/
/*
- ********************************* END ************************************
+ * It is not possible or allowable to create a node of this type.
+ * If the hardware exists, it will already have created it.
+ */
+static int
+ngar_constructor(node_p *nodep)
+{
+ return (EINVAL);
+}
+
+/*
+ * give our ok for a hook to be added...
+ * If we are not running this should kick the device into life.
+ * We allow hooks called "control" and dlci[1-1023]
+ * The hook's private info points to our stash of info about that
+ * channel.
+ */
+static int
+ngar_newhook(node_p node, hook_p hook, const char *name)
+{
+ struct ar_softc * sc = node->private;
+
+ /*
+ * check if it's our friend the debug hook
+ */
+ if (strcmp(name, NG_AR_HOOK_DEBUG) == 0) {
+ hook->private = NULL; /* paranoid */
+ sc->debug_hook = hook;
+ return (0);
+ }
+
+ /*
+ * Check for raw mode hook.
+ */
+ if (strcmp(name, NG_AR_HOOK_RAW) != 0) {
+ return (EINVAL);
+ }
+ hook->private = sc;
+ sc->hook = hook;
+ sc->datahooks++;
+ ar_up(sc);
+ return (0);
+}
+
+/*
+ * incoming messages.
+ * Just respond to the generic TEXT_STATUS message
*/
+static int
+ngar_rcvmsg(node_p node,
+ struct ng_mesg *msg, const char *retaddr, struct ng_mesg **resp)
+{
+ struct ar_softc * sc;
+ int error = 0;
+
+ sc = node->private;
+ switch (msg->header.typecookie) {
+ case NG_AR_COOKIE:
+ error = EINVAL;
+ break;
+ case NGM_GENERIC_COOKIE:
+ switch(msg->header.cmd) {
+ case NGM_TEXT_STATUS: {
+ char *arg;
+ int pos = 0;
+ int resplen = sizeof(struct ng_mesg) + 512;
+ MALLOC(*resp, struct ng_mesg *, resplen,
+ M_NETGRAPH, M_NOWAIT);
+ if (*resp == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ bzero(*resp, resplen);
+ arg = (*resp)->data;
+
+ /*
+ * Put in the throughput information.
+ */
+ pos = sprintf(arg, "%ld bytes in, %ld bytes out\n"
+ "highest rate seen: %ld B/S in, %ld B/S out\n",
+ sc->inbytes, sc->outbytes,
+ sc->inrate, sc->outrate);
+ pos += sprintf(arg + pos,
+ "%ld output errors\n",
+ sc->oerrors);
+ pos += sprintf(arg + pos,
+ "ierrors = %ld, %ld, %ld, %ld\n",
+ sc->ierrors[0],
+ sc->ierrors[1],
+ sc->ierrors[2],
+ sc->ierrors[3]);
+
+ (*resp)->header.version = NG_VERSION;
+ (*resp)->header.arglen = strlen(arg) + 1;
+ (*resp)->header.token = msg->header.token;
+ (*resp)->header.typecookie = NG_AR_COOKIE;
+ (*resp)->header.cmd = msg->header.cmd;
+ strncpy((*resp)->header.cmdstr, "status",
+ NG_CMDSTRLEN);
+ }
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ free(msg, M_NETGRAPH);
+ return (error);
+}
+
+/*
+ * get data from another node and transmit it to the correct channel
+ */
+static int
+ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
+{
+ int s;
+ int error = 0;
+ struct ar_softc * sc = hook->node->private;
+ struct ifqueue *xmitq_p;
+
+ /*
+ * data doesn't come in from just anywhere (e.g control hook)
+ */
+ if ( hook->private == NULL) {
+ error = ENETDOWN;
+ goto bad;
+ }
+
+ /*
+ * Now queue the data for when it can be sent
+ */
+ if (meta && meta->priority > 0) {
+ xmitq_p = (&sc->xmitq_hipri);
+ } else {
+ xmitq_p = (&sc->xmitq);
+ }
+ s = splimp();
+ if (IF_QFULL(xmitq_p)) {
+ IF_DROP(xmitq_p);
+ splx(s);
+ error = ENOBUFS;
+ goto bad;
+ }
+ IF_ENQUEUE(xmitq_p, m);
+ splx(s);
+ arstart(sc);
+ return (0);
+
+bad:
+ /*
+ * It was an error case.
+ * check if we need to free the mbuf, and then return the error
+ */
+ NG_FREE_DATA(m, meta);
+ return (error);
+}
+
+/*
+ * do local shutdown processing..
+ * this node will refuse to go away, unless the hardware says to..
+ * don't unref the node, or remove our name. just clear our links up.
+ */
+static int
+ngar_rmnode(node_p node)
+{
+ struct ar_softc * sc = node->private;
+
+ ar_down(sc);
+ ng_cutlinks(node);
+ node->flags &= ~NG_INVALID; /* bounce back to life */
+ return (0);
+}
+
+/* already linked */
+static int
+ngar_connect(hook_p hook)
+{
+ /* be really amiable and just say "YUP that's OK by me! " */
+ return (0);
+}
+
+/*
+ * notify on hook disconnection (destruction)
+ *
+ * Invalidate the private data associated with this dlci.
+ * For this type, removal of the last link resets tries to destroy the node.
+ * As the device still exists, the shutdown method will not actually
+ * destroy the node, but reset the device and leave it 'fresh' :)
+ *
+ * The node removal code will remove all references except that owned by the
+ * driver.
+ */
+static int
+ngar_disconnect(hook_p hook)
+{
+ struct ar_softc * sc = hook->node->private;
+ int s;
+ /*
+ * If it's the data hook, then free resources etc.
+ */
+ if (hook->private) {
+ s = splimp();
+ sc->datahooks--;
+ if (sc->datahooks == 0)
+ ar_down(sc);
+ splx(s);
+ } else {
+ sc->debug_hook = NULL;
+ }
+ return (0);
+}
+
+/*
+ * called during bootup
+ * or LKM loading to put this type into the list of known modules
+ */
+static void
+ngar_init(void *ignored)
+{
+ if (ng_newtype(&typestruct))
+ printf("ngar install failed\n");
+ ngar_done_init = 1;
+}
+#endif /* NETGRAPH */
+/*
+ ********************************* END ************************************
+ */
diff --git a/sys/dev/ar/if_ar.h b/sys/dev/ar/if_ar.h
new file mode 100644
index 0000000..a40ccb9
--- /dev/null
+++ b/sys/dev/ar/if_ar.h
@@ -0,0 +1,23 @@
+/*
+ * if_ar.h
+ *
+ * Copyright (C) 1997-1999 Whistle Communications Inc.
+ * All rights reserved.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _I386_ISA_IF_AR_H_
+#define _I386_ISA_IF_AR_H_
+
+/* Node type name and type cookie */
+#define NG_AR_NODE_TYPE "sync_ar"
+#define NG_AR_COOKIE 860552149
+
+/* Netgraph hooks */
+#define NG_AR_HOOK_DEBUG "debug"
+#define NG_AR_HOOK_CONTROL "control"
+#define NG_AR_HOOK_RAW "rawdata"
+
+#endif /* _I386_ISA_IF_AR_H_ */
+
diff --git a/sys/dev/ar/if_ar_isa.c b/sys/dev/ar/if_ar_isa.c
index 3e78c79..0eec2cf 100644
--- a/sys/dev/ar/if_ar_isa.c
+++ b/sys/dev/ar/if_ar_isa.c
@@ -45,6 +45,7 @@
*
*/
+#include "opt_netgraph.h"
#include "ar.h"
#include <sys/param.h>
@@ -55,9 +56,16 @@
#include <sys/socket.h>
#include <net/if.h>
+#ifdef NETGRAPH
+#include <netgraph/ng_message.h>
+#include <netgraph/netgraph.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <i386/isa/if_ar.h>
+#else /* NETGRAPH */
#include <net/if_sppp.h>
-
#include <net/bpf.h>
+#endif /* NETGRAPH */
#include <machine/clock.h>
#include <machine/md_var.h>
@@ -66,10 +74,12 @@
#include <i386/isa/ic/hd64570.h>
#include <i386/isa/isa_device.h>
+#ifndef NETGRAPH
#include "sppp.h"
#if NSPPP <= 0
#error device 'ar' require sppp.
-#endif
+#endif /* NSPPP <= 0 */
+#endif /* NETGRAPH */
#ifdef TRACE
#define TRC(x) x
@@ -118,7 +128,9 @@ static int next_ar_unit = 0;
static struct ar_hardc ar_hardc[NAR];
struct ar_softc {
+#ifndef NETGRAPH
struct sppp ifsppp;
+#endif /* NETGRAPH */
int unit; /* With regards to all ar devices */
int subunit; /* With regards to this card */
struct ar_hardc *hc;
@@ -146,8 +158,38 @@ struct ar_softc {
int scano;
int scachan;
sca_regs *sca;
+#ifdef NETGRAPH
+ int running; /* something is attached so we are running */
+ int dcd; /* do we have dcd? */
+ /* ---netgraph bits --- */
+ char nodename[NG_NODELEN + 1]; /* store our node name */
+ int datahooks; /* number of data hooks attached */
+ node_p node; /* netgraph node */
+ hook_p hook; /* data hook */
+ hook_p debug_hook;
+ struct ifqueue xmitq_hipri; /* hi-priority transmit queue */
+ struct ifqueue xmitq; /* transmit queue */
+ int flags; /* state */
+#define SCF_RUNNING 0x01 /* board is active */
+#define SCF_OACTIVE 0x02 /* output is active */
+ int out_dog; /* watchdog cycles output count-down */
+ struct callout_handle handle; /* timeout(9) handle */
+ u_long inbytes, outbytes; /* stats */
+ u_long lastinbytes, lastoutbytes; /* a second ago */
+ u_long inrate, outrate; /* highest rate seen */
+ u_long inlast; /* last input N secs ago */
+ u_long out_deficit; /* output since last input */
+ u_long oerrors, ierrors[6];
+ u_long opackets, ipackets;
+#endif /* NETGRAPH */
};
+#ifdef NETGRAPH
+#define DOG_HOLDOFF 6 /* dog holds off for 6 secs */
+#define QUITE_A_WHILE 300 /* 5 MINUTES */
+#define LOTS_OF_PACKETS 100
+#endif /* NETGRAPH */
+
static int arprobe(struct isa_device *id);
static int arattach_isa(struct isa_device *id);
@@ -184,9 +226,14 @@ void arintr_hc(struct ar_hardc *hc);
static ointhand2_t arintr;
static int arattach(struct ar_hardc *hc);
static void ar_xmit(struct ar_softc *sc);
+#ifndef NETGRAPH
static void arstart(struct ifnet *ifp);
static int arioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
static void arwatchdog(struct ifnet *ifp);
+#else /* NETGRAPH */
+static void arstart(struct ar_softc *sc);
+static void arwatchdog(struct ar_softc *sc);
+#endif /* NETGRAPH */
static int ar_packet_avail(struct ar_softc *sc, int *len, u_char *rxstat);
static void ar_copy_rxbuf(struct mbuf *m, struct ar_softc *sc, int len);
static void ar_eat_packet(struct ar_softc *sc, int single);
@@ -204,6 +251,37 @@ static void ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr);
static void ar_msci_intr(struct ar_hardc *hc, int scano, u_char isr);
static void ar_timer_intr(struct ar_hardc *hc, int scano, u_char isr);
+#ifdef NETGRAPH
+static void ngar_watchdog_frame(void * arg);
+static void ngar_init(void* ignored);
+static int ngar_constructor(node_p *nodep);
+static int ngar_rcvmsg(node_p node, struct ng_mesg *msg,
+ const char *retaddr, struct ng_mesg **resp);
+static int ngar_rmnode(node_p node);
+static int ngar_newhook(node_p node, hook_p hook, const char *name);
+/*static hook_p ngar_findhook(node_p node, char *name);*/
+static int ngar_connect(hook_p hook); /* already PARTLY linked */
+static int ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta);
+static int ngar_disconnect(hook_p hook); /* notify on disconnect */
+
+static struct ng_type typestruct = {
+ NG_VERSION,
+ NG_AR_NODE_TYPE,
+ NULL,
+ ngar_constructor,
+ ngar_rcvmsg,
+ ngar_rmnode,
+ ngar_newhook,
+ NULL,
+ ngar_connect,
+ ngar_rcvdata,
+ ngar_rcvdata,
+ ngar_disconnect
+};
+
+static int ngar_done_init = 0;
+#endif /* NETGRAPH */
+
/*
* Register the Adapter.
* Probe to see if it is there.
@@ -348,7 +426,9 @@ static int
arattach(struct ar_hardc *hc)
{
struct ar_softc *sc;
+#ifndef NETGRAPH
struct ifnet *ifp;
+#endif /* NETGRAPH */
int unit;
char *iface;
@@ -380,6 +460,7 @@ arattach(struct ar_hardc *hc)
ar_init_tx_dmac(sc);
ar_init_msci(sc);
+#ifndef NETGRAPH
ifp = &sc->ifsppp.pp_if;
ifp->if_softc = sc;
@@ -412,6 +493,25 @@ arattach(struct ar_hardc *hc)
if_attach(ifp);
bpfattach(ifp, DLT_PPP, PPP_HEADER_LEN);
+#else /* NETGRAPH */
+ /*
+ * we have found a node, make sure our 'type' is availabe.
+ */
+ if (ngar_done_init == 0) ngar_init(NULL);
+ if (ng_make_node_common(&typestruct, &sc->node) != 0)
+ return (0);
+ sc->node->private = sc;
+ callout_handle_init(&sc->handle);
+ sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
+ sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
+ sprintf(sc->nodename, "%s%d", NG_AR_NODE_TYPE, sc->unit);
+ if (ng_name_node(sc->node, sc->nodename)) {
+ ng_rmnode(sc->node);
+ ng_unref(sc->node);
+ return (0);
+ }
+ sc->running = 0;
+#endif /* NETGRAPH */
}
if(hc->bustype == AR_BUS_ISA)
@@ -511,10 +611,14 @@ arintr_hc(struct ar_hardc *hc)
static void
ar_xmit(struct ar_softc *sc)
{
+#ifndef NETGRAPH
struct ifnet *ifp;
+#endif /* NETGRAPH */
dmac_channel *dmac;
+#ifndef NETGRAPH
ifp = &sc->ifsppp.pp_if;
+#endif /* NETGRAPH */
dmac = &sc->sca->dmac[DMAC_TXCH(sc->scachan)];
if(sc->hc->bustype == AR_BUS_ISA)
@@ -530,7 +634,11 @@ ar_xmit(struct ar_softc *sc)
if(sc->txb_next_tx == AR_TX_BLOCKS)
sc->txb_next_tx = 0;
+#ifndef NETGRAPH
ifp->if_timer = 2; /* Value in seconds. */
+#else /* NETGRAPH */
+ sc->out_dog = DOG_HOLDOFF; /* give ourself some breathing space*/
+#endif /* NETGRAPH */
if(sc->hc->bustype == AR_BUS_ISA)
ARC_SET_OFF(sc->hc->iobase);
}
@@ -549,30 +657,51 @@ ar_xmit(struct ar_softc *sc)
* that clears that should ensure that the transmitter and its DMA is
* in a "good" idle state.
*/
+#ifndef NETGRAPH
static void
arstart(struct ifnet *ifp)
{
struct ar_softc *sc = ifp->if_softc;
+#else /* NETGRAPH */
+static void
+arstart(struct ar_softc *sc)
+{
+#endif /* NETGRAPH */
int i, len, tlen;
struct mbuf *mtx;
u_char *txdata;
sca_descriptor *txdesc;
struct buf_block *blkp;
+#ifndef NETGRAPH
if(!(ifp->if_flags & IFF_RUNNING))
return;
+#else /* NETGRAPH */
+/* XXX */
+#endif /* NETGRAPH */
top_arstart:
/*
* See if we have space for more packets.
*/
+#ifndef NETGRAPH
if(sc->txb_inuse == AR_TX_BLOCKS) {
- ifp->if_flags |= IFF_OACTIVE;
+ ifp->if_flags |= IFF_OACTIVE; /* yes, mark active */
+#else /* NETGRAPH */
+/*XXX*/ /*ifp->if_flags |= IFF_OACTIVE;*/ /* yes, mark active */
+#endif /* NETGRAPH */
return;
}
+#ifndef NETGRAPH
mtx = sppp_dequeue(ifp);
+#else /* NETGRAPH */
+ IF_DEQUEUE(&sc->xmitq_hipri, mtx);
+ if (mtx == NULL) {
+ IF_DEQUEUE(&sc->xmitq, mtx);
+ }
+#endif /* NETGRAPH */
if(!mtx)
return;
@@ -618,10 +747,16 @@ top_arstart:
txdata += AR_BUF_SIZ;
i++;
+#ifndef NETGRAPH
if(ifp->if_bpf)
bpf_mtap(ifp, mtx);
m_freem(mtx);
++sc->ifsppp.pp_if.if_opackets;
+#else /* NETGRAPH */
+ m_freem(mtx);
+ sc->outbytes += len;
+ ++sc->opackets;
+#endif /* NETGRAPH */
/*
* Check if we have space for another mbuf.
@@ -631,7 +766,14 @@ top_arstart:
if((i + 3) >= blkp->txmax)
break;
+#ifndef NETGRAPH
mtx = sppp_dequeue(ifp);
+#else /* NETGRAPH */
+ IF_DEQUEUE(&sc->xmitq_hipri, mtx);
+ if (mtx == NULL) {
+ IF_DEQUEUE(&sc->xmitq, mtx);
+ }
+#endif /* NETGRAPH */
if(!mtx)
break;
}
@@ -670,6 +812,7 @@ top_arstart:
goto top_arstart;
}
+#ifndef NETGRAPH
static int
arioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
@@ -711,18 +854,26 @@ arioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
splx(s);
return 0;
}
+#endif /* NETGRAPH */
/*
* This is to catch lost tx interrupts.
*/
static void
+#ifndef NETGRAPH
arwatchdog(struct ifnet *ifp)
{
struct ar_softc *sc = ifp->if_softc;
+#else /* NETGRAPH */
+arwatchdog(struct ar_softc *sc)
+{
+#endif /* NETGRAPH */
msci_channel *msci = &sc->sca->msci[sc->scachan];
+#ifndef NETGRAPH
if(!(ifp->if_flags & IFF_RUNNING))
return;
+#endif /* NETGRAPH */
if(sc->hc->bustype == AR_BUS_ISA)
ARC_SET_SCA(sc->hc->iobase, sc->scano);
@@ -730,7 +881,7 @@ arwatchdog(struct ifnet *ifp)
/* XXX if(sc->ifsppp.pp_if.if_flags & IFF_DEBUG) */
printf("ar%d: transmit failed, "
"ST0 %x, ST1 %x, ST3 %x, DSR %x.\n",
- ifp->if_unit,
+ sc->unit,
msci->st0,
msci->st1,
msci->st3,
@@ -743,12 +894,20 @@ arwatchdog(struct ifnet *ifp)
}
sc->xmit_busy = 0;
+#ifndef NETGRAPH
ifp->if_flags &= ~IFF_OACTIVE;
+#else /* NETGRAPH */
+ /* XXX ifp->if_flags &= ~IFF_OACTIVE; */
+#endif /* NETGRAPH */
if(sc->txb_inuse && --sc->txb_inuse)
ar_xmit(sc);
+#ifndef NETGRAPH
arstart(ifp);
+#else /* NETGRAPH */
+ arstart(sc);
+#endif /* NETGRAPH */
}
static void
@@ -803,6 +962,11 @@ ar_up(struct ar_softc *sc)
if(sc->hc->bustype == AR_BUS_ISA)
ARC_SET_OFF(sc->hc->iobase);
+#ifdef NETGRAPH
+ untimeout(ngar_watchdog_frame, sc, sc->handle);
+ sc->handle = timeout(ngar_watchdog_frame, sc, hz);
+ sc->running = 1;
+#endif /* NETGRAPH */
}
static void
@@ -814,6 +978,10 @@ ar_down(struct ar_softc *sc)
sca = sc->sca;
msci = &sca->msci[sc->scachan];
+#ifdef NETGRAPH
+ untimeout(ngar_watchdog_frame, sc, sc->handle);
+ sc->running = 0;
+#endif /* NETGRAPH */
/*
* Disable transmitter and receiver.
* Lower DTR and RTS.
@@ -958,9 +1126,12 @@ arc_init(struct ar_hardc *hc)
u_int descneeded;
u_char isr, mar;
- sc = hc->sc = malloc(hc->numports * sizeof(struct ar_softc),
- M_DEVBUF, M_WAITOK);
+ MALLOC(sc, struct ar_softc *,
+ hc->numports * sizeof(struct ar_softc), M_DEVBUF, M_WAITOK);
+ if (sc == NULL)
+ return (ENOMEM);
bzero(sc, hc->numports * sizeof(struct ar_softc));
+ hc->sc = sc;
hc->txc_dtr[0] = AR_TXC_DTR_NOTRESET |
AR_TXC_DTR_DTR0 | AR_TXC_DTR_DTR1;
@@ -1088,7 +1259,6 @@ arc_init(struct ar_hardc *hc)
if(hc->bustype == AR_BUS_PCI)
hc->orbase[AR_PIMCTRL] = AR_PIM_MODEG | AR_PIM_AUTO_LED;
-
}
@@ -1105,7 +1275,6 @@ ar_init_sca(struct ar_hardc *hc, int scano)
sca_regs *sca;
sca = hc->sca[scano];
-
if(hc->bustype == AR_BUS_ISA)
ARC_SET_SCA(hc->iobase, scano);
@@ -1562,7 +1731,13 @@ ar_get_packets(struct ar_softc *sc)
ar_eat_packet(sc, 1);
continue;
}
+#ifndef NETGRAPH
m->m_pkthdr.rcvif = &sc->ifsppp.pp_if;
+#else /* NETGRAPH */
+ m->m_pkthdr.rcvif = NULL;
+ sc->inbytes += len;
+ sc->inlast = 0;
+#endif /* NETGRAPH */
m->m_pkthdr.len = m->m_len = len;
if(len > MHLEN) {
MCLGET(m, M_DONTWAIT);
@@ -1573,10 +1748,15 @@ ar_get_packets(struct ar_softc *sc)
}
}
ar_copy_rxbuf(m, sc, len);
+#ifndef NETGRAPH
if(sc->ifsppp.pp_if.if_bpf)
bpf_mtap(&sc->ifsppp.pp_if, m);
sppp_input(&sc->ifsppp.pp_if, m);
sc->ifsppp.pp_if.if_ipackets++;
+#else /* NETGRAPH */
+ ng_queue_data(sc->hook, m, NULL);
+ sc->ipackets++;
+#endif /* NETGRAPH */
/*
* Update the eda to the previous descriptor.
@@ -1609,7 +1789,11 @@ ar_get_packets(struct ar_softc *sc)
ar_eat_packet(sc, 1);
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_ierrors++;
+#else /* NETGRAPH */
+ sc->ierrors[0]++;
+#endif /* NETGRAPH */
if(sc->hc->bustype == AR_BUS_ISA)
ARC_SET_SCA(sc->hc->iobase, sc->scano);
@@ -1678,8 +1862,13 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
printf("ar%d: TX DMA Counter overflow, "
"txpacket no %lu.\n",
sc->unit,
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_opackets);
sc->ifsppp.pp_if.if_oerrors++;
+#else /* NETGRAPH */
+ sc->opackets);
+ sc->oerrors++;
+#endif /* NETGRAPH */
}
/* Buffer overflow */
@@ -1688,11 +1877,19 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
"txpacket no %lu, dsr %02x, "
"cda %04x, eda %04x.\n",
sc->unit,
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_opackets,
+#else /* NETGRAPH */
+ sc->opackets,
+#endif /* NETGRAPH */
dsr,
dmac->cda,
dmac->eda);
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_oerrors++;
+#else /* NETGRAPH */
+ sc->oerrors++;
+#endif /* NETGRAPH */
}
/* End of Transfer */
@@ -1706,8 +1903,13 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
* there is data to transmit.
*/
sc->xmit_busy = 0;
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_flags &= ~IFF_OACTIVE;
sc->ifsppp.pp_if.if_timer = 0;
+#else /* NETGRAPH */
+ /* XXX c->ifsppp.pp_if.if_flags &= ~IFF_OACTIVE; */
+ sc->out_dog = 0; /* XXX */
+#endif /* NETGRAPH */
if(sc->txb_inuse && --sc->txb_inuse)
ar_xmit(sc);
@@ -1735,7 +1937,11 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
ar_get_packets(sc);
TRC(
+#ifndef NETGRAPH
if(tt == sc->ifsppp.pp_if.if_ipackets) {
+#else /* NETGRAPH */
+ if(tt == sc->ipackets) {
+#endif /* NETGRAPH */
sca_descriptor *rxdesc;
int i;
@@ -1779,8 +1985,13 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
printf("ar%d: RX DMA Counter overflow, "
"rxpkts %lu.\n",
sc->unit,
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_ipackets);
sc->ifsppp.pp_if.if_ierrors++;
+#else /* NETGRAPH */
+ sc->ipackets);
+ sc->ierrors[1]++;
+#endif /* NETGRAPH */
}
/* Buffer overflow */
@@ -1791,7 +2002,11 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
"rxpkts %lu, rxind %d, "
"cda %x, eda %x, dsr %x.\n",
sc->unit,
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_ipackets,
+#else /* NETGRAPH */
+ sc->ipackets,
+#endif /* NETGRAPH */
sc->rxhind,
dmac->cda,
dmac->eda,
@@ -1801,7 +2016,11 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
* Then get the system running again.
*/
ar_eat_packet(sc, 0);
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_ierrors++;
+#else /* NETGRAPH */
+ sc->ierrors[2]++;
+#endif /* NETGRAPH */
if(hc->bustype == AR_BUS_ISA)
ARC_SET_SCA(hc->iobase, scano);
sca->msci[mch].cmd = SCA_CMD_RXMSGREJ;
@@ -1829,8 +2048,13 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
*/
printf("ar%d: RX End of transfer, rxpkts %lu.\n",
sc->unit,
+#ifndef NETGRAPH
sc->ifsppp.pp_if.if_ipackets);
sc->ifsppp.pp_if.if_ierrors++;
+#else /* NETGRAPH */
+ sc->ipackets);
+ sc->ierrors[3]++;
+#endif /* NETGRAPH */
}
}
@@ -1846,7 +2070,11 @@ ar_dmac_intr(struct ar_hardc *hc, int scano, u_char isr1)
for(mch = 0; mch < NCHAN; mch++) {
if(dotxstart & 0x0C) {
sc = &hc->sc[mch + (NCHAN * scano)];
+#ifndef NETGRAPH
arstart(&sc->ifsppp.pp_if);
+#else /* NETGRAPH */
+ arstart(sc);
+#endif /* NETGRAPH */
}
dotxstart >>= 4;
}
@@ -1864,7 +2092,299 @@ ar_timer_intr(struct ar_hardc *hc, int scano, u_char isr2)
printf("arc%d: ARINTR: TIMER\n", hc->cunit);
}
+
+#ifdef NETGRAPH
+/*****************************************
+ * Device timeout/watchdog routine.
+ * called once per second.
+ * checks to see that if activity was expected, that it hapenned.
+ * At present we only look to see if expected output was completed.
+ */
+static void
+ngar_watchdog_frame(void * arg)
+{
+ struct ar_softc * sc = arg;
+ int s;
+ int speed;
+
+ if(sc->running == 0)
+ return; /* if we are not running let timeouts die */
+ /*
+ * calculate the apparent throughputs
+ * XXX a real hack
+ */
+ s = splimp();
+ speed = sc->inbytes - sc->lastinbytes;
+ sc->lastinbytes = sc->inbytes;
+ if ( sc->inrate < speed )
+ sc->inrate = speed;
+ speed = sc->outbytes - sc->lastoutbytes;
+ sc->lastoutbytes = sc->outbytes;
+ if ( sc->outrate < speed )
+ sc->outrate = speed;
+ sc->inlast++;
+ splx(s);
+
+ if ((sc->inlast > QUITE_A_WHILE)
+ && (sc->out_deficit > LOTS_OF_PACKETS)) {
+ log(LOG_ERR, "ar%d: No response from remote end\n", sc->unit);
+ s = splimp();
+ ar_down(sc);
+ ar_up(sc);
+ sc->inlast = sc->out_deficit = 0;
+ splx(s);
+ } else if ( sc->xmit_busy ) { /* no TX -> no TX timeouts */
+ if (sc->out_dog == 0) {
+ log(LOG_ERR, "ar%d: Transmit failure.. no clock?\n",
+ sc->unit);
+ arwatchdog(sc);
+#if 0
+ s = splimp();
+ ar_down(sc);
+ ar_up(sc);
+ splx(s);
+#endif
+ sc->inlast = sc->out_deficit = 0;
+ } else {
+ sc->out_dog--;
+ }
+ }
+ sc->handle = timeout(ngar_watchdog_frame, sc, hz);
+}
+
+/***********************************************************************
+ * This section contains the methods for the Netgraph interface
+ ***********************************************************************/
/*
- ********************************* END ************************************
+ * It is not possible or allowable to create a node of this type.
+ * If the hardware exists, it will already have created it.
+ */
+static int
+ngar_constructor(node_p *nodep)
+{
+ return (EINVAL);
+}
+
+/*
+ * give our ok for a hook to be added...
+ * If we are not running this should kick the device into life.
+ * We allow hooks called "control" and dlci[1-1023]
+ * The hook's private info points to our stash of info about that
+ * channel.
+ */
+static int
+ngar_newhook(node_p node, hook_p hook, const char *name)
+{
+ struct ar_softc * sc = node->private;
+
+ /*
+ * check if it's our friend the debug hook
+ */
+ if (strcmp(name, NG_AR_HOOK_DEBUG) == 0) {
+ hook->private = NULL; /* paranoid */
+ sc->debug_hook = hook;
+ return (0);
+ }
+
+ /*
+ * Check for raw mode hook.
+ */
+ if (strcmp(name, NG_AR_HOOK_RAW) != 0) {
+ return (EINVAL);
+ }
+ hook->private = sc;
+ sc->hook = hook;
+ sc->datahooks++;
+ ar_up(sc);
+ return (0);
+}
+
+/*
+ * incoming messages.
+ * Just respond to the generic TEXT_STATUS message
*/
+static int
+ngar_rcvmsg(node_p node,
+ struct ng_mesg *msg, const char *retaddr, struct ng_mesg **resp)
+{
+ struct ar_softc * sc;
+ int error = 0;
+
+ sc = node->private;
+ switch (msg->header.typecookie) {
+ case NG_AR_COOKIE:
+ error = EINVAL;
+ break;
+ case NGM_GENERIC_COOKIE:
+ switch(msg->header.cmd) {
+ case NGM_TEXT_STATUS: {
+ char *arg;
+ int pos = 0;
+ int resplen = sizeof(struct ng_mesg) + 512;
+ MALLOC(*resp, struct ng_mesg *, resplen,
+ M_NETGRAPH, M_NOWAIT);
+ if (*resp == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ bzero(*resp, resplen);
+ arg = (*resp)->data;
+
+ /*
+ * Put in the throughput information.
+ */
+ pos = sprintf(arg, "%ld bytes in, %ld bytes out\n"
+ "highest rate seen: %ld B/S in, %ld B/S out\n",
+ sc->inbytes, sc->outbytes,
+ sc->inrate, sc->outrate);
+ pos += sprintf(arg + pos,
+ "%ld output errors\n",
+ sc->oerrors);
+ pos += sprintf(arg + pos,
+ "ierrors = %ld, %ld, %ld, %ld\n",
+ sc->ierrors[0],
+ sc->ierrors[1],
+ sc->ierrors[2],
+ sc->ierrors[3]);
+
+ (*resp)->header.version = NG_VERSION;
+ (*resp)->header.arglen = strlen(arg) + 1;
+ (*resp)->header.token = msg->header.token;
+ (*resp)->header.typecookie = NG_AR_COOKIE;
+ (*resp)->header.cmd = msg->header.cmd;
+ strncpy((*resp)->header.cmdstr, "status",
+ NG_CMDSTRLEN);
+ }
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ free(msg, M_NETGRAPH);
+ return (error);
+}
+
+/*
+ * get data from another node and transmit it to the correct channel
+ */
+static int
+ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
+{
+ int s;
+ int error = 0;
+ struct ar_softc * sc = hook->node->private;
+ struct ifqueue *xmitq_p;
+
+ /*
+ * data doesn't come in from just anywhere (e.g control hook)
+ */
+ if ( hook->private == NULL) {
+ error = ENETDOWN;
+ goto bad;
+ }
+
+ /*
+ * Now queue the data for when it can be sent
+ */
+ if (meta && meta->priority > 0) {
+ xmitq_p = (&sc->xmitq_hipri);
+ } else {
+ xmitq_p = (&sc->xmitq);
+ }
+ s = splimp();
+ if (IF_QFULL(xmitq_p)) {
+ IF_DROP(xmitq_p);
+ splx(s);
+ error = ENOBUFS;
+ goto bad;
+ }
+ IF_ENQUEUE(xmitq_p, m);
+ splx(s);
+ arstart(sc);
+ return (0);
+
+bad:
+ /*
+ * It was an error case.
+ * check if we need to free the mbuf, and then return the error
+ */
+ NG_FREE_DATA(m, meta);
+ return (error);
+}
+
+/*
+ * do local shutdown processing..
+ * this node will refuse to go away, unless the hardware says to..
+ * don't unref the node, or remove our name. just clear our links up.
+ */
+static int
+ngar_rmnode(node_p node)
+{
+ struct ar_softc * sc = node->private;
+
+ ar_down(sc);
+ ng_cutlinks(node);
+ node->flags &= ~NG_INVALID; /* bounce back to life */
+ return (0);
+}
+
+/* already linked */
+static int
+ngar_connect(hook_p hook)
+{
+ /* be really amiable and just say "YUP that's OK by me! " */
+ return (0);
+}
+
+/*
+ * notify on hook disconnection (destruction)
+ *
+ * Invalidate the private data associated with this dlci.
+ * For this type, removal of the last link resets tries to destroy the node.
+ * As the device still exists, the shutdown method will not actually
+ * destroy the node, but reset the device and leave it 'fresh' :)
+ *
+ * The node removal code will remove all references except that owned by the
+ * driver.
+ */
+static int
+ngar_disconnect(hook_p hook)
+{
+ struct ar_softc * sc = hook->node->private;
+ int s;
+ /*
+ * If it's the data hook, then free resources etc.
+ */
+ if (hook->private) {
+ s = splimp();
+ sc->datahooks--;
+ if (sc->datahooks == 0)
+ ar_down(sc);
+ splx(s);
+ } else {
+ sc->debug_hook = NULL;
+ }
+ return (0);
+}
+
+/*
+ * called during bootup
+ * or LKM loading to put this type into the list of known modules
+ */
+static void
+ngar_init(void *ignored)
+{
+ if (ng_newtype(&typestruct))
+ printf("ngar install failed\n");
+ ngar_done_init = 1;
+}
+#endif /* NETGRAPH */
+/*
+ ********************************* END ************************************
+ */
OpenPOWER on IntegriCloud