150824Ssklower /*
2*63364Sbostic * Copyright (c) 1982, 1990, 1993
3*63364Sbostic * The Regents of the University of California. All rights reserved.
450824Ssklower *
550824Ssklower * %sccs.include.redist.c%
650824Ssklower *
7*63364Sbostic * @(#)if_apx.c 8.1 (Berkeley) 06/11/93
850824Ssklower */
950824Ssklower
1050824Ssklower /*
1150824Ssklower * Driver for SGS-THOMSON MK5025 based Link level controller.
1250824Ssklower * The chip will do LAPB in hardware, although this driver only
1350824Ssklower * attempts to use it for HDLC framing.
1450824Ssklower *
1550824Ssklower * Driver written by Keith Sklower, based on lance AMD7990
1650824Ssklower * driver by Van Jacobsen, and information graciously supplied
1750824Ssklower * by the ADAX corporation of Berkeley, CA.
1850824Ssklower */
1950824Ssklower
2050824Ssklower #include "apx.h"
2150824Ssklower #if NAPX > 0
2250824Ssklower
2356513Sbostic #include <sys/param.h>
2456513Sbostic #include <sys/mbuf.h>
2556513Sbostic #include <sys/socket.h>
2656513Sbostic #include <sys/ioctl.h>
2756513Sbostic #include <sys/errno.h>
2856513Sbostic #include <sys/syslog.h>
2950824Ssklower
3056513Sbostic #include <net/if.h>
3156513Sbostic #include <net/netisr.h>
3256513Sbostic #include <net/if_types.h>
3352828Ssklower #ifdef CCITT
3456513Sbostic #include <netccitt/x25.h>
3552828Ssklower int x25_rtrequest(), x25_ifoutput();
3652828Ssklower #endif
3750824Ssklower
3856513Sbostic #include <i386/isa/if_apxreg.h>
3950824Ssklower
4050824Ssklower int apxprobe(), apxattach(), apxstart(), apx_uprim(), apx_meminit();
4152849Ssklower int apxinit(), apxoutput(), apxioctl(), apxreset(), apxdebug = 0;
4252828Ssklower void apx_ifattach(), apxtest(), apxinput(), apxintr(), apxtint(), apxrint();
4350824Ssklower
4450824Ssklower struct apx_softc {
4550824Ssklower struct ifnet apx_if;
4652828Ssklower caddr_t apx_device; /* e.g. isa_device, vme_device, etc. */
4750824Ssklower struct apc_reg *apx_reg; /* control regs for both subunits */
4850824Ssklower struct apc_mem *apx_hmem; /* Host addr for shared memory */
4950824Ssklower struct apc_mem *apx_dmem; /* Device (chip) addr for shared mem */
5050824Ssklower struct sgcp *apx_sgcp; /* IO control port for this subunit */
5152828Ssklower int apx_flags; /* Flags specific to this driver */
5252828Ssklower #define APXF_CHIPHERE 0x01 /* mk5025 present */
5350824Ssklower int apx_rxnum; /* Last receiver dx we looked at */
5450824Ssklower int apx_txnum; /* Last tranmistter dx we stomped on */
5550824Ssklower int apx_txcnt; /* Number of packets queued for tx*/
5652848Ssklower u_int apx_msize;
5752842Ssklower struct sgae apx_csr23; /* 24 bit init addr, as seen by chip */
5852828Ssklower u_short apx_csr4; /* byte gender, set in mach dep code */
5952828Ssklower struct apc_modes apx_modes; /* Parameters, as amended by ioctls */
6052828Ssklower } apx_softc[2 * NAPX];
6150824Ssklower
6250824Ssklower struct apxstat {
6352842Ssklower int rxnull; /* no rx bufs ready this interrupt */
6452842Ssklower int rxnrdy; /* expected rx buf not ready */
6552842Ssklower int rx2big; /* expected rx buf not ready */
6652842Ssklower int txnull;
6752842Ssklower int pint; /* new primitive available interrupt */
6852842Ssklower int rint; /* receive interrupts */
6952842Ssklower int tint; /* transmit interrupts */
7052842Ssklower int anyint; /* note all interrupts */
7152842Ssklower int queued; /* got through apxinput */
7252842Ssklower int nxpctd; /* received while if was down */
7352848Ssklower int rstfld; /* reset didn't work */
7450825Ssklower } apxstat;
7550824Ssklower
7650824Ssklower /* default operating paramters for devices */
7750824Ssklower struct apc_modes apx_default_modes = {
7850824Ssklower { 1, /* apm_sgob.lsaddr; */
7950824Ssklower 3, /* apm_sgob.rsaddr; */
8050824Ssklower -SGMTU, /* apm_sgob.n1; */
8150824Ssklower ((-10)<<8), /* apm_sgob.n2_scale; */
8250824Ssklower -1250, /* apm_sgob.t1; */
8350824Ssklower -10000, /* apm_sgob.t3; */
8450824Ssklower -80, /* apm_sgob.tp; */
8550824Ssklower },
8650824Ssklower 2, /* apm_txwin; */
8752842Ssklower 1, /* apm_apxmode: RS_232 connector and modem clock; */
8852842Ssklower 0, /* apm_apxaltmode: enable dtr, disable X.21 connector; */
8950824Ssklower IFT_X25, /* apm_iftype; */
9050824Ssklower };
9150824Ssklower
9250824Ssklower /* Begin bus & endian dependence */
9350824Ssklower
9456513Sbostic #include <i386/isa/isa_device.h>
9550824Ssklower
9650824Ssklower struct isa_driver apxdriver = {
9750824Ssklower apxprobe, apxattach, "apx",
9850824Ssklower };
9950824Ssklower
10050824Ssklower #define SG_RCSR(apx, csrnum) \
10150825Ssklower (outw(&(apx->apx_sgcp->sgcp_rap), csrnum << 1), \
10250825Ssklower inw(&(apx->apx_sgcp->sgcp_rdp)))
10350824Ssklower
10450824Ssklower #define SG_WCSR(apx, csrnum, data) \
10550825Ssklower (outw(&(apx->apx_sgcp->sgcp_rap), csrnum << 1), \
10650824Ssklower outw(&(apx->apx_sgcp->sgcp_rdp), data))
10750824Ssklower
10850824Ssklower #define APX_RCSR(apx, csrname) inb(&(apx->apx_reg->csrname))
10950824Ssklower #define APX_WCSR(apx, csrname, data) outb(&(apx->apx_reg->csrname), data)
11050824Ssklower
11150824Ssklower #define TIMO 10000 /* used in apx_uprim */
11250824Ssklower
apxprobe(id)11350824Ssklower apxprobe(id)
11450824Ssklower register struct isa_device *id;
11550824Ssklower {
11655603Ssklower int moffset = 0, nchips = 2, unit = id->id_unit << 1, subunit;
11750825Ssklower struct apc_reg *reg = (struct apc_reg *)id->id_iobase;
11850824Ssklower register struct apx_softc *apx = apx_softc + unit;
11950824Ssklower
12055603Ssklower /*
12155603Ssklower * Probing for the second MK5025 on all ISA/EISA adax boards
12255603Ssklower * manufactured prior to July 1992 (and some time following)
12355603Ssklower * will hang the bus and the system. Thus, it is essential
12455603Ssklower * not to probe for the second mk5025 if it is known not to be there.
12555603Ssklower * As the current config scheme for 386BSD does not have a flags
12655603Ssklower * field, we adopt the convention of using the low order bit of
12755603Ssklower * the memsize to warn us that we have a single chip board.
12855603Ssklower */
12955603Ssklower if (id->id_msize & 1)
13055603Ssklower nchips = 1;
13155603Ssklower for (subunit = 0; subunit < nchips; subunit++) {
13252848Ssklower apx->apx_msize = id->id_msize >> 1;
13350824Ssklower apx->apx_hmem = (struct apc_mem *) (id->id_maddr + moffset);
13452848Ssklower apx->apx_dmem = (struct apc_mem *) moffset;
13552849Ssklower apx->apx_device = (caddr_t) id;
13650824Ssklower apx->apx_reg = reg;
13752828Ssklower apx->apx_sgcp = reg->axr_sgcp + subunit;
13852828Ssklower apx->apx_csr4 = 0x0210; /* no byte swapping for PC-AT */
13952828Ssklower apx->apx_modes = apx_default_modes;
14052828Ssklower apx->apx_if.if_unit = unit++;
14153099Ssklower moffset = apx->apx_msize;
14252830Ssklower apxtest(apx++);
14350824Ssklower }
14450824Ssklower return 1;
14550824Ssklower }
14650824Ssklower
14750824Ssklower apxattach(id)
14852830Ssklower struct isa_device *id;
14950824Ssklower {
15052830Ssklower register struct apx_softc *apx = apx_softc + (id->id_unit << 1);
15150824Ssklower
15252830Ssklower apx_ifattach(&((apx++)->apx_if));
15352830Ssklower apx_ifattach(&(apx->apx_if));
15452828Ssklower return 0;
15550824Ssklower }
15650824Ssklower /* End bus & endian dependence */
15750824Ssklower
15850824Ssklower /*
15950824Ssklower * Interface exists: make available by filling in network interface
16050824Ssklower * record. System will initialize the interface when it is ready
16150824Ssklower * to accept packets.
16250824Ssklower */
16350825Ssklower void
apx_ifattach(ifp)16452830Ssklower apx_ifattach(ifp)
16552830Ssklower register struct ifnet *ifp;
16650824Ssklower {
16750824Ssklower /*
16850824Ssklower * Initialize ifnet structure
16950824Ssklower */
17052828Ssklower ifp->if_name = "apc";
17152828Ssklower ifp->if_mtu = SGMTU;
17252828Ssklower ifp->if_init = apxinit;
17352828Ssklower ifp->if_output = apxoutput;
17452828Ssklower ifp->if_start = apxstart;
17552828Ssklower ifp->if_ioctl = apxioctl;
17652828Ssklower ifp->if_reset = apxreset;
17752828Ssklower ifp->if_type = apx_default_modes.apm_iftype;
17852828Ssklower ifp->if_hdrlen = 5;
17952828Ssklower ifp->if_addrlen = 8;
18050824Ssklower if_attach(ifp);
18150824Ssklower }
18250824Ssklower /*
18350824Ssklower * Initialization of interface
18450824Ssklower */
apxinit(unit)18550824Ssklower apxinit(unit)
18650824Ssklower int unit;
18750824Ssklower {
18850824Ssklower struct ifnet *ifp = &apx_softc[unit].apx_if;
18950824Ssklower int s = splimp();
19050824Ssklower
19150824Ssklower ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
19250824Ssklower if (apxreset(unit) && (ifp->if_flags & IFF_UP)) {
19350824Ssklower ifp->if_flags |= IFF_RUNNING;
19450824Ssklower (void)apxstart(ifp);
19550824Ssklower }
19650824Ssklower splx(s);
19750824Ssklower return 0;
19850824Ssklower }
19950824Ssklower
apxctr(apx)20052672Ssklower apxctr(apx)
20152672Ssklower register struct apx_softc *apx;
20252672Ssklower {
20352828Ssklower APX_WCSR(apx, axr_ccr, 0xB0); /* select ctr 2, write lsb+msb, mode 0 */
20452672Ssklower APX_WCSR(apx, axr_cnt2, 0x1);
20552672Ssklower APX_WCSR(apx, axr_cnt2, 0x0);
20652672Ssklower DELAY(50);
20752828Ssklower APX_WCSR(apx, axr_ccr, 0xE8); /* latch status, ctr 2; */
20852828Ssklower return (APX_RCSR(apx, axr_cnt2));
20952672Ssklower }
21052672Ssklower
21152828Ssklower void
apxtest(apx)21252828Ssklower apxtest(apx)
21352828Ssklower register struct apx_softc *apx;
21452828Ssklower {
21552828Ssklower int i = 0;
21652828Ssklower
21752828Ssklower if ((apx->apx_if.if_unit & 1) == 0 && (i = apxctr(apx)) == 0)
21852828Ssklower apxerror(apx, "no response from timer chip", 0);
21952828Ssklower if (SG_RCSR(apx, 1) & 0x8000)
22052828Ssklower SG_WCSR(apx, 1, 0x8040);
22152828Ssklower SG_WCSR(apx, 4, apx->apx_csr4);
22252828Ssklower SG_WCSR(apx, 5, 0x08); /* Set DTR mode in SGS thompson chip */
22352828Ssklower if (((i = SG_RCSR(apx, 5)) & 0xff08) != 0x08)
22452828Ssklower apxerror(apx, "no mk5025, csr5 high bits are", i);
22552828Ssklower else
22652828Ssklower apx->apx_flags |= APXF_CHIPHERE;
22752842Ssklower (void) apx_uprim(apx, SG_STOP, "stop after probing");
22852828Ssklower }
22952828Ssklower
apxreset(unit)23050824Ssklower apxreset(unit)
23150824Ssklower int unit;
23250824Ssklower {
23350824Ssklower register struct apx_softc *apx = &apx_softc[unit ^ 1];
23450824Ssklower u_char apm_apxmode = 0, apm_apxaltmode = 0;
23550824Ssklower #define MODE(m) (m |= apx->apx_modes.m << ((apx->apx_if.if_unit & 1) ? 1 : 0))
23650824Ssklower
23750824Ssklower MODE(apm_apxmode);
23850824Ssklower MODE(apm_apxaltmode);
23950824Ssklower apx = apx_softc + unit;
24050824Ssklower MODE(apm_apxmode);
24150824Ssklower MODE(apm_apxaltmode);
24250824Ssklower APX_WCSR(apx, axr_mode, apm_apxmode);
24350824Ssklower APX_WCSR(apx, axr_altmode, apm_apxaltmode);
24452842Ssklower (void) apxctr(apx);
24552842Ssklower (void) apx_uprim(apx, SG_STOP, "stop to reset");
24652842Ssklower if ((apx->apx_if.if_flags & IFF_UP) == 0)
24750824Ssklower return 0;
24852842Ssklower apx_meminit(apx->apx_hmem, apx);
24950824Ssklower SG_WCSR(apx, 4, apx->apx_csr4);
25052842Ssklower SG_WCSR(apx, 2, apx->apx_csr23.f_hi);
25152842Ssklower SG_WCSR(apx, 3, apx->apx_csr23.lo);
25250825Ssklower if (apx_uprim(apx, SG_INIT, "init request") ||
25350824Ssklower apx_uprim(apx, SG_STAT, "status request") ||
25452849Ssklower apx_uprim(apx, SG_TRANS, "transparent mode"))
25550824Ssklower return 0;
25650824Ssklower SG_WCSR(apx, 0, SG_INEA);
25750825Ssklower return 1;
25850824Ssklower }
25950824Ssklower
apx_uprim(apx,request,ident)26050824Ssklower apx_uprim(apx, request, ident)
26152830Ssklower register struct apx_softc *apx;
26250824Ssklower char *ident;
26350824Ssklower {
26450824Ssklower register int timo = 0;
26552830Ssklower int reply;
26650824Ssklower
26752830Ssklower if ((apx->apx_flags & APXF_CHIPHERE) == 0)
26852830Ssklower return 1; /* maybe even should panic . . . */
26952830Ssklower if ((reply = SG_RCSR(apx, 1)) & 0x8040)
27052828Ssklower SG_WCSR(apx, 1, 0x8040); /* Magic! */
27152849Ssklower if (request == SG_STOP && (SG_RCSR(apx, 0) & SG_STOPPED))
27252848Ssklower return 0;
27350824Ssklower SG_WCSR(apx, 1, request | SG_UAV);
27450824Ssklower do {
27552849Ssklower reply = SG_RCSR(apx, 1);
27652842Ssklower if (timo++ >= TIMO || (reply & 0x8000)) {
27752842Ssklower apxerror(apx, ident, reply);
27852842Ssklower return 1;
27950824Ssklower }
28050824Ssklower } while (reply & SG_UAV);
28150824Ssklower return 0;
28250824Ssklower }
28350824Ssklower
apx_meminit(apc,apx)28450824Ssklower apx_meminit(apc, apx)
28550824Ssklower register struct apc_mem *apc;
28650824Ssklower struct apx_softc *apx;
28750824Ssklower {
28850824Ssklower register struct apc_mem *apcbase = apx->apx_dmem;
28950824Ssklower register int i;
29050825Ssklower #define LOWADDR(e) (((u_long)&(apcbase->e)) & 0xffff)
29150825Ssklower #define HIADDR(e) ((((u_long)&(apcbase->e)) >> 16) & 0xff)
29252842Ssklower #define SET_SGAE(d, f, a) {(d).lo = LOWADDR(a); (d).f_hi = (f) | HIADDR(a);}
29352842Ssklower #define SET_SGDX(d, f, a, b) \
29452842Ssklower {SET_SGAE((d).sgdx_ae, f, a); (d).sgdx_mcnt = (d).sgdx_bcnt = (b);}
29550824Ssklower
29652842Ssklower apx->apx_txnum = apx->apx_rxnum = apx->apx_txcnt = 0;
29752849Ssklower bzero((caddr_t)apc, ((caddr_t)(&apc->apc_rxmd[0])) - (caddr_t)apc);
29852849Ssklower apc->apc_mode = 0x0108; /* 2 flag spacing, leave addr & ctl, do CRC16 */
29950824Ssklower apc->apc_sgop = apx->apx_modes.apm_sgop;
30052842Ssklower SET_SGAE(apx->apx_csr23, SG_UIE | SG_PROM, apc_mode);
30152842Ssklower SET_SGAE(apc->apc_rxdd, SG_RLEN, apc_rxmd[0]);
30252848Ssklower i = SG_TLEN | ((apx->apx_modes.apm_txwin)<< 8);
30352848Ssklower SET_SGAE(apc->apc_txdd, i, apc_txmd[0]);
30452842Ssklower SET_SGAE(apc->apc_stdd, 0, apc_sgsb);
30552842Ssklower SET_SGDX(apc->apc_rxtid, SG_OWN, apc_rxidbuf[0], -SGMTU);
30652842Ssklower SET_SGDX(apc->apc_txtid, 0, apc_txidbuf[0], 0);
30750824Ssklower for (i = 0; i < SGRBUF; i++)
30852842Ssklower SET_SGDX(apc->apc_rxmd[i], SG_OWN, apc_rbuf[i][0], -SGMTU)
30950824Ssklower for (i = 0; i < SGTBUF; i++)
31052848Ssklower SET_SGDX(apc->apc_txmd[i], 0, apc_tbuf[i][0], 0)
31150824Ssklower }
31250824Ssklower
31350824Ssklower /*
31450824Ssklower * Start output on interface. Get another datagram to send
31550824Ssklower * off of the interface queue, and copy it to the interface
31650824Ssklower * before starting the output.
31750824Ssklower */
31850824Ssklower apxstart(ifp)
31950824Ssklower struct ifnet *ifp;
32050824Ssklower {
32150824Ssklower register struct apx_softc *apx = &apx_softc[ifp->if_unit];
32250824Ssklower register struct sgdx *dx;
32350825Ssklower struct apc_mem *apc = apx->apx_hmem;
32450824Ssklower struct mbuf *m;
32550824Ssklower int len;
32650824Ssklower
32750824Ssklower if ((ifp->if_flags & IFF_RUNNING) == 0)
32850824Ssklower return (0);
32950824Ssklower do {
33050825Ssklower dx = apc->apc_txmd + apx->apx_txnum;
33150824Ssklower if (dx->sgdx_flags & SG_OWN)
33250824Ssklower return (0);
33350824Ssklower IF_DEQUEUE(&ifp->if_snd, m);
33450824Ssklower if (m == 0)
33550824Ssklower return (0);
33650824Ssklower len = min(m->m_pkthdr.len, SGMTU);
33750825Ssklower m_copydata(m, 0, len, apc->apc_tbuf[apx->apx_txnum]);
33855603Ssklower m_freem(m);
33950824Ssklower dx->sgdx_mcnt = -len;
34052842Ssklower dx->sgdx_flags = (SG_OWN|SG_TUI|SG_SLF|SG_ELF) |
34152842Ssklower (0xff & dx->sgdx_flags);
34250824Ssklower SG_WCSR(apx, 0, SG_INEA | SG_TDMD);
34352848Ssklower DELAY(20);
34450824Ssklower if (++apx->apx_txnum >= SGTBUF)
34550824Ssklower apx->apx_txnum = 0;
34650824Ssklower } while (++apx->apx_txcnt < SGTBUF);
34752830Ssklower apx->apx_txcnt = SGTBUF; /* in case txcnt > SGTBUF by mistake */
34850824Ssklower ifp->if_flags |= IFF_OACTIVE;
34950824Ssklower return (0);
35050824Ssklower }
35150824Ssklower
35250825Ssklower void
apxintr()35350824Ssklower apxintr()
35450824Ssklower {
35552828Ssklower register struct apx_softc *apx;
35650824Ssklower int reply;
35750824Ssklower
35852842Ssklower apxstat.anyint++;
35952828Ssklower for (apx = apx_softc + NAPX + NAPX; --apx >= apx_softc;) {
36052828Ssklower if (apx->apx_flags & APXF_CHIPHERE)
36150824Ssklower /* Try to turn off interrupt cause */
36252849Ssklower while ((reply = SG_RCSR(apx, 0)) & 0xff) {
36350824Ssklower SG_WCSR(apx, 0, SG_INEA | 0xfe);
36450824Ssklower if (reply & (SG_MERR|SG_TUR|SG_ROR)) {
36550824Ssklower apxerror(apx, "mem, rx, or tx error", reply);
36650824Ssklower apxinit(apx->apx_if.if_unit);
36750824Ssklower break;
36850824Ssklower }
36950824Ssklower if (reply & SG_RINT)
37050824Ssklower apxrint(apx);
37150824Ssklower if (reply & SG_TINT)
37250824Ssklower apxtint(apx);
37350824Ssklower if (reply & SG_PINT)
37450824Ssklower apxstat.pint++;
37550824Ssklower }
37652828Ssklower }
37750824Ssklower }
37850824Ssklower
37950825Ssklower void
apxtint(apx)38050824Ssklower apxtint(apx)
38150824Ssklower register struct apx_softc *apx;
38250824Ssklower {
38350825Ssklower register struct apc_mem *apc = apx->apx_hmem;
38450824Ssklower int i, loopcount = 0;
38550824Ssklower
38652842Ssklower apxstat.tint++;
38750824Ssklower do {
38850824Ssklower if ((i = apx->apx_txnum - apx->apx_txcnt) < 0)
38950824Ssklower i += SGTBUF;
39050824Ssklower if (apc->apc_txmd[i].sgdx_flags & SG_OWN) {
39150824Ssklower if (loopcount)
39250824Ssklower break;
39352842Ssklower apxstat.txnull++;
39450824Ssklower return;
39550824Ssklower }
39650824Ssklower loopcount++;
39750824Ssklower apx->apx_if.if_flags &= ~IFF_OACTIVE;
39850824Ssklower } while (--apx->apx_txcnt > 0);
39950824Ssklower apxstart(&apx->apx_if);
40050824Ssklower }
40150824Ssklower
40252828Ssklower void
apxrint(apx)40350824Ssklower apxrint(apx)
40450824Ssklower register struct apx_softc *apx;
40550824Ssklower {
40650825Ssklower register struct apc_mem *apc = apx->apx_hmem;
40750824Ssklower register struct sgdx *dx = apc->apc_rxmd + apx->apx_rxnum;
40852842Ssklower int i = 0;
40950824Ssklower #define SGNEXTRXMD \
41050824Ssklower dx = ++apx->apx_rxnum == SGRBUF ? &apc->apc_rxmd[apx->apx_rxnum = 0] : dx + 1;
41150824Ssklower
41252842Ssklower apxstat.rint++;
41350824Ssklower /*
41450824Ssklower * Out of sync with hardware, should never happen?
41550824Ssklower */
41652842Ssklower while (dx->sgdx_flags & SG_OWN) {
41752842Ssklower apxstat.rxnrdy++;
41852842Ssklower if (++i == SGRBUF) {
41952842Ssklower apxstat.rxnull++;
42052842Ssklower return;
42152842Ssklower }
42252842Ssklower SGNEXTRXMD;
42350824Ssklower }
42450824Ssklower /*
42550824Ssklower * Process all buffers with valid data
42650824Ssklower */
42750824Ssklower while ((dx->sgdx_flags & SG_OWN) == 0) {
42850824Ssklower if ((dx->sgdx_flags & (SG_SLF|SG_ELF)) != (SG_SLF|SG_ELF)) {
42950824Ssklower /*
43052842Ssklower * Find the end of the packet so we synch up.
43152842Ssklower * We throw the data away.
43250824Ssklower */
43350825Ssklower apxerror(apx, "chained buffer", dx->sgdx_flags);
43450824Ssklower do {
43552842Ssklower apxstat.rx2big++;
43650824Ssklower dx->sgdx_bcnt = 0;
43750824Ssklower dx->sgdx_flags = SG_OWN | (0xff&dx->sgdx_flags);
43850824Ssklower SGNEXTRXMD;
43950824Ssklower } while (!(dx->sgdx_flags & (SG_OWN|SG_SLF|SG_ELF)));
44050824Ssklower /*
44150824Ssklower * If search terminated without successful completion
44250824Ssklower * we reset the hardware (conservative).
44350824Ssklower */
44450824Ssklower if ((dx->sgdx_flags & (SG_OWN|SG_SLF|SG_ELF)) !=
44550825Ssklower SG_ELF) {
44650824Ssklower apxreset(apx->apx_if.if_unit);
44750824Ssklower return;
44850824Ssklower }
44950824Ssklower } else
45050824Ssklower apxinput(&apx->apx_if, apc->apc_rbuf[apx->apx_rxnum],
45152842Ssklower -dx->sgdx_mcnt);
45250824Ssklower dx->sgdx_bcnt = 0;
45350824Ssklower dx->sgdx_flags = SG_OWN | (0xff & dx->sgdx_flags);
45450824Ssklower SGNEXTRXMD;
45550824Ssklower }
45650824Ssklower }
45750824Ssklower
45850825Ssklower void
apxinput(ifp,buffer,len)45950824Ssklower apxinput(ifp, buffer, len)
46052830Ssklower register struct ifnet *ifp;
46152830Ssklower caddr_t buffer;
46250824Ssklower {
46352830Ssklower extern struct ifqueue hdintrq, ipintrq;
46450824Ssklower register struct ifqueue *inq;
46552830Ssklower register u_char *cp = (u_char *)buffer;
46652672Ssklower struct mbuf *m, *m_devget();
46750824Ssklower int isr;
46850824Ssklower
46950824Ssklower ifp->if_ipackets++;
47052842Ssklower if ((ifp->if_flags & IFF_UP) == 0) {
47152842Ssklower apxstat.nxpctd++;
47252842Ssklower return;
47352842Ssklower }
47450824Ssklower if (cp[0] == 0xff && cp[1] == 0x3) {
47550824Ssklower /* This is a UI HDLC Packet, so we'll assume PPP
47650824Ssklower protocol. for now, IP only. */
47750824Ssklower buffer += 4;
47850824Ssklower len -= 4;
47950824Ssklower inq = &ipintrq;
48050824Ssklower isr = NETISR_IP;
48150824Ssklower } else {
48252830Ssklower #ifdef CCITT
48350824Ssklower inq = &hdintrq;
48450824Ssklower isr = NETISR_CCITT;
48550824Ssklower }
48652830Ssklower if (len <= 0) {
48752830Ssklower #endif
48850824Ssklower return;
48952830Ssklower }
49052672Ssklower m = m_devget(buffer, len, 0, ifp, (void (*)())0);
49150824Ssklower if (m == 0)
49250824Ssklower return;
49350824Ssklower if(IF_QFULL(inq)) {
49450824Ssklower IF_DROP(inq);
49550824Ssklower m_freem(m);
49650824Ssklower } else {
49752842Ssklower apxstat.queued++;
49850824Ssklower IF_ENQUEUE(inq, m);
49950824Ssklower schednetisr(isr);
50050824Ssklower }
50150824Ssklower }
50250824Ssklower
50350824Ssklower /*
50450824Ssklower * Process an ioctl request.
50550824Ssklower */
apxioctl(ifp,cmd,data)50650824Ssklower apxioctl(ifp, cmd, data)
50750824Ssklower register struct ifnet *ifp;
50850824Ssklower int cmd;
50950824Ssklower caddr_t data;
51050824Ssklower {
51150824Ssklower register struct ifaddr *ifa = (struct ifaddr *)data;
51250824Ssklower int s = splimp(), error = 0;
51350824Ssklower struct apx_softc *apx = &apx_softc[ifp->if_unit];
51450824Ssklower
51550824Ssklower switch (cmd) {
51652828Ssklower
51752828Ssklower case SIOCSIFADDR:
51852828Ssklower #ifdef CCITT
51952849Ssklower ifa->ifa_rtrequest = x25_rtrequest;
52052828Ssklower break;
52152828Ssklower
52250824Ssklower case SIOCSIFCONF_X25:
52352828Ssklower ifp->if_output = x25_ifoutput;
52450824Ssklower ifp->if_flags |= IFF_UP;
52550824Ssklower error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr);
52650824Ssklower if (error == 0)
52750824Ssklower apxinit(ifp->if_unit);
52852828Ssklower #endif
52950824Ssklower break;
53050824Ssklower
53150824Ssklower case SIOCSIFFLAGS:
53250824Ssklower if (((ifp->if_flags & IFF_UP) == 0 &&
53350824Ssklower (ifp->if_flags & IFF_RUNNING)) ||
53450824Ssklower (ifp->if_flags & IFF_UP) &&
53550824Ssklower (ifp->if_flags & IFF_RUNNING) == 0)
53650824Ssklower apxinit(ifp->if_unit);
53750824Ssklower break;
53850824Ssklower
53950824Ssklower case SIOCSIFMODE:
54050824Ssklower if ((ifp->if_flags & IFF_UP) == 0)
54150825Ssklower apx->apx_modes = *(struct apc_modes *)data;
54250824Ssklower else
54350824Ssklower default:
54450824Ssklower error = EINVAL;
54550824Ssklower
54650824Ssklower }
54750824Ssklower splx(s);
54850824Ssklower return (error);
54950824Ssklower }
55050824Ssklower
apxerror(apx,msg,data)55150824Ssklower apxerror(apx, msg, data)
55250824Ssklower register struct apx_softc *apx;
55350824Ssklower char *msg;
55450824Ssklower {
55550824Ssklower log(LOG_WARNING, "apc%d: %s, stat=0x%x\n",
55650824Ssklower apx->apx_if.if_unit, msg, data);
55750824Ssklower }
55852849Ssklower
55952828Ssklower /*
56052828Ssklower * For debugging loopback activity.
56152828Ssklower */
apxoutput(ifp,m,dst,rt)56252828Ssklower apxoutput(ifp, m, dst, rt)
56352828Ssklower register struct ifnet *ifp;
56452828Ssklower register struct mbuf *m;
56552828Ssklower struct sockaddr *dst;
56652828Ssklower struct rtentry *rt;
56752828Ssklower {
56852849Ssklower int s = splimp(), error = 0;
56952849Ssklower static char pppheader[4] = { -1, 3, 0, 0x21 };
57052828Ssklower /*
57152828Ssklower * Queue message on interface, and start output if interface
57252828Ssklower * not yet active.
57352828Ssklower */
57452849Ssklower ifp->if_opackets++;
57552828Ssklower M_PREPEND(m, sizeof pppheader, M_DONTWAIT);
57652828Ssklower if (m == 0) {
57752828Ssklower splx(s);
57852828Ssklower return ENOBUFS;
57952828Ssklower }
58052828Ssklower bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader);
58152828Ssklower if (IF_QFULL(&ifp->if_snd)) {
58252828Ssklower IF_DROP(&ifp->if_snd);
58352828Ssklower m_freem(m);
58452828Ssklower error = ENOBUFS;
58552828Ssklower } else {
58652828Ssklower IF_ENQUEUE(&ifp->if_snd, m);
58752828Ssklower if ((ifp->if_flags & IFF_OACTIVE) == 0)
58852828Ssklower (*ifp->if_start)(ifp);
58952828Ssklower }
59052828Ssklower splx(s);
59152828Ssklower return (error);
59252828Ssklower }
59350824Ssklower #endif /* NAPX */
594