150824Ssklower /* 250824Ssklower * Copyright (c) 1982, 1990 The Regents of the University of California. 350824Ssklower * All rights reserved. 450824Ssklower * 550824Ssklower * %sccs.include.redist.c% 650824Ssklower * 7*55603Ssklower * @(#)if_apx.c 7.10 (Berkeley) 07/23/92 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 2350824Ssklower #include "param.h" 2450824Ssklower #include "mbuf.h" 2550824Ssklower #include "socket.h" 2650824Ssklower #include "ioctl.h" 2750824Ssklower #include "errno.h" 2850824Ssklower #include "syslog.h" 2950824Ssklower 3050824Ssklower #include "net/if.h" 3150824Ssklower #include "net/netisr.h" 3250825Ssklower #include "net/if_types.h" 3352828Ssklower #ifdef CCITT 3450824Ssklower #include "netccitt/x25.h" 3552828Ssklower int x25_rtrequest(), x25_ifoutput(); 3652828Ssklower #endif 3750824Ssklower 3850825Ssklower #include "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 9450825Ssklower #include "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 11350824Ssklower apxprobe(id) 11450824Ssklower register struct isa_device *id; 11550824Ssklower { 116*55603Ssklower 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 120*55603Ssklower /* 121*55603Ssklower * Probing for the second MK5025 on all ISA/EISA adax boards 122*55603Ssklower * manufactured prior to July 1992 (and some time following) 123*55603Ssklower * will hang the bus and the system. Thus, it is essential 124*55603Ssklower * not to probe for the second mk5025 if it is known not to be there. 125*55603Ssklower * As the current config scheme for 386BSD does not have a flags 126*55603Ssklower * field, we adopt the convention of using the low order bit of 127*55603Ssklower * the memsize to warn us that we have a single chip board. 128*55603Ssklower */ 129*55603Ssklower if (id->id_msize & 1) 130*55603Ssklower nchips = 1; 131*55603Ssklower 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 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 */ 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 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 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 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 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 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]); 338*55603Ssklower 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 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 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 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 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 */ 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 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 */ 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