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*52848Ssklower * @(#)if_apx.c 7.7 (Berkeley) 03/05/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(); 36*52848Ssklower struct mbuf_cache { 37*52848Ssklower int mbc_size; 38*52848Ssklower int mbc_num; 39*52848Ssklower int mbc_oldsize; 40*52848Ssklower struct mbuf **mbc_cache; 41*52848Ssklower } apx_cache = { 20 }; 4252828Ssklower #endif 4350824Ssklower 4450825Ssklower #include "if_apxreg.h" 4550824Ssklower 4650824Ssklower int apxprobe(), apxattach(), apxstart(), apx_uprim(), apx_meminit(); 4752828Ssklower int apxinit(), apxoutput(), apxioctl(), apxreset(), apxdebug = 1; 4852828Ssklower void apx_ifattach(), apxtest(), apxinput(), apxintr(), apxtint(), apxrint(); 49*52848Ssklower int apxipdebug = 1; 5050824Ssklower 5150824Ssklower struct apx_softc { 5250824Ssklower struct ifnet apx_if; 5352828Ssklower caddr_t apx_device; /* e.g. isa_device, vme_device, etc. */ 5450824Ssklower struct apc_reg *apx_reg; /* control regs for both subunits */ 5550824Ssklower struct apc_mem *apx_hmem; /* Host addr for shared memory */ 5650824Ssklower struct apc_mem *apx_dmem; /* Device (chip) addr for shared mem */ 5750824Ssklower struct sgcp *apx_sgcp; /* IO control port for this subunit */ 5852828Ssklower int apx_flags; /* Flags specific to this driver */ 5952828Ssklower #define APXF_CHIPHERE 0x01 /* mk5025 present */ 6050824Ssklower int apx_rxnum; /* Last receiver dx we looked at */ 6150824Ssklower int apx_txnum; /* Last tranmistter dx we stomped on */ 6250824Ssklower int apx_txcnt; /* Number of packets queued for tx*/ 63*52848Ssklower u_int apx_msize; 64*52848Ssklower u_short apx_csr0; 65*52848Ssklower u_short apx_csr1; 6652842Ssklower struct sgae apx_csr23; /* 24 bit init addr, as seen by chip */ 6752828Ssklower u_short apx_csr4; /* byte gender, set in mach dep code */ 6852828Ssklower struct apc_modes apx_modes; /* Parameters, as amended by ioctls */ 6952828Ssklower } apx_softc[2 * NAPX]; 7050824Ssklower 7150824Ssklower struct apxstat { 7252842Ssklower int rxnull; /* no rx bufs ready this interrupt */ 7352842Ssklower int rxnrdy; /* expected rx buf not ready */ 7452842Ssklower int rx2big; /* expected rx buf not ready */ 7552842Ssklower int txnull; 7652842Ssklower int pint; /* new primitive available interrupt */ 7752842Ssklower int rint; /* receive interrupts */ 7852842Ssklower int tint; /* transmit interrupts */ 7952842Ssklower int anyint; /* note all interrupts */ 8052842Ssklower int queued; /* got through apxinput */ 8152842Ssklower int nxpctd; /* received while if was down */ 82*52848Ssklower int rstfld; /* reset didn't work */ 8350825Ssklower } apxstat; 8450824Ssklower 8550824Ssklower /* default operating paramters for devices */ 8650824Ssklower struct apc_modes apx_default_modes = { 8750824Ssklower { 1, /* apm_sgob.lsaddr; */ 8850824Ssklower 3, /* apm_sgob.rsaddr; */ 8950824Ssklower -SGMTU, /* apm_sgob.n1; */ 9050824Ssklower ((-10)<<8), /* apm_sgob.n2_scale; */ 9150824Ssklower -1250, /* apm_sgob.t1; */ 9250824Ssklower -10000, /* apm_sgob.t3; */ 9350824Ssklower -80, /* apm_sgob.tp; */ 9450824Ssklower }, 9550824Ssklower 2, /* apm_txwin; */ 9652842Ssklower 1, /* apm_apxmode: RS_232 connector and modem clock; */ 9752842Ssklower 0, /* apm_apxaltmode: enable dtr, disable X.21 connector; */ 9850824Ssklower IFT_X25, /* apm_iftype; */ 9950824Ssklower }; 10050824Ssklower 10150824Ssklower /* Begin bus & endian dependence */ 10250824Ssklower 10350825Ssklower #include "isa_device.h" 10450824Ssklower 10550824Ssklower struct isa_driver apxdriver = { 10650824Ssklower apxprobe, apxattach, "apx", 10750824Ssklower }; 10850824Ssklower 10950824Ssklower #define SG_RCSR(apx, csrnum) \ 11050825Ssklower (outw(&(apx->apx_sgcp->sgcp_rap), csrnum << 1), \ 11150825Ssklower inw(&(apx->apx_sgcp->sgcp_rdp))) 11250824Ssklower 11350824Ssklower #define SG_WCSR(apx, csrnum, data) \ 11450825Ssklower (outw(&(apx->apx_sgcp->sgcp_rap), csrnum << 1), \ 11550824Ssklower outw(&(apx->apx_sgcp->sgcp_rdp), data)) 11650824Ssklower 11750824Ssklower #define APX_RCSR(apx, csrname) inb(&(apx->apx_reg->csrname)) 11850824Ssklower #define APX_WCSR(apx, csrname, data) outb(&(apx->apx_reg->csrname), data) 11950824Ssklower 12050824Ssklower #define TIMO 10000 /* used in apx_uprim */ 12150824Ssklower 12250824Ssklower apxprobe(id) 12350824Ssklower register struct isa_device *id; 12450824Ssklower { 125*52848Ssklower int moffset = 0, subunit, unit = id->id_unit << 1; 12650825Ssklower struct apc_reg *reg = (struct apc_reg *)id->id_iobase; 12750824Ssklower register struct apx_softc *apx = apx_softc + unit; 12850824Ssklower 12952830Ssklower for (subunit = 0; subunit < 2; subunit++) { 130*52848Ssklower apx->apx_msize = id->id_msize >> 1; 13150824Ssklower apx->apx_hmem = (struct apc_mem *) (id->id_maddr + moffset); 132*52848Ssklower apx->apx_dmem = (struct apc_mem *) moffset; 13350824Ssklower apx->apx_device = (caddr_t) id; 13450824Ssklower apx->apx_reg = reg; 13552828Ssklower apx->apx_sgcp = reg->axr_sgcp + subunit; 13652828Ssklower apx->apx_csr4 = 0x0210; /* no byte swapping for PC-AT */ 13752828Ssklower apx->apx_modes = apx_default_modes; 13852828Ssklower apx->apx_if.if_unit = unit++; 13952830Ssklower apxtest(apx++); 140*52848Ssklower moffset = apx->apx_msize; 14150824Ssklower } 14250824Ssklower return 1; 14350824Ssklower } 14450824Ssklower 14550824Ssklower apxattach(id) 14652830Ssklower struct isa_device *id; 14750824Ssklower { 14852830Ssklower register struct apx_softc *apx = apx_softc + (id->id_unit << 1); 14950824Ssklower 15052830Ssklower apx_ifattach(&((apx++)->apx_if)); 15152830Ssklower apx_ifattach(&(apx->apx_if)); 15252828Ssklower return 0; 15350824Ssklower } 15450824Ssklower /* End bus & endian dependence */ 15550824Ssklower 15650824Ssklower /* 15750824Ssklower * Interface exists: make available by filling in network interface 15850824Ssklower * record. System will initialize the interface when it is ready 15950824Ssklower * to accept packets. 16050824Ssklower */ 16150825Ssklower void 16252830Ssklower apx_ifattach(ifp) 16352830Ssklower register struct ifnet *ifp; 16450824Ssklower { 16550824Ssklower /* 16650824Ssklower * Initialize ifnet structure 16750824Ssklower */ 16852828Ssklower ifp->if_name = "apc"; 16952828Ssklower ifp->if_mtu = SGMTU; 17052828Ssklower ifp->if_init = apxinit; 17152828Ssklower ifp->if_output = apxoutput; 17252828Ssklower ifp->if_start = apxstart; 17352828Ssklower ifp->if_ioctl = apxioctl; 17452828Ssklower ifp->if_reset = apxreset; 17552828Ssklower ifp->if_type = apx_default_modes.apm_iftype; 17652828Ssklower ifp->if_hdrlen = 5; 17752828Ssklower ifp->if_addrlen = 8; 17850824Ssklower if_attach(ifp); 17950824Ssklower } 18050824Ssklower /* 18150824Ssklower * Initialization of interface 18250824Ssklower */ 18350824Ssklower apxinit(unit) 18450824Ssklower int unit; 18550824Ssklower { 18650824Ssklower struct ifnet *ifp = &apx_softc[unit].apx_if; 18750824Ssklower int s = splimp(); 18850824Ssklower 18950824Ssklower ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 19050824Ssklower if (apxreset(unit) && (ifp->if_flags & IFF_UP)) { 19150824Ssklower ifp->if_flags |= IFF_RUNNING; 19250824Ssklower (void)apxstart(ifp); 19350824Ssklower } 19450824Ssklower splx(s); 19550824Ssklower return 0; 19650824Ssklower } 19750824Ssklower 19852672Ssklower apxctr(apx) 19952672Ssklower register struct apx_softc *apx; 20052672Ssklower { 20152828Ssklower APX_WCSR(apx, axr_ccr, 0xB0); /* select ctr 2, write lsb+msb, mode 0 */ 20252672Ssklower APX_WCSR(apx, axr_cnt2, 0x1); 20352672Ssklower APX_WCSR(apx, axr_cnt2, 0x0); 20452672Ssklower DELAY(50); 20552828Ssklower APX_WCSR(apx, axr_ccr, 0xE8); /* latch status, ctr 2; */ 20652828Ssklower return (APX_RCSR(apx, axr_cnt2)); 20752672Ssklower } 20852672Ssklower 20952828Ssklower void 21052828Ssklower apxtest(apx) 21152828Ssklower register struct apx_softc *apx; 21252828Ssklower { 21352828Ssklower int i = 0; 21452828Ssklower 21552828Ssklower if ((apx->apx_if.if_unit & 1) == 0 && (i = apxctr(apx)) == 0) 21652828Ssklower apxerror(apx, "no response from timer chip", 0); 21752828Ssklower if (SG_RCSR(apx, 1) & 0x8000) 21852828Ssklower SG_WCSR(apx, 1, 0x8040); 21952828Ssklower SG_WCSR(apx, 4, apx->apx_csr4); 22052828Ssklower if (apxdebug && i) { 22152828Ssklower apxerror(apx, "counter 2 value", i); 22252828Ssklower apxerror(apx, "mk5025 csr4 value", SG_RCSR(apx, 4)); 22352828Ssklower } 22452828Ssklower SG_WCSR(apx, 5, 0x08); /* Set DTR mode in SGS thompson chip */ 22552828Ssklower if (((i = SG_RCSR(apx, 5)) & 0xff08) != 0x08) 22652828Ssklower apxerror(apx, "no mk5025, csr5 high bits are", i); 22752828Ssklower else 22852828Ssklower apx->apx_flags |= APXF_CHIPHERE; 22952842Ssklower (void) apx_uprim(apx, SG_STOP, "stop after probing"); 23052828Ssklower } 23152828Ssklower 23250824Ssklower apxreset(unit) 23350824Ssklower int unit; 23450824Ssklower { 23550824Ssklower register struct apx_softc *apx = &apx_softc[unit ^ 1]; 23650824Ssklower u_char apm_apxmode = 0, apm_apxaltmode = 0; 23750824Ssklower #define MODE(m) (m |= apx->apx_modes.m << ((apx->apx_if.if_unit & 1) ? 1 : 0)) 23850824Ssklower 23950824Ssklower MODE(apm_apxmode); 24050824Ssklower MODE(apm_apxaltmode); 24150824Ssklower apx = apx_softc + unit; 24250824Ssklower MODE(apm_apxmode); 24350824Ssklower MODE(apm_apxaltmode); 24450824Ssklower APX_WCSR(apx, axr_mode, apm_apxmode); 24550824Ssklower APX_WCSR(apx, axr_altmode, apm_apxaltmode); 24652842Ssklower (void) apxctr(apx); 24752842Ssklower (void) apx_uprim(apx, SG_STOP, "stop to reset"); 24852842Ssklower if ((apx->apx_if.if_flags & IFF_UP) == 0) 24950824Ssklower return 0; 25052842Ssklower apx_meminit(apx->apx_hmem, apx); 25150824Ssklower SG_WCSR(apx, 4, apx->apx_csr4); 25252842Ssklower SG_WCSR(apx, 2, apx->apx_csr23.f_hi); 25352842Ssklower SG_WCSR(apx, 3, apx->apx_csr23.lo); 25450825Ssklower if (apx_uprim(apx, SG_INIT, "init request") || 25550824Ssklower apx_uprim(apx, SG_STAT, "status request") || 256*52848Ssklower apx_uprim(apx, SG_TRANS, "transparent mode")) { 257*52848Ssklower apxstat.rstfld++; 25850824Ssklower return 0; 259*52848Ssklower } 26050824Ssklower SG_WCSR(apx, 0, SG_INEA); 26150825Ssklower return 1; 26250824Ssklower } 26352842Ssklower int apx_doinit = 1, apx_dostat = 1; 26452842Ssklower int apx_didinit = 0, apx_didstat = 0; 26550824Ssklower 26650824Ssklower apx_uprim(apx, request, ident) 26752830Ssklower register struct apx_softc *apx; 26850824Ssklower char *ident; 26950824Ssklower { 27050824Ssklower register int timo = 0; 27152830Ssklower int reply; 27250824Ssklower 27352830Ssklower if ((apx->apx_flags & APXF_CHIPHERE) == 0) 27452830Ssklower return 1; /* maybe even should panic . . . */ 27552842Ssklower 27652842Ssklower if (request == SG_STAT) { if (apx_dostat) apx_didstat = 1; else return 0;} 27752842Ssklower if (request == SG_INIT) { if (apx_doinit) apx_didinit = 1; else return 0;} 27852842Ssklower 27952830Ssklower if ((reply = SG_RCSR(apx, 1)) & 0x8040) 28052828Ssklower SG_WCSR(apx, 1, 0x8040); /* Magic! */ 281*52848Ssklower apx->apx_csr0 = SG_RCSR(apx, 0); 282*52848Ssklower if (request == SG_STOP && (apx->apx_csr0 & SG_STOPPED)) 283*52848Ssklower return 0; 28450824Ssklower SG_WCSR(apx, 1, request | SG_UAV); 28550824Ssklower do { 286*52848Ssklower apx->apx_csr1 = reply = SG_RCSR(apx, 1); 28752842Ssklower if (timo++ >= TIMO || (reply & 0x8000)) { 28852842Ssklower if (request != SG_STOP || apxdebug) 28952842Ssklower apxerror(apx, ident, reply); 29052842Ssklower if (request != SG_STOP) 29152842Ssklower return 1; 29250824Ssklower } 29350824Ssklower } while (reply & SG_UAV); 294*52848Ssklower apx->apx_csr0 = SG_RCSR(apx, 0); 29550824Ssklower return 0; 29650824Ssklower } 29750824Ssklower 29850824Ssklower apx_meminit(apc, apx) 29950824Ssklower register struct apc_mem *apc; 30050824Ssklower struct apx_softc *apx; 30150824Ssklower { 30250824Ssklower register struct apc_mem *apcbase = apx->apx_dmem; 30350824Ssklower register int i; 30450825Ssklower #define LOWADDR(e) (((u_long)&(apcbase->e)) & 0xffff) 30550825Ssklower #define HIADDR(e) ((((u_long)&(apcbase->e)) >> 16) & 0xff) 30652842Ssklower #define SET_SGAE(d, f, a) {(d).lo = LOWADDR(a); (d).f_hi = (f) | HIADDR(a);} 30752842Ssklower #define SET_SGDX(d, f, a, b) \ 30852842Ssklower {SET_SGAE((d).sgdx_ae, f, a); (d).sgdx_mcnt = (d).sgdx_bcnt = (b);} 30950824Ssklower 31052842Ssklower apx->apx_txnum = apx->apx_rxnum = apx->apx_txcnt = 0; 311*52848Ssklower bzero((caddr_t)apc, apx->apx_msize); 312*52848Ssklower /*bzero((caddr_t)apc, ((caddr_t)(&apc->apc_rxmd[0])) - (caddr_t)apc);*/ 313*52848Ssklower apc->apc_mode = 0x0108; /* 2 flag spacing, leave addr&ctl, do CRC16 */ 31450824Ssklower apc->apc_sgop = apx->apx_modes.apm_sgop; 31552842Ssklower SET_SGAE(apx->apx_csr23, SG_UIE | SG_PROM, apc_mode); 31652842Ssklower SET_SGAE(apc->apc_rxdd, SG_RLEN, apc_rxmd[0]); 317*52848Ssklower i = SG_TLEN | ((apx->apx_modes.apm_txwin)<< 8); 318*52848Ssklower SET_SGAE(apc->apc_txdd, i, apc_txmd[0]); 31952842Ssklower SET_SGAE(apc->apc_stdd, 0, apc_sgsb); 32052842Ssklower SET_SGDX(apc->apc_rxtid, SG_OWN, apc_rxidbuf[0], -SGMTU); 32152842Ssklower SET_SGDX(apc->apc_txtid, 0, apc_txidbuf[0], 0); 32250824Ssklower for (i = 0; i < SGRBUF; i++) 32352842Ssklower SET_SGDX(apc->apc_rxmd[i], SG_OWN, apc_rbuf[i][0], -SGMTU) 32450824Ssklower for (i = 0; i < SGTBUF; i++) 325*52848Ssklower SET_SGDX(apc->apc_txmd[i], 0, apc_tbuf[i][0], 0) 32650824Ssklower } 32750824Ssklower 32850824Ssklower /* 32950824Ssklower * Start output on interface. Get another datagram to send 33050824Ssklower * off of the interface queue, and copy it to the interface 33150824Ssklower * before starting the output. 33250824Ssklower */ 33350824Ssklower apxstart(ifp) 33450824Ssklower struct ifnet *ifp; 33550824Ssklower { 33650824Ssklower register struct apx_softc *apx = &apx_softc[ifp->if_unit]; 33750824Ssklower register struct sgdx *dx; 33850825Ssklower struct apc_mem *apc = apx->apx_hmem; 33950824Ssklower struct mbuf *m; 34050824Ssklower int len; 34150824Ssklower 34250824Ssklower if ((ifp->if_flags & IFF_RUNNING) == 0) 34350824Ssklower return (0); 34450824Ssklower do { 34550825Ssklower dx = apc->apc_txmd + apx->apx_txnum; 34650824Ssklower if (dx->sgdx_flags & SG_OWN) 34750824Ssklower return (0); 34850824Ssklower IF_DEQUEUE(&ifp->if_snd, m); 34950824Ssklower if (m == 0) 35050824Ssklower return (0); 35150824Ssklower len = min(m->m_pkthdr.len, SGMTU); 35250825Ssklower m_copydata(m, 0, len, apc->apc_tbuf[apx->apx_txnum]); 35350824Ssklower dx->sgdx_mcnt = -len; 35452842Ssklower dx->sgdx_flags = (SG_OWN|SG_TUI|SG_SLF|SG_ELF) | 35552842Ssklower (0xff & dx->sgdx_flags); 35650824Ssklower SG_WCSR(apx, 0, SG_INEA | SG_TDMD); 357*52848Ssklower DELAY(20); 358*52848Ssklower apx->apx_csr1 = SG_RCSR(apx, 1); 359*52848Ssklower apx->apx_csr0 = SG_RCSR(apx, 0); 36050824Ssklower if (++apx->apx_txnum >= SGTBUF) 36150824Ssklower apx->apx_txnum = 0; 36250824Ssklower } while (++apx->apx_txcnt < SGTBUF); 36352830Ssklower apx->apx_txcnt = SGTBUF; /* in case txcnt > SGTBUF by mistake */ 36450824Ssklower ifp->if_flags |= IFF_OACTIVE; 36550824Ssklower return (0); 36650824Ssklower } 36750824Ssklower 36850825Ssklower void 36950824Ssklower apxintr() 37050824Ssklower { 37152828Ssklower register struct apx_softc *apx; 37250824Ssklower int reply; 37350824Ssklower 37452842Ssklower apxstat.anyint++; 37552828Ssklower for (apx = apx_softc + NAPX + NAPX; --apx >= apx_softc;) { 37652828Ssklower if (apx->apx_flags & APXF_CHIPHERE) 37750824Ssklower /* Try to turn off interrupt cause */ 378*52848Ssklower while ((apx->apx_csr0 = SG_RCSR(apx, 0)) & 0xff) { 379*52848Ssklower reply = apx->apx_csr0; 38050824Ssklower SG_WCSR(apx, 0, SG_INEA | 0xfe); 38150824Ssklower if (reply & (SG_MERR|SG_TUR|SG_ROR)) { 38250824Ssklower apxerror(apx, "mem, rx, or tx error", reply); 38350824Ssklower apxinit(apx->apx_if.if_unit); 38450824Ssklower break; 38550824Ssklower } 38650824Ssklower if (reply & SG_RINT) 38750824Ssklower apxrint(apx); 38850824Ssklower if (reply & SG_TINT) 38950824Ssklower apxtint(apx); 39050824Ssklower if (reply & SG_PINT) 39150824Ssklower apxstat.pint++; 39250824Ssklower } 39352828Ssklower } 39450824Ssklower } 39550824Ssklower 39650825Ssklower void 39750824Ssklower apxtint(apx) 39850824Ssklower register struct apx_softc *apx; 39950824Ssklower { 40050825Ssklower register struct apc_mem *apc = apx->apx_hmem; 40150824Ssklower int i, loopcount = 0; 40250824Ssklower 40352842Ssklower apxstat.tint++; 40450824Ssklower do { 40550824Ssklower if ((i = apx->apx_txnum - apx->apx_txcnt) < 0) 40650824Ssklower i += SGTBUF; 40750824Ssklower if (apc->apc_txmd[i].sgdx_flags & SG_OWN) { 40850824Ssklower if (loopcount) 40950824Ssklower break; 41052842Ssklower apxstat.txnull++; 41150824Ssklower return; 41250824Ssklower } 41350824Ssklower loopcount++; 41450824Ssklower apx->apx_if.if_flags &= ~IFF_OACTIVE; 41550824Ssklower } while (--apx->apx_txcnt > 0); 41650824Ssklower apxstart(&apx->apx_if); 41750824Ssklower } 41850824Ssklower 41952828Ssklower void 42050824Ssklower apxrint(apx) 42150824Ssklower register struct apx_softc *apx; 42250824Ssklower { 42350825Ssklower register struct apc_mem *apc = apx->apx_hmem; 42450824Ssklower register struct sgdx *dx = apc->apc_rxmd + apx->apx_rxnum; 42552842Ssklower int i = 0; 42650824Ssklower #define SGNEXTRXMD \ 42750824Ssklower dx = ++apx->apx_rxnum == SGRBUF ? &apc->apc_rxmd[apx->apx_rxnum = 0] : dx + 1; 42850824Ssklower 42952842Ssklower apxstat.rint++; 43050824Ssklower /* 43150824Ssklower * Out of sync with hardware, should never happen? 43250824Ssklower */ 43352842Ssklower while (dx->sgdx_flags & SG_OWN) { 43452842Ssklower apxstat.rxnrdy++; 43552842Ssklower if (++i == SGRBUF) { 43652842Ssklower apxstat.rxnull++; 43752842Ssklower return; 43852842Ssklower } 43952842Ssklower SGNEXTRXMD; 44050824Ssklower } 44150824Ssklower /* 44250824Ssklower * Process all buffers with valid data 44350824Ssklower */ 44450824Ssklower while ((dx->sgdx_flags & SG_OWN) == 0) { 44550824Ssklower if ((dx->sgdx_flags & (SG_SLF|SG_ELF)) != (SG_SLF|SG_ELF)) { 44650824Ssklower /* 44752842Ssklower * Find the end of the packet so we synch up. 44852842Ssklower * We throw the data away. 44950824Ssklower */ 45050825Ssklower apxerror(apx, "chained buffer", dx->sgdx_flags); 45150824Ssklower do { 45252842Ssklower apxstat.rx2big++; 45350824Ssklower dx->sgdx_bcnt = 0; 45450824Ssklower dx->sgdx_flags = SG_OWN | (0xff&dx->sgdx_flags); 45550824Ssklower SGNEXTRXMD; 45650824Ssklower } while (!(dx->sgdx_flags & (SG_OWN|SG_SLF|SG_ELF))); 45750824Ssklower /* 45850824Ssklower * If search terminated without successful completion 45950824Ssklower * we reset the hardware (conservative). 46050824Ssklower */ 46150824Ssklower if ((dx->sgdx_flags & (SG_OWN|SG_SLF|SG_ELF)) != 46250825Ssklower SG_ELF) { 46350824Ssklower apxreset(apx->apx_if.if_unit); 46450824Ssklower return; 46550824Ssklower } 46650824Ssklower } else 46750824Ssklower apxinput(&apx->apx_if, apc->apc_rbuf[apx->apx_rxnum], 46852842Ssklower -dx->sgdx_mcnt); 46950824Ssklower dx->sgdx_bcnt = 0; 47050824Ssklower dx->sgdx_flags = SG_OWN | (0xff & dx->sgdx_flags); 47150824Ssklower SGNEXTRXMD; 47250824Ssklower } 47350824Ssklower } 47450824Ssklower 47550825Ssklower void 47650824Ssklower apxinput(ifp, buffer, len) 47752830Ssklower register struct ifnet *ifp; 47852830Ssklower caddr_t buffer; 47950824Ssklower { 48052830Ssklower extern struct ifqueue hdintrq, ipintrq; 48150824Ssklower register struct ifqueue *inq; 48252830Ssklower register u_char *cp = (u_char *)buffer; 48352672Ssklower struct mbuf *m, *m_devget(); 48450824Ssklower int isr; 48550824Ssklower 48650824Ssklower ifp->if_ipackets++; 48752842Ssklower if ((ifp->if_flags & IFF_UP) == 0) { 48852842Ssklower apxstat.nxpctd++; 48952842Ssklower return; 49052842Ssklower } 49150824Ssklower if (cp[0] == 0xff && cp[1] == 0x3) { 49250824Ssklower /* This is a UI HDLC Packet, so we'll assume PPP 49350824Ssklower protocol. for now, IP only. */ 49450824Ssklower buffer += 4; 49550824Ssklower len -= 4; 49650824Ssklower inq = &ipintrq; 49750824Ssklower isr = NETISR_IP; 49850824Ssklower } else { 49952830Ssklower #ifdef CCITT 50050824Ssklower inq = &hdintrq; 50150824Ssklower isr = NETISR_CCITT; 50250824Ssklower } 50352830Ssklower if (len <= 0) { 50452830Ssklower #endif 50550824Ssklower return; 50652830Ssklower } 50752672Ssklower m = m_devget(buffer, len, 0, ifp, (void (*)())0); 50850824Ssklower if (m == 0) 50950824Ssklower return; 510*52848Ssklower #ifdef CCITT 511*52848Ssklower if (apxipdebug) 512*52848Ssklower mbuf_cache(&apx_cache, m); 513*52848Ssklower #endif 51450824Ssklower if(IF_QFULL(inq)) { 51550824Ssklower IF_DROP(inq); 51650824Ssklower m_freem(m); 51750824Ssklower } else { 51852842Ssklower apxstat.queued++; 51950824Ssklower IF_ENQUEUE(inq, m); 52050824Ssklower schednetisr(isr); 52150824Ssklower } 52250824Ssklower } 52350824Ssklower 52450824Ssklower /* 52550824Ssklower * Process an ioctl request. 52650824Ssklower */ 52750824Ssklower apxioctl(ifp, cmd, data) 52850824Ssklower register struct ifnet *ifp; 52950824Ssklower int cmd; 53050824Ssklower caddr_t data; 53150824Ssklower { 53250824Ssklower register struct ifaddr *ifa = (struct ifaddr *)data; 53350824Ssklower int s = splimp(), error = 0; 53450824Ssklower struct apx_softc *apx = &apx_softc[ifp->if_unit]; 53550824Ssklower 53650824Ssklower switch (cmd) { 53752828Ssklower 53852828Ssklower case SIOCSIFADDR: 53952828Ssklower #ifdef CCITT 540*52848Ssklower if (apxipdebug) { 541*52848Ssklower ifp->if_flags |= IFF_UP; 542*52848Ssklower apxinit(ifp->if_unit); 543*52848Ssklower } else 544*52848Ssklower ifa->ifa_rtrequest = x25_rtrequest; 54552828Ssklower break; 54652828Ssklower 54750824Ssklower case SIOCSIFCONF_X25: 54852828Ssklower ifp->if_output = x25_ifoutput; 54950824Ssklower ifp->if_flags |= IFF_UP; 55050824Ssklower error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); 55150824Ssklower if (error == 0) 55250824Ssklower apxinit(ifp->if_unit); 55352828Ssklower #endif 55450824Ssklower break; 55550824Ssklower 55650824Ssklower case SIOCSIFFLAGS: 55750824Ssklower if (((ifp->if_flags & IFF_UP) == 0 && 55850824Ssklower (ifp->if_flags & IFF_RUNNING)) || 55950824Ssklower (ifp->if_flags & IFF_UP) && 56050824Ssklower (ifp->if_flags & IFF_RUNNING) == 0) 56150824Ssklower apxinit(ifp->if_unit); 56250824Ssklower break; 56350824Ssklower 56450824Ssklower case SIOCSIFMODE: 56550824Ssklower if ((ifp->if_flags & IFF_UP) == 0) 56650825Ssklower apx->apx_modes = *(struct apc_modes *)data; 56750824Ssklower else 56850824Ssklower default: 56950824Ssklower error = EINVAL; 57050824Ssklower 57150824Ssklower } 57250824Ssklower splx(s); 57350824Ssklower return (error); 57450824Ssklower } 57550824Ssklower 57650824Ssklower apxerror(apx, msg, data) 57750824Ssklower register struct apx_softc *apx; 57850824Ssklower char *msg; 57950824Ssklower { 58050824Ssklower log(LOG_WARNING, "apc%d: %s, stat=0x%x\n", 58150824Ssklower apx->apx_if.if_unit, msg, data); 58250824Ssklower } 58352828Ssklower /* 58452828Ssklower * For debugging loopback activity. 58552828Ssklower */ 58652828Ssklower static char pppheader[4] = { -1, 3, 0, 0x21 }; 58752828Ssklower 58852828Ssklower apxoutput(ifp, m, dst, rt) 58952828Ssklower register struct ifnet *ifp; 59052828Ssklower register struct mbuf *m; 59152828Ssklower struct sockaddr *dst; 59252828Ssklower struct rtentry *rt; 59352828Ssklower { 59452828Ssklower /* 59552828Ssklower * Queue message on interface, and start output if interface 59652828Ssklower * not yet active. 59752828Ssklower */ 59852828Ssklower int s = splimp(), error = 0; 59952828Ssklower M_PREPEND(m, sizeof pppheader, M_DONTWAIT); 60052828Ssklower if (m == 0) { 60152828Ssklower splx(s); 60252828Ssklower return ENOBUFS; 60352828Ssklower } 60452828Ssklower bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader); 60552828Ssklower if (IF_QFULL(&ifp->if_snd)) { 60652828Ssklower IF_DROP(&ifp->if_snd); 60752828Ssklower /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", 60852828Ssklower ifp->if_name, ifp->if_unit);*/ 60952828Ssklower m_freem(m); 61052828Ssklower error = ENOBUFS; 61152828Ssklower } else { 61252828Ssklower IF_ENQUEUE(&ifp->if_snd, m); 61352828Ssklower if ((ifp->if_flags & IFF_OACTIVE) == 0) 61452828Ssklower (*ifp->if_start)(ifp); 61552828Ssklower } 61652828Ssklower splx(s); 61752828Ssklower return (error); 61852828Ssklower } 61952828Ssklower 62050824Ssklower #endif /* NAPX */ 621