145163Ssklower /*
245163Ssklower * Copyright (c) 1990 Regents of the University of California.
345163Ssklower * All rights reserved.
445163Ssklower *
545163Ssklower * %sccs.include.redist.c%
645163Ssklower *
7*53368Ssklower * @(#)if_dp.c 7.10 (Berkeley) 05/04/92
845163Ssklower */
945163Ssklower
1045163Ssklower #include "dp.h"
1145163Ssklower #if NDP > 0
1245163Ssklower
1345163Ssklower /*
1445163Ssklower * DPV-11 device driver, X.25 version
1545163Ssklower *
1645163Ssklower * Derived from dmc-11 driver:
1745163Ssklower *
1845163Ssklower * Bill Nesheim
1945163Ssklower * Cornell University
2045163Ssklower *
2145163Ssklower * Lou Salkind
2245163Ssklower * New York University
2345163Ssklower */
2445163Ssklower
2545163Ssklower /* #define DEBUG /* for base table dump on fatal error */
2645163Ssklower
2745801Sbostic #include "../include/pte.h"
2845163Ssklower
2945801Sbostic #include "sys/param.h"
3045801Sbostic #include "sys/systm.h"
3145801Sbostic #include "sys/mbuf.h"
3245801Sbostic #include "sys/buf.h"
3345801Sbostic #include "sys/ioctl.h" /* must precede tty.h */
3445801Sbostic #include "sys/protosw.h"
3545801Sbostic #include "sys/socket.h"
3645801Sbostic #include "sys/socketvar.h"
3745801Sbostic #include "sys/syslog.h"
3845801Sbostic #include "sys/vmmac.h"
3945801Sbostic #include "sys/errno.h"
4045801Sbostic #include "sys/time.h"
4145801Sbostic #include "sys/kernel.h"
4245163Ssklower
4345801Sbostic #include "net/if.h"
4448964Ssklower #include "net/if_types.h"
4545801Sbostic #include "net/netisr.h"
4645801Sbostic #include "net/route.h"
4745163Ssklower
4845801Sbostic #include "../include/cpu.h"
4945801Sbostic #include "../include/mtpr.h"
5045166Ssklower
5145228Ssklower #define dzdevice dpdevice
5245801Sbostic #include "../uba/pdma.h"
5345801Sbostic #include "../uba/ubavar.h"
5445163Ssklower
5545801Sbostic #include "netccitt/x25.h"
5645801Sbostic #include "netccitt/pk.h"
5745801Sbostic #include "netccitt/pk_var.h"
5845166Ssklower
5945163Ssklower #include "if_dpreg.h"
6045163Ssklower
6145163Ssklower /*
6245163Ssklower * Driver information for auto-configuration stuff.
6345163Ssklower */
6445163Ssklower int dpprobe(), dpattach(), dpinit(), dpioctl(), dprint(), dpxint();
6550166Ssklower int dpoutput(), dpreset(), dptimeout(), dpstart(), dptestoutput();
6650166Ssklower int x25_ifoutput(), x25_rtrequest();
6745163Ssklower
6845163Ssklower struct uba_device *dpinfo[NDP];
6945163Ssklower
7045163Ssklower u_short dpstd[] = { 0 };
7145163Ssklower struct uba_driver dpdriver =
7245163Ssklower { dpprobe, 0, dpattach, 0, dpstd, "dp", dpinfo };
7345163Ssklower
7445163Ssklower /*
7545163Ssklower * Pdma structures for fast interrupts.
7645163Ssklower */
7745163Ssklower struct pdma dppdma[2*NDP];
7845163Ssklower
7945163Ssklower /*
8045163Ssklower * DP software status per interface.
8145163Ssklower *
8245163Ssklower * Each interface is referenced by a network interface structure,
8345163Ssklower * dp_if, which the routing code uses to locate the interface.
8445163Ssklower * This structure contains the output queue for the interface, its address, ...
8545163Ssklower */
8645163Ssklower struct dp_softc {
8745163Ssklower struct ifnet dp_if; /* network-visible interface */
8845228Ssklower int dp_ipl;
8945236Ssklower struct dpdevice *dp_addr; /* dpcsr address */
9045163Ssklower short dp_iused; /* input buffers given to DP */
9145163Ssklower short dp_flags; /* flags */
9245228Ssklower #define DPF_RUNNING 0x01 /* device initialized */
9345228Ssklower #define DPF_ONLINE 0x02 /* device running (had a RDYO) */
9445228Ssklower #define DPF_RESTART 0x04 /* software restart in progress */
9545228Ssklower #define DPF_FLUSH 0x08 /* had a ROVR, flush ipkt when done */
9650166Ssklower #define DPF_X25UP 0x10 /* XXX -- someday we'll do PPP also */
9745163Ssklower short dp_ostate; /* restarting, etc. */
9845163Ssklower short dp_istate; /* not sure this is necessary */
9945163Ssklower #define DPS_IDLE 0
10045163Ssklower #define DPS_RESTART 1
10145163Ssklower #define DPS_ACTIVE 2
10245163Ssklower #define DPS_XEM 3 /* transmitting CRC, etc. */
10345289Ssklower short dp_olen; /* length of last packet sent */
10445289Ssklower short dp_ilen; /* length of last packet recvd */
10545163Ssklower char dp_obuf[DP_MTU+8];
10645166Ssklower char dp_ibuf[DP_MTU+8];
10745163Ssklower } dp_softc[NDP];
10845163Ssklower
10945289Ssklower /*
11045289Ssklower * Debug info
11145289Ssklower */
11245289Ssklower struct dpstat {
11345289Ssklower long start;
11445289Ssklower long nohdr;
11545289Ssklower long init;
11645289Ssklower long rint;
11745289Ssklower long xint;
11845289Ssklower long reset;
11945289Ssklower long ioctl;
12045289Ssklower long down;
12145289Ssklower long mchange;
12245289Ssklower long timeout;
12345289Ssklower long rsm;
12445289Ssklower long rem;
12545289Ssklower long remchr;
12645289Ssklower long rga;
12745289Ssklower long xem;
12845289Ssklower long rovr;
12945289Ssklower } dpstat;
13045289Ssklower
13145289Ssklower short dp_ilb = 0;
13248964Ssklower short dp_log = 0;
13345289Ssklower
13445289Ssklower #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
13545289Ssklower int dp_sizes[] = {
13645289Ssklower sizeof(dp_softc[0]), sizeof(struct ifnet),
13745289Ssklower _offsetof(struct dp_softc, dp_obuf[0]),
13845289Ssklower _offsetof(struct dp_softc, dp_ibuf[0]),
13945289Ssklower };
14045289Ssklower
dpprobe(reg,ui)14145163Ssklower dpprobe(reg, ui)
14245163Ssklower caddr_t reg;
14345163Ssklower struct uba_device *ui;
14445163Ssklower {
14545163Ssklower register int br, cvec;
14645163Ssklower register struct dpdevice *addr = (struct dpdevice *)reg;
14745236Ssklower register int unit = ui->ui_unit;
14845163Ssklower
14945163Ssklower #ifdef lint
15045163Ssklower br = 0; cvec = br; br = cvec;
15145163Ssklower dprint(0); dpxint(0);
15245163Ssklower #endif
15345228Ssklower (void) spl6();
15445163Ssklower addr->dpclr = DP_CLR;
15545163Ssklower addr->dpclr = DP_XIE|DP_XE;
15645163Ssklower DELAY(100000);
15745236Ssklower dp_softc[unit].dp_ipl = br = qbgetpri();
15845236Ssklower dp_softc[unit].dp_addr = addr;
15945163Ssklower addr->dpclr = 0;
16045228Ssklower if (cvec && cvec != 0x200){
16145228Ssklower cvec -= 4;
16245228Ssklower }
16345163Ssklower return (1);
16445163Ssklower }
16545163Ssklower
16645163Ssklower /*
16745163Ssklower * Interface exists: make available by filling in network interface
16845163Ssklower * record. System will initialize the interface when it is ready
16945163Ssklower * to accept packets.
17045163Ssklower */
dpattach(ui)17145163Ssklower dpattach(ui)
17245163Ssklower register struct uba_device *ui;
17345163Ssklower {
17445163Ssklower register struct dp_softc *dp = &dp_softc[ui->ui_unit];
17545163Ssklower
17645163Ssklower dp->dp_if.if_unit = ui->ui_unit;
17745163Ssklower dp->dp_if.if_name = "dp";
17845163Ssklower dp->dp_if.if_mtu = DP_MTU;
17945163Ssklower dp->dp_if.if_init = dpinit;
18045163Ssklower dp->dp_if.if_output = x25_ifoutput;
18148964Ssklower dp->dp_if.if_type = IFT_X25;
18248964Ssklower dp->dp_if.if_hdrlen = 5;
18348964Ssklower dp->dp_if.if_addrlen = 8;
18445163Ssklower dp->dp_if.if_start = dpstart;
18545163Ssklower dp->dp_if.if_ioctl = dpioctl;
18645163Ssklower dp->dp_if.if_reset = dpreset;
18745163Ssklower dp->dp_if.if_watchdog = dptimeout;
18845228Ssklower dp->dp_if.if_flags = 0;
18945163Ssklower if_attach(&dp->dp_if);
19045163Ssklower }
19145163Ssklower
19245163Ssklower /*
19345163Ssklower * Reset of interface after UNIBUS reset.
19445163Ssklower * If interface is on specified UBA, reset its state.
19545163Ssklower */
dpreset(unit,uban)19645163Ssklower dpreset(unit, uban)
19745163Ssklower int unit, uban;
19845163Ssklower {
19945163Ssklower register struct uba_device *ui;
20045163Ssklower register struct dp_softc *dp = &dp_softc[unit];
20145163Ssklower register struct dpdevice *addr;
20245163Ssklower
20345228Ssklower dpstat.reset++;
20445163Ssklower if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 ||
20545163Ssklower ui->ui_ubanum != uban)
20645163Ssklower return;
20745236Ssklower dpdown(unit);
20845236Ssklower dpinit(unit);
20945163Ssklower printf(" dp%d", unit);
21045163Ssklower }
21145163Ssklower
21245163Ssklower /*
21345163Ssklower * Initialization of interface.
21445163Ssklower */
dpinit(unit)21545163Ssklower dpinit(unit)
21645163Ssklower int unit;
21745163Ssklower {
21845163Ssklower register struct dp_softc *dp = &dp_softc[unit];
21945163Ssklower register struct dpdevice *addr;
22045228Ssklower register struct ifaddr *ifa;
22145228Ssklower register struct pdma *pdp = &dppdma[unit*2];
22245228Ssklower int base, s;
22345163Ssklower
22445228Ssklower dpstat.init++;
22545163Ssklower /*
22645163Ssklower * Check to see that an address has been set.
22745163Ssklower */
22845228Ssklower for (ifa = dp->dp_if.if_addrlist; ifa; ifa = ifa->ifa_next)
22945163Ssklower if (ifa->ifa_addr->sa_family != AF_LINK)
23045163Ssklower break;
23145163Ssklower if (ifa == (struct ifaddr *) 0)
23245163Ssklower return;
23345163Ssklower
23445236Ssklower addr = dp->dp_addr;
23545228Ssklower s = splimp();
23645163Ssklower dp->dp_iused = 0;
23745163Ssklower dp->dp_istate = dp->dp_ostate = DPS_IDLE;
23845228Ssklower dp->dp_if.if_flags |= IFF_RUNNING;
23945228Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE;
24045228Ssklower
24145228Ssklower pdp->p_addr = addr;
24245228Ssklower pdp->p_fcn = dpxint;
24345228Ssklower pdp->p_mem = pdp->p_end = dp->dp_obuf;
24445228Ssklower pdp++;
24545228Ssklower pdp->p_addr = addr;
24645228Ssklower pdp->p_fcn = dprint;
24745228Ssklower /* force initial interrupt to come to dprint */
24845228Ssklower pdp->p_mem = pdp->p_end = dp->dp_ibuf + DP_MTU + 8;
24945228Ssklower
25045228Ssklower addr->dpclr = DP_CLR;
25145289Ssklower DELAY(5000);
25245237Ssklower /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts),
25345237Ssklower CRC = CCIIT, initially all ones, 2nd addr = 0 */
25445237Ssklower addr->dpsar = DP_SSLM | DP_IDLE;
25545289Ssklower addr->dpclr = DP_XE | dp_ilb;
25645289Ssklower addr->dptdsr = DP_XSM;
25745237Ssklower /* enable receiver, receive interrupt, DTR, RTS */
25845228Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
25945228Ssklower dpstart(&dp->dp_if);
26045163Ssklower splx(s);
26145163Ssklower }
26245163Ssklower
26345163Ssklower /*
26445163Ssklower * Start output on interface. Get another datagram
26545163Ssklower * to send from the interface queue and map it to
26645163Ssklower * the interface before starting output.
26745163Ssklower *
26845163Ssklower */
26945163Ssklower dpstart(ifp)
27045163Ssklower struct ifnet *ifp;
27145163Ssklower {
27245228Ssklower int s, unit = ifp->if_unit, error = 0, len;
27345163Ssklower register struct dp_softc *dp = &dp_softc[unit];
27445237Ssklower register struct dpdevice *addr = dp->dp_addr;
27545163Ssklower register struct mbuf *m;
27645163Ssklower register char *cp;
27745163Ssklower char *cplim;
27845163Ssklower
27945163Ssklower /*
28045163Ssklower * If already doing output, go away and depend on transmit
28145163Ssklower * complete or error.
28245163Ssklower */
28345228Ssklower dpstat.start++;
28445236Ssklower if ((dp->dp_if.if_flags & IFF_OACTIVE) ||
28545289Ssklower (dp->dp_if.if_flags & IFF_RUNNING) == 0)
28645228Ssklower goto out;
28745163Ssklower IF_DEQUEUE(&dp->dp_if.if_snd, m);
28845163Ssklower if (m == 0)
28945228Ssklower goto out;
29045228Ssklower dp->dp_if.if_collisions++;
29145228Ssklower if (m->m_flags & M_PKTHDR)
29245228Ssklower len = m->m_pkthdr.len;
29345228Ssklower else {
29445228Ssklower struct mbuf *m0 = m;
29545228Ssklower for (len = 0; m; m = m->m_next)
29645228Ssklower len += m->m_len;
29745228Ssklower m = m0;
29845228Ssklower dpstat.nohdr++;
29945228Ssklower }
30045289Ssklower if (len < 2)
30145228Ssklower goto out;
30245228Ssklower if (len > DP_MTU) {
30345228Ssklower error = EINVAL;
30445228Ssklower goto out;
30545228Ssklower }
30645289Ssklower dppdma[2*unit].p_mem = cp = dp->dp_obuf;
30745163Ssklower while (m) {
30845163Ssklower struct mbuf *n;
30945163Ssklower bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len);
31045163Ssklower cp += m->m_len;
31145163Ssklower MFREE(m, n); m = n;
31245163Ssklower }
31345289Ssklower dppdma[2*unit].p_end = cp - 1;
31445163Ssklower dp->dp_if.if_flags |= IFF_OACTIVE;
31545163Ssklower dp->dp_ostate = DPS_ACTIVE;
31645228Ssklower dp->dp_if.if_collisions--;
31745289Ssklower dp->dp_olen = len;
31845289Ssklower if (dp_log) {
31945289Ssklower register u_char *p = (u_char *)dp->dp_obuf;
32045289Ssklower log(LOG_DEBUG, "dpoutput(%d):%x %x %x %x %x\n",
32145289Ssklower len, p[0], p[1], p[2], p[3], p[4]);
32245289Ssklower }
32345237Ssklower addr->dpsar = DP_SSLM | DP_IDLE;
32445237Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
32545289Ssklower addr->dpclr = DP_XIE | DP_XE | dp_ilb;
32645289Ssklower addr->dptdsr = DP_XSM;
32745228Ssklower out:
32845228Ssklower return (error);
32945163Ssklower }
33045163Ssklower /*
33145163Ssklower * Receive done or error interrupt
33245163Ssklower */
dprint(unit,pdma,addr)33345163Ssklower dprint(unit, pdma, addr)
33445163Ssklower register struct pdma *pdma;
33545163Ssklower register struct dpdevice *addr;
33645163Ssklower {
33745166Ssklower register struct dp_softc *dp = &dp_softc[unit];
33845237Ssklower short rdsr = addr->dprdsr, rcsr = pdma->p_arg;
33945163Ssklower
34045228Ssklower dpstat.rint++;
34145228Ssklower splx(dp->dp_ipl);
34245237Ssklower if (rdsr & DP_RGA) {
34345237Ssklower /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts),
34445237Ssklower CRC = CCIIT, initially all ones, 2nd addr = 0 */
34545237Ssklower addr->dpsar = DP_SSLM | DP_IDLE;
34645237Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
34745237Ssklower dpstat.rga++;
34845237Ssklower return;
34945237Ssklower }
35045166Ssklower if (rdsr & DP_RSM) { /* Received Start of Message */
35145237Ssklower dpstat.rsm++;
35245237Ssklower pdma->p_mem = dp->dp_ibuf;
35345237Ssklower if (rcsr & DP_RDR) {
35445237Ssklower dp->dp_ibuf[0] = rdsr & DP_RBUF;
35545237Ssklower pdma->p_mem++;
35645237Ssklower }
35745166Ssklower dp->dp_flags &= ~DPF_FLUSH;
35845163Ssklower return;
35945163Ssklower }
36045166Ssklower if (rdsr & DP_REM) { /* Received End of Message */
36145237Ssklower dpstat.rem++;
36245289Ssklower if (rcsr & DP_RDR) {
36345289Ssklower *(pdma->p_mem++) = rdsr;
36445289Ssklower dpstat.remchr++;
36545289Ssklower }
36645289Ssklower dp->dp_ilen = pdma->p_mem - dp->dp_ibuf;
36745166Ssklower if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) {
36845166Ssklower dp->dp_if.if_ierrors++;
36945228Ssklower } else
37045289Ssklower dpinput(&dp->dp_if, dp->dp_ilen, dp->dp_ibuf);
37145228Ssklower pdma->p_mem = pdma->p_end;
37245228Ssklower dp->dp_flags &= ~ DPF_FLUSH;
37345228Ssklower return;
37445228Ssklower }
37545228Ssklower if (rdsr & DP_ROVR) {
37645289Ssklower dpstat.rovr++;
37745228Ssklower dp->dp_flags |= DPF_FLUSH;
37845228Ssklower return;
37945228Ssklower }
38045228Ssklower if (rcsr & DP_MSC) {
38145228Ssklower dpstat.mchange++;
38245228Ssklower if (0 == (rcsr & DP_DSR)) {
38345228Ssklower log(LOG_DEBUG, "dp%d: lost modem\n", unit);
38445237Ssklower /*dpdown(unit);*/
38545163Ssklower }
38645163Ssklower return;
38745163Ssklower }
38845163Ssklower dp->dp_flags |= DPF_FLUSH;
38945163Ssklower if (pdma->p_mem != pdma->p_end)
39045289Ssklower log(LOG_DEBUG, "dp%d: unexplained receiver interrupt\n", unit);
39145163Ssklower }
39245163Ssklower /*
39345163Ssklower * Transmit complete or error interrupt
39445163Ssklower */
dpxint(unit,pdma,addr)39545163Ssklower dpxint(unit, pdma, addr)
39645163Ssklower register struct pdma *pdma;
39745163Ssklower register struct dpdevice *addr;
39845163Ssklower {
39945166Ssklower register struct dp_softc *dp = &dp_softc[unit];
40045228Ssklower int s;
40145163Ssklower
40245228Ssklower splx(dp->dp_ipl);
40345228Ssklower dpstat.xint++;
40445163Ssklower if (addr->dptdsr & DP_XERR) {
40545289Ssklower log(LOG_DEBUG, "if_dp%d: data late\n", unit);
40645163Ssklower restart:
40745163Ssklower pdma->p_mem = dp->dp_obuf;
40845163Ssklower addr->dptdsr = DP_XSM;
40945228Ssklower dp->dp_if.if_oerrors++;
41045163Ssklower return;
41145163Ssklower }
41245163Ssklower switch (dp->dp_ostate) {
41345163Ssklower
41445163Ssklower case DPS_ACTIVE:
41545163Ssklower if (pdma->p_mem != pdma->p_end) {
41645289Ssklower log(LOG_DEBUG, "if_dp%d: misc error in dpxint\n", unit);
41745163Ssklower goto restart;
41845163Ssklower }
41945289Ssklower addr->dpsar = DP_IDLE|DP_SSLM;
42045289Ssklower addr->dpclr = DP_XE | DP_XIE | dp_ilb;
42145289Ssklower addr->dptdsr = DP_XEM | (0xff & pdma->p_mem[0]);
42245289Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
42345163Ssklower dp->dp_ostate = DPS_XEM;
42445163Ssklower break;
42545163Ssklower
42645163Ssklower case DPS_XEM:
42745289Ssklower dpstat.xem++;
42845228Ssklower dp->dp_if.if_opackets++;
42945289Ssklower dp->dp_ostate = DPS_IDLE;
43045163Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE;
43145163Ssklower if (dp->dp_if.if_snd.ifq_len)
43245163Ssklower dpstart(&dp->dp_if);
43345163Ssklower else {
43445289Ssklower addr->dpsar = DP_IDLE|DP_SSLM;
43545289Ssklower addr->dpclr = DP_XE | dp_ilb;
43645289Ssklower addr->dptdsr = DP_XSM;
43745289Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR|DP_RTS;
43845163Ssklower }
43945163Ssklower break;
44045163Ssklower
44145163Ssklower default:
44245289Ssklower log(LOG_DEBUG, "if_dp%d: impossible state in dpxint\n");
44345163Ssklower }
44445163Ssklower }
44545163Ssklower
dpinput(ifp,len,buffer)44645228Ssklower dpinput(ifp, len, buffer)
44745228Ssklower register struct ifnet *ifp;
44845163Ssklower caddr_t buffer;
44945163Ssklower {
45045163Ssklower register struct ifqueue *inq;
45145163Ssklower register struct mbuf *m;
45245228Ssklower extern struct ifqueue hdintrq, ipintrq;
45345289Ssklower int isr;
454*53368Ssklower extern struct mbuf *m_devget();
45545163Ssklower
45645228Ssklower ifp->if_ipackets++;
45745289Ssklower if (dp_log) {
45845289Ssklower register u_char *p = (u_char *)buffer;
45945289Ssklower log(LOG_DEBUG, "dpinput(%d):%x %x %x %x %x\n",
46045289Ssklower len, p[0], p[1], p[2], p[3], p[4]);
46145289Ssklower }
46245289Ssklower
46345228Ssklower {
46445228Ssklower register struct ifaddr *ifa = ifp->if_addrlist;
46545228Ssklower register u_char *cp = (u_char *)buffer;
46645228Ssklower
46745228Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
46845228Ssklower if (ifa->ifa_addr->sa_family != AF_LINK)
46945228Ssklower break;
47045228Ssklower if (cp[0] == 0xff && cp[1] == 0x3) {
47145228Ssklower /* This is a UI HDLC Packet, so we'll assume PPP
47245228Ssklower protocol. for now, IP only. */
47345228Ssklower buffer += 4;
47445228Ssklower len -= 4;
47545228Ssklower inq = &ipintrq;
47645289Ssklower isr = NETISR_IP;
47745228Ssklower } else {
47845228Ssklower inq = &hdintrq;
47945289Ssklower isr = NETISR_CCITT;
48045228Ssklower }
48145228Ssklower }
48245228Ssklower if (len <= 0)
48345163Ssklower return;
48445163Ssklower
485*53368Ssklower m = m_devget(buffer, len , 0, ifp, 0);
48645163Ssklower if (m == 0)
48745163Ssklower return;
48845163Ssklower
48945163Ssklower if(IF_QFULL(inq)) {
49045163Ssklower IF_DROP(inq);
49145163Ssklower m_freem(m);
49245163Ssklower } else {
49345163Ssklower IF_ENQUEUE(inq, m);
49445289Ssklower schednetisr(isr);
49545163Ssklower }
49645163Ssklower }
49745163Ssklower
49845163Ssklower /*
49945163Ssklower * Process an ioctl request.
50045163Ssklower */
dpioctl(ifp,cmd,data)50145163Ssklower dpioctl(ifp, cmd, data)
50245163Ssklower register struct ifnet *ifp;
50345163Ssklower int cmd;
50445163Ssklower caddr_t data;
50545163Ssklower {
50645163Ssklower register struct ifaddr *ifa = (struct ifaddr *)data;
50745163Ssklower int s = splimp(), error = 0;
50845166Ssklower struct dp_softc *dp = &dp_softc[ifp->if_unit];
50945163Ssklower
51045228Ssklower dpstat.ioctl++;
51145163Ssklower switch (cmd) {
51245228Ssklower case SIOCSIFCONF_X25:
51345228Ssklower ifp->if_flags |= IFF_UP;
51445228Ssklower error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr);
51545228Ssklower if (error == 0)
51645228Ssklower dpinit(ifp->if_unit);
51745228Ssklower break;
51845163Ssklower
51950166Ssklower case SIOCSIFADDR:
52050166Ssklower ifa->ifa_rtrequest = x25_rtrequest;
52150166Ssklower break;
52250166Ssklower
52345228Ssklower case SIOCSIFFLAGS:
52445228Ssklower if ((ifp->if_flags & IFF_UP) == 0 &&
52545228Ssklower (ifp->if_flags & IFF_RUNNING))
52645228Ssklower dpdown(ifp->if_unit);
52745228Ssklower else if (ifp->if_flags & IFF_UP &&
52845228Ssklower (ifp->if_flags & IFF_RUNNING) == 0)
52945228Ssklower dpinit(ifp->if_unit);
53045228Ssklower break;
53145163Ssklower
53245228Ssklower
53345163Ssklower default:
53445163Ssklower error = EINVAL;
53545163Ssklower }
53645163Ssklower splx(s);
53745163Ssklower return (error);
53845163Ssklower }
53945163Ssklower /*
54045163Ssklower * Reset a device and mark down.
54145163Ssklower * Flush output queue and drop queue limit.
54245163Ssklower */
dpdown(unit)54345163Ssklower dpdown(unit)
54445236Ssklower int unit;
54545163Ssklower {
54645236Ssklower
54745163Ssklower register struct dp_softc *dp = &dp_softc[unit];
54845236Ssklower register struct dpdevice *addr = dp->dp_addr;
54945163Ssklower
55045228Ssklower dpstat.down++;
55145163Ssklower if_qflush(&dp->dp_if.if_snd);
55245236Ssklower dp->dp_flags = 0;
55345236Ssklower dp->dp_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
55445236Ssklower
55545236Ssklower addr->dpclr = DP_CLR;
55645236Ssklower DELAY(1000);
55745236Ssklower addr->dpsar = 0;
55845236Ssklower addr->dprcsr = 0;
55945163Ssklower }
56045163Ssklower
56145163Ssklower /*
56245163Ssklower * Watchdog timeout to see that transmitted packets don't
56345163Ssklower * lose interrupts. The device has to be online (the first
56445163Ssklower * transmission may block until the other side comes up).
56545163Ssklower */
dptimeout(unit)56645163Ssklower dptimeout(unit)
56745163Ssklower int unit;
56845163Ssklower {
56945163Ssklower register struct dp_softc *dp;
57045163Ssklower
57145228Ssklower /* currently not armed */
57245228Ssklower dpstat.timeout++;
57345163Ssklower dp = &dp_softc[unit];
57445228Ssklower if (dp->dp_if.if_flags & IFF_OACTIVE) {
57545228Ssklower dpstart(&dp->dp_if);
57645163Ssklower }
57745163Ssklower }
57845228Ssklower /*
57945228Ssklower * For debugging loopback activity.
58045228Ssklower */
58145228Ssklower static char pppheader[4] = { -1, 3, 0, 0x21 };
58245228Ssklower int dp_louts;
58345228Ssklower
dptestoutput(ifp,m,dst,rt)58445228Ssklower dptestoutput(ifp, m, dst, rt)
58545228Ssklower register struct ifnet *ifp;
58645228Ssklower register struct mbuf *m;
58745228Ssklower struct sockaddr *dst;
58845228Ssklower struct rtentry *rt;
58945228Ssklower {
59045228Ssklower /*
59145228Ssklower * Queue message on interface, and start output if interface
59245228Ssklower * not yet active.
59345228Ssklower */
59445228Ssklower int s = splimp(), error = 0;
59545228Ssklower dp_louts++;
59645228Ssklower M_PREPEND(m, sizeof pppheader, M_DONTWAIT);
59745228Ssklower if (m == 0) {
59845228Ssklower splx(s);
59945228Ssklower return ENOBUFS;
60045228Ssklower }
60145228Ssklower bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader);
60245228Ssklower if (IF_QFULL(&ifp->if_snd)) {
60345228Ssklower IF_DROP(&ifp->if_snd);
60445228Ssklower /* printf("%s%d: HDLC says OK to send but queue full, may hang\n",
60545228Ssklower ifp->if_name, ifp->if_unit);*/
60645228Ssklower m_freem(m);
60745228Ssklower error = ENOBUFS;
60845228Ssklower } else {
60945228Ssklower IF_ENQUEUE(&ifp->if_snd, m);
61045228Ssklower if ((ifp->if_flags & IFF_OACTIVE) == 0)
61145228Ssklower (*ifp->if_start)(ifp);
61245228Ssklower }
61345228Ssklower splx(s);
61445228Ssklower return (error);
61545228Ssklower }
61645228Ssklower
61745163Ssklower #endif
618