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*52842Ssklower * @(#)if_apx.c 7.6 (Berkeley) 03/04/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(); 4152828Ssklower int apxinit(), apxoutput(), apxioctl(), apxreset(), apxdebug = 1; 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*/ 56*52842Ssklower struct sgae apx_csr23; /* 24 bit init addr, as seen by chip */ 5752828Ssklower u_short apx_csr4; /* byte gender, set in mach dep code */ 5852828Ssklower struct apc_modes apx_modes; /* Parameters, as amended by ioctls */ 5952828Ssklower } apx_softc[2 * NAPX]; 6050824Ssklower 6150824Ssklower struct apxstat { 62*52842Ssklower int rxnull; /* no rx bufs ready this interrupt */ 63*52842Ssklower int rxnrdy; /* expected rx buf not ready */ 64*52842Ssklower int rx2big; /* expected rx buf not ready */ 65*52842Ssklower int txnull; 66*52842Ssklower int pint; /* new primitive available interrupt */ 67*52842Ssklower int rint; /* receive interrupts */ 68*52842Ssklower int tint; /* transmit interrupts */ 69*52842Ssklower int anyint; /* note all interrupts */ 70*52842Ssklower int queued; /* got through apxinput */ 71*52842Ssklower int nxpctd; /* received while if was down */ 7250825Ssklower } apxstat; 7350824Ssklower 7450824Ssklower /* default operating paramters for devices */ 7550824Ssklower struct apc_modes apx_default_modes = { 7650824Ssklower { 1, /* apm_sgob.lsaddr; */ 7750824Ssklower 3, /* apm_sgob.rsaddr; */ 7850824Ssklower -SGMTU, /* apm_sgob.n1; */ 7950824Ssklower ((-10)<<8), /* apm_sgob.n2_scale; */ 8050824Ssklower -1250, /* apm_sgob.t1; */ 8150824Ssklower -10000, /* apm_sgob.t3; */ 8250824Ssklower -80, /* apm_sgob.tp; */ 8350824Ssklower }, 8450824Ssklower 2, /* apm_txwin; */ 85*52842Ssklower 1, /* apm_apxmode: RS_232 connector and modem clock; */ 86*52842Ssklower 0, /* apm_apxaltmode: enable dtr, disable X.21 connector; */ 8750824Ssklower IFT_X25, /* apm_iftype; */ 8850824Ssklower }; 8950824Ssklower 9050824Ssklower /* Begin bus & endian dependence */ 9150824Ssklower 9250825Ssklower #include "isa_device.h" 9350824Ssklower 9450824Ssklower struct isa_driver apxdriver = { 9550824Ssklower apxprobe, apxattach, "apx", 9650824Ssklower }; 9750824Ssklower 9850824Ssklower #define SG_RCSR(apx, csrnum) \ 9950825Ssklower (outw(&(apx->apx_sgcp->sgcp_rap), csrnum << 1), \ 10050825Ssklower inw(&(apx->apx_sgcp->sgcp_rdp))) 10150824Ssklower 10250824Ssklower #define SG_WCSR(apx, csrnum, data) \ 10350825Ssklower (outw(&(apx->apx_sgcp->sgcp_rap), csrnum << 1), \ 10450824Ssklower outw(&(apx->apx_sgcp->sgcp_rdp), data)) 10550824Ssklower 10650824Ssklower #define APX_RCSR(apx, csrname) inb(&(apx->apx_reg->csrname)) 10750824Ssklower #define APX_WCSR(apx, csrname, data) outb(&(apx->apx_reg->csrname), data) 10850824Ssklower 10950824Ssklower #define TIMO 10000 /* used in apx_uprim */ 11050824Ssklower 11150824Ssklower apxprobe(id) 11250824Ssklower register struct isa_device *id; 11350824Ssklower { 11450824Ssklower int moffset, subunit, unit = id->id_unit << 1; 11550825Ssklower struct apc_reg *reg = (struct apc_reg *)id->id_iobase; 11650824Ssklower register struct apx_softc *apx = apx_softc + unit; 11750824Ssklower 11852830Ssklower for (subunit = 0; subunit < 2; subunit++) { 11950824Ssklower moffset = subunit ? id->id_msize >> 1 : 0; 12050824Ssklower apx->apx_hmem = (struct apc_mem *) (id->id_maddr + moffset); 12150824Ssklower apx->apx_dmem = (struct apc_mem *) (moffset); 12250824Ssklower apx->apx_device = (caddr_t) id; 12350824Ssklower apx->apx_reg = reg; 12452828Ssklower apx->apx_sgcp = reg->axr_sgcp + subunit; 12552828Ssklower apx->apx_csr4 = 0x0210; /* no byte swapping for PC-AT */ 12652828Ssklower apx->apx_modes = apx_default_modes; 12752828Ssklower apx->apx_if.if_unit = unit++; 12852830Ssklower apxtest(apx++); 12950824Ssklower } 13050824Ssklower return 1; 13150824Ssklower } 13250824Ssklower 13350824Ssklower apxattach(id) 13452830Ssklower struct isa_device *id; 13550824Ssklower { 13652830Ssklower register struct apx_softc *apx = apx_softc + (id->id_unit << 1); 13750824Ssklower 13852830Ssklower apx_ifattach(&((apx++)->apx_if)); 13952830Ssklower apx_ifattach(&(apx->apx_if)); 14052828Ssklower return 0; 14150824Ssklower } 14250824Ssklower /* End bus & endian dependence */ 14350824Ssklower 14450824Ssklower /* 14550824Ssklower * Interface exists: make available by filling in network interface 14650824Ssklower * record. System will initialize the interface when it is ready 14750824Ssklower * to accept packets. 14850824Ssklower */ 14950825Ssklower void 15052830Ssklower apx_ifattach(ifp) 15152830Ssklower register struct ifnet *ifp; 15250824Ssklower { 15350824Ssklower /* 15450824Ssklower * Initialize ifnet structure 15550824Ssklower */ 15652828Ssklower ifp->if_name = "apc"; 15752828Ssklower ifp->if_mtu = SGMTU; 15852828Ssklower ifp->if_init = apxinit; 15952828Ssklower ifp->if_output = apxoutput; 16052828Ssklower ifp->if_start = apxstart; 16152828Ssklower ifp->if_ioctl = apxioctl; 16252828Ssklower ifp->if_reset = apxreset; 16352828Ssklower ifp->if_type = apx_default_modes.apm_iftype; 16452828Ssklower ifp->if_hdrlen = 5; 16552828Ssklower ifp->if_addrlen = 8; 16650824Ssklower if_attach(ifp); 16750824Ssklower } 16850824Ssklower /* 16950824Ssklower * Initialization of interface 17050824Ssklower */ 17150824Ssklower apxinit(unit) 17250824Ssklower int unit; 17350824Ssklower { 17450824Ssklower struct ifnet *ifp = &apx_softc[unit].apx_if; 17550824Ssklower int s = splimp(); 17650824Ssklower 17750824Ssklower ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 17850824Ssklower if (apxreset(unit) && (ifp->if_flags & IFF_UP)) { 17950824Ssklower ifp->if_flags |= IFF_RUNNING; 18050824Ssklower (void)apxstart(ifp); 18150824Ssklower } 18250824Ssklower splx(s); 18350824Ssklower return 0; 18450824Ssklower } 18550824Ssklower 18652672Ssklower apxctr(apx) 18752672Ssklower register struct apx_softc *apx; 18852672Ssklower { 18952828Ssklower APX_WCSR(apx, axr_ccr, 0xB0); /* select ctr 2, write lsb+msb, mode 0 */ 19052672Ssklower APX_WCSR(apx, axr_cnt2, 0x1); 19152672Ssklower APX_WCSR(apx, axr_cnt2, 0x0); 19252672Ssklower DELAY(50); 19352828Ssklower APX_WCSR(apx, axr_ccr, 0xE8); /* latch status, ctr 2; */ 19452828Ssklower return (APX_RCSR(apx, axr_cnt2)); 19552672Ssklower } 19652672Ssklower 19752828Ssklower void 19852828Ssklower apxtest(apx) 19952828Ssklower register struct apx_softc *apx; 20052828Ssklower { 20152828Ssklower int i = 0; 20252828Ssklower 20352828Ssklower if ((apx->apx_if.if_unit & 1) == 0 && (i = apxctr(apx)) == 0) 20452828Ssklower apxerror(apx, "no response from timer chip", 0); 20552828Ssklower if (SG_RCSR(apx, 1) & 0x8000) 20652828Ssklower SG_WCSR(apx, 1, 0x8040); 20752828Ssklower SG_WCSR(apx, 4, apx->apx_csr4); 20852828Ssklower if (apxdebug && i) { 20952828Ssklower apxerror(apx, "counter 2 value", i); 21052828Ssklower apxerror(apx, "mk5025 csr4 value", SG_RCSR(apx, 4)); 21152828Ssklower } 21252828Ssklower SG_WCSR(apx, 5, 0x08); /* Set DTR mode in SGS thompson chip */ 21352828Ssklower if (((i = SG_RCSR(apx, 5)) & 0xff08) != 0x08) 21452828Ssklower apxerror(apx, "no mk5025, csr5 high bits are", i); 21552828Ssklower else 21652828Ssklower apx->apx_flags |= APXF_CHIPHERE; 217*52842Ssklower (void) apx_uprim(apx, SG_STOP, "stop after probing"); 21852828Ssklower } 21952828Ssklower 22050824Ssklower apxreset(unit) 22150824Ssklower int unit; 22250824Ssklower { 22350824Ssklower register struct apx_softc *apx = &apx_softc[unit ^ 1]; 22450824Ssklower u_char apm_apxmode = 0, apm_apxaltmode = 0; 22550824Ssklower #define MODE(m) (m |= apx->apx_modes.m << ((apx->apx_if.if_unit & 1) ? 1 : 0)) 22650824Ssklower 22750824Ssklower MODE(apm_apxmode); 22850824Ssklower MODE(apm_apxaltmode); 22950824Ssklower apx = apx_softc + unit; 23050824Ssklower MODE(apm_apxmode); 23150824Ssklower MODE(apm_apxaltmode); 23250824Ssklower APX_WCSR(apx, axr_mode, apm_apxmode); 23350824Ssklower APX_WCSR(apx, axr_altmode, apm_apxaltmode); 234*52842Ssklower (void) apxctr(apx); 235*52842Ssklower (void) apx_uprim(apx, SG_STOP, "stop to reset"); 236*52842Ssklower if ((apx->apx_if.if_flags & IFF_UP) == 0) 23750824Ssklower return 0; 238*52842Ssklower apx_meminit(apx->apx_hmem, apx); 23950824Ssklower SG_WCSR(apx, 4, apx->apx_csr4); 240*52842Ssklower SG_WCSR(apx, 2, apx->apx_csr23.f_hi); 241*52842Ssklower SG_WCSR(apx, 3, apx->apx_csr23.lo); 24250825Ssklower if (apx_uprim(apx, SG_INIT, "init request") || 24350824Ssklower apx_uprim(apx, SG_STAT, "status request") || 24450824Ssklower apx_uprim(apx, SG_TRANS, "transparent mode")) 24550824Ssklower return 0; 24650824Ssklower SG_WCSR(apx, 0, SG_INEA); 24750825Ssklower return 1; 24850824Ssklower } 249*52842Ssklower int apx_doinit = 1, apx_dostat = 1; 250*52842Ssklower int apx_didinit = 0, apx_didstat = 0; 25150824Ssklower 25250824Ssklower apx_uprim(apx, request, ident) 25352830Ssklower register struct apx_softc *apx; 25450824Ssklower char *ident; 25550824Ssklower { 25650824Ssklower register int timo = 0; 25752830Ssklower int reply; 25850824Ssklower 25952830Ssklower if ((apx->apx_flags & APXF_CHIPHERE) == 0) 26052830Ssklower return 1; /* maybe even should panic . . . */ 261*52842Ssklower 262*52842Ssklower if (request == SG_STAT) { if (apx_dostat) apx_didstat = 1; else return 0;} 263*52842Ssklower if (request == SG_INIT) { if (apx_doinit) apx_didinit = 1; else return 0;} 264*52842Ssklower 26552830Ssklower if ((reply = SG_RCSR(apx, 1)) & 0x8040) 26652828Ssklower SG_WCSR(apx, 1, 0x8040); /* Magic! */ 26750824Ssklower SG_WCSR(apx, 1, request | SG_UAV); 26850824Ssklower do { 26952828Ssklower reply = SG_RCSR(apx, 1); 270*52842Ssklower if (timo++ >= TIMO || (reply & 0x8000)) { 271*52842Ssklower if (request != SG_STOP || apxdebug) 272*52842Ssklower apxerror(apx, ident, reply); 273*52842Ssklower if (request != SG_STOP) 274*52842Ssklower return 1; 27550824Ssklower } 27650824Ssklower } while (reply & SG_UAV); 27750824Ssklower return 0; 27850824Ssklower } 27950824Ssklower 28050824Ssklower apx_meminit(apc, apx) 28150824Ssklower register struct apc_mem *apc; 28250824Ssklower struct apx_softc *apx; 28350824Ssklower { 28450824Ssklower register struct apc_mem *apcbase = apx->apx_dmem; 28550824Ssklower register int i; 28650825Ssklower #define LOWADDR(e) (((u_long)&(apcbase->e)) & 0xffff) 28750825Ssklower #define HIADDR(e) ((((u_long)&(apcbase->e)) >> 16) & 0xff) 288*52842Ssklower #define SET_SGAE(d, f, a) {(d).lo = LOWADDR(a); (d).f_hi = (f) | HIADDR(a);} 289*52842Ssklower #define SET_SGDX(d, f, a, b) \ 290*52842Ssklower {SET_SGAE((d).sgdx_ae, f, a); (d).sgdx_mcnt = (d).sgdx_bcnt = (b);} 29150824Ssklower 292*52842Ssklower apx->apx_txnum = apx->apx_rxnum = apx->apx_txcnt = 0; 293*52842Ssklower bzero((caddr_t)apc, ((caddr_t)(&apc->apc_rxmd[0])) - (caddr_t)apc); 294*52842Ssklower apc->apc_mode = 0x0008; /* 2 flag spacing, trans mode, 16bit FCS */ 29550824Ssklower apc->apc_sgop = apx->apx_modes.apm_sgop; 296*52842Ssklower SET_SGAE(apx->apx_csr23, SG_UIE | SG_PROM, apc_mode); 297*52842Ssklower SET_SGAE(apc->apc_rxdd, SG_RLEN, apc_rxmd[0]); 298*52842Ssklower SET_SGAE(apc->apc_txdd, SG_TLEN|apx->apx_modes.apm_txwin, apc_txmd[0]); 299*52842Ssklower SET_SGAE(apc->apc_stdd, 0, apc_sgsb); 300*52842Ssklower SET_SGDX(apc->apc_rxtid, SG_OWN, apc_rxidbuf[0], -SGMTU); 301*52842Ssklower SET_SGDX(apc->apc_txtid, 0, apc_txidbuf[0], 0); 30250824Ssklower for (i = 0; i < SGRBUF; i++) 303*52842Ssklower SET_SGDX(apc->apc_rxmd[i], SG_OWN, apc_rbuf[i][0], -SGMTU) 30450824Ssklower for (i = 0; i < SGTBUF; i++) 305*52842Ssklower SET_SGDX(apc->apc_txmd[i], SG_TUI, apc_tbuf[i][0], 0) 30650824Ssklower } 30750824Ssklower 30850824Ssklower /* 30950824Ssklower * Start output on interface. Get another datagram to send 31050824Ssklower * off of the interface queue, and copy it to the interface 31150824Ssklower * before starting the output. 31250824Ssklower */ 31350824Ssklower apxstart(ifp) 31450824Ssklower struct ifnet *ifp; 31550824Ssklower { 31650824Ssklower register struct apx_softc *apx = &apx_softc[ifp->if_unit]; 31750824Ssklower register struct sgdx *dx; 31850825Ssklower struct apc_mem *apc = apx->apx_hmem; 31950824Ssklower struct mbuf *m; 32050824Ssklower int len; 32150824Ssklower 32250824Ssklower if ((ifp->if_flags & IFF_RUNNING) == 0) 32350824Ssklower return (0); 32450824Ssklower do { 32550825Ssklower dx = apc->apc_txmd + apx->apx_txnum; 32650824Ssklower if (dx->sgdx_flags & SG_OWN) 32750824Ssklower return (0); 32850824Ssklower IF_DEQUEUE(&ifp->if_snd, m); 32950824Ssklower if (m == 0) 33050824Ssklower return (0); 33150824Ssklower len = min(m->m_pkthdr.len, SGMTU); 33250825Ssklower m_copydata(m, 0, len, apc->apc_tbuf[apx->apx_txnum]); 33350824Ssklower dx->sgdx_mcnt = -len; 334*52842Ssklower dx->sgdx_flags = (SG_OWN|SG_TUI|SG_SLF|SG_ELF) | 335*52842Ssklower (0xff & dx->sgdx_flags); 33650824Ssklower SG_WCSR(apx, 0, SG_INEA | SG_TDMD); 33750824Ssklower if (++apx->apx_txnum >= SGTBUF) 33850824Ssklower apx->apx_txnum = 0; 33950824Ssklower } while (++apx->apx_txcnt < SGTBUF); 34052830Ssklower apx->apx_txcnt = SGTBUF; /* in case txcnt > SGTBUF by mistake */ 34150824Ssklower ifp->if_flags |= IFF_OACTIVE; 34250824Ssklower return (0); 34350824Ssklower } 34450824Ssklower 34550825Ssklower void 34650824Ssklower apxintr() 34750824Ssklower { 34852828Ssklower register struct apx_softc *apx; 34950824Ssklower int reply; 35050824Ssklower 351*52842Ssklower apxstat.anyint++; 35252828Ssklower for (apx = apx_softc + NAPX + NAPX; --apx >= apx_softc;) { 35352828Ssklower if (apx->apx_flags & APXF_CHIPHERE) 35450824Ssklower /* Try to turn off interrupt cause */ 35550824Ssklower while ((reply = SG_RCSR(apx, 0)) & 0xff) { 35650824Ssklower SG_WCSR(apx, 0, SG_INEA | 0xfe); 35750824Ssklower if (reply & (SG_MERR|SG_TUR|SG_ROR)) { 35850824Ssklower apxerror(apx, "mem, rx, or tx error", reply); 35950824Ssklower apxinit(apx->apx_if.if_unit); 36050824Ssklower break; 36150824Ssklower } 36250824Ssklower if (reply & SG_RINT) 36350824Ssklower apxrint(apx); 36450824Ssklower if (reply & SG_TINT) 36550824Ssklower apxtint(apx); 36650824Ssklower if (reply & SG_PINT) 36750824Ssklower apxstat.pint++; 36850824Ssklower } 36952828Ssklower } 37050824Ssklower } 37150824Ssklower 37250825Ssklower void 37350824Ssklower apxtint(apx) 37450824Ssklower register struct apx_softc *apx; 37550824Ssklower { 37650825Ssklower register struct apc_mem *apc = apx->apx_hmem; 37750824Ssklower int i, loopcount = 0; 37850824Ssklower 379*52842Ssklower apxstat.tint++; 38050824Ssklower do { 38150824Ssklower if ((i = apx->apx_txnum - apx->apx_txcnt) < 0) 38250824Ssklower i += SGTBUF; 38350824Ssklower if (apc->apc_txmd[i].sgdx_flags & SG_OWN) { 38450824Ssklower if (loopcount) 38550824Ssklower break; 386*52842Ssklower apxstat.txnull++; 38750824Ssklower return; 38850824Ssklower } 38950824Ssklower loopcount++; 39050824Ssklower apx->apx_if.if_flags &= ~IFF_OACTIVE; 39150824Ssklower } while (--apx->apx_txcnt > 0); 39250824Ssklower apxstart(&apx->apx_if); 39350824Ssklower } 39450824Ssklower 39552828Ssklower void 39650824Ssklower apxrint(apx) 39750824Ssklower register struct apx_softc *apx; 39850824Ssklower { 39950825Ssklower register struct apc_mem *apc = apx->apx_hmem; 40050824Ssklower register struct sgdx *dx = apc->apc_rxmd + apx->apx_rxnum; 401*52842Ssklower int i = 0; 40250824Ssklower #define SGNEXTRXMD \ 40350824Ssklower dx = ++apx->apx_rxnum == SGRBUF ? &apc->apc_rxmd[apx->apx_rxnum = 0] : dx + 1; 40450824Ssklower 405*52842Ssklower apxstat.rint++; 40650824Ssklower /* 40750824Ssklower * Out of sync with hardware, should never happen? 40850824Ssklower */ 409*52842Ssklower while (dx->sgdx_flags & SG_OWN) { 410*52842Ssklower apxstat.rxnrdy++; 411*52842Ssklower if (++i == SGRBUF) { 412*52842Ssklower apxstat.rxnull++; 413*52842Ssklower return; 414*52842Ssklower } 415*52842Ssklower SGNEXTRXMD; 41650824Ssklower } 41750824Ssklower /* 41850824Ssklower * Process all buffers with valid data 41950824Ssklower */ 42050824Ssklower while ((dx->sgdx_flags & SG_OWN) == 0) { 42150824Ssklower if ((dx->sgdx_flags & (SG_SLF|SG_ELF)) != (SG_SLF|SG_ELF)) { 42250824Ssklower /* 423*52842Ssklower * Find the end of the packet so we synch up. 424*52842Ssklower * We throw the data away. 42550824Ssklower */ 42650825Ssklower apxerror(apx, "chained buffer", dx->sgdx_flags); 42750824Ssklower do { 428*52842Ssklower apxstat.rx2big++; 42950824Ssklower dx->sgdx_bcnt = 0; 43050824Ssklower dx->sgdx_flags = SG_OWN | (0xff&dx->sgdx_flags); 43150824Ssklower SGNEXTRXMD; 43250824Ssklower } while (!(dx->sgdx_flags & (SG_OWN|SG_SLF|SG_ELF))); 43350824Ssklower /* 43450824Ssklower * If search terminated without successful completion 43550824Ssklower * we reset the hardware (conservative). 43650824Ssklower */ 43750824Ssklower if ((dx->sgdx_flags & (SG_OWN|SG_SLF|SG_ELF)) != 43850825Ssklower SG_ELF) { 43950824Ssklower apxreset(apx->apx_if.if_unit); 44050824Ssklower return; 44150824Ssklower } 44250824Ssklower } else 44350824Ssklower apxinput(&apx->apx_if, apc->apc_rbuf[apx->apx_rxnum], 444*52842Ssklower -dx->sgdx_mcnt); 44550824Ssklower dx->sgdx_bcnt = 0; 44650824Ssklower dx->sgdx_flags = SG_OWN | (0xff & dx->sgdx_flags); 44750824Ssklower SGNEXTRXMD; 44850824Ssklower } 44950824Ssklower } 45050824Ssklower 45150825Ssklower void 45250824Ssklower apxinput(ifp, buffer, len) 45352830Ssklower register struct ifnet *ifp; 45452830Ssklower caddr_t buffer; 45550824Ssklower { 45652830Ssklower extern struct ifqueue hdintrq, ipintrq; 45750824Ssklower register struct ifqueue *inq; 45852830Ssklower register u_char *cp = (u_char *)buffer; 45952672Ssklower struct mbuf *m, *m_devget(); 46050824Ssklower int isr; 46150824Ssklower 46250824Ssklower ifp->if_ipackets++; 463*52842Ssklower if ((ifp->if_flags & IFF_UP) == 0) { 464*52842Ssklower apxstat.nxpctd++; 465*52842Ssklower return; 466*52842Ssklower } 46750824Ssklower if (cp[0] == 0xff && cp[1] == 0x3) { 46850824Ssklower /* This is a UI HDLC Packet, so we'll assume PPP 46950824Ssklower protocol. for now, IP only. */ 47050824Ssklower buffer += 4; 47150824Ssklower len -= 4; 47250824Ssklower inq = &ipintrq; 47350824Ssklower isr = NETISR_IP; 47450824Ssklower } else { 47552830Ssklower #ifdef CCITT 47650824Ssklower inq = &hdintrq; 47750824Ssklower isr = NETISR_CCITT; 47850824Ssklower } 47952830Ssklower if (len <= 0) { 48052830Ssklower #endif 48150824Ssklower return; 48252830Ssklower } 48352672Ssklower m = m_devget(buffer, len, 0, ifp, (void (*)())0); 48450824Ssklower if (m == 0) 48550824Ssklower return; 48650824Ssklower if(IF_QFULL(inq)) { 48750824Ssklower IF_DROP(inq); 48850824Ssklower m_freem(m); 48950824Ssklower } else { 490*52842Ssklower apxstat.queued++; 49150824Ssklower IF_ENQUEUE(inq, m); 49250824Ssklower schednetisr(isr); 49350824Ssklower } 49450824Ssklower } 49550824Ssklower 49650824Ssklower /* 49750824Ssklower * Process an ioctl request. 49850824Ssklower */ 49950824Ssklower apxioctl(ifp, cmd, data) 50050824Ssklower register struct ifnet *ifp; 50150824Ssklower int cmd; 50250824Ssklower caddr_t data; 50350824Ssklower { 50450824Ssklower register struct ifaddr *ifa = (struct ifaddr *)data; 50550824Ssklower int s = splimp(), error = 0; 50650824Ssklower struct apx_softc *apx = &apx_softc[ifp->if_unit]; 50750824Ssklower 50850824Ssklower switch (cmd) { 50952828Ssklower 51052828Ssklower case SIOCSIFADDR: 51152828Ssklower #ifdef CCITT 51252828Ssklower ifa->ifa_rtrequest = x25_rtrequest; 51352828Ssklower break; 51452828Ssklower 51550824Ssklower case SIOCSIFCONF_X25: 51652828Ssklower ifp->if_output = x25_ifoutput; 51750824Ssklower ifp->if_flags |= IFF_UP; 51850824Ssklower error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); 51950824Ssklower if (error == 0) 52050824Ssklower apxinit(ifp->if_unit); 52152828Ssklower #endif 52250824Ssklower break; 52350824Ssklower 52450824Ssklower case SIOCSIFFLAGS: 52550824Ssklower if (((ifp->if_flags & IFF_UP) == 0 && 52650824Ssklower (ifp->if_flags & IFF_RUNNING)) || 52750824Ssklower (ifp->if_flags & IFF_UP) && 52850824Ssklower (ifp->if_flags & IFF_RUNNING) == 0) 52950824Ssklower apxinit(ifp->if_unit); 53050824Ssklower break; 53150824Ssklower 53250824Ssklower case SIOCSIFMODE: 53350824Ssklower if ((ifp->if_flags & IFF_UP) == 0) 53450825Ssklower apx->apx_modes = *(struct apc_modes *)data; 53550824Ssklower else 53650824Ssklower default: 53750824Ssklower error = EINVAL; 53850824Ssklower 53950824Ssklower } 54050824Ssklower splx(s); 54150824Ssklower return (error); 54250824Ssklower } 54350824Ssklower 54450824Ssklower apxerror(apx, msg, data) 54550824Ssklower register struct apx_softc *apx; 54650824Ssklower char *msg; 54750824Ssklower { 54850824Ssklower log(LOG_WARNING, "apc%d: %s, stat=0x%x\n", 54950824Ssklower apx->apx_if.if_unit, msg, data); 55050824Ssklower } 55152828Ssklower /* 55252828Ssklower * For debugging loopback activity. 55352828Ssklower */ 55452828Ssklower static char pppheader[4] = { -1, 3, 0, 0x21 }; 55552828Ssklower 55652828Ssklower apxoutput(ifp, m, dst, rt) 55752828Ssklower register struct ifnet *ifp; 55852828Ssklower register struct mbuf *m; 55952828Ssklower struct sockaddr *dst; 56052828Ssklower struct rtentry *rt; 56152828Ssklower { 56252828Ssklower /* 56352828Ssklower * Queue message on interface, and start output if interface 56452828Ssklower * not yet active. 56552828Ssklower */ 56652828Ssklower int s = splimp(), error = 0; 56752828Ssklower M_PREPEND(m, sizeof pppheader, M_DONTWAIT); 56852828Ssklower if (m == 0) { 56952828Ssklower splx(s); 57052828Ssklower return ENOBUFS; 57152828Ssklower } 57252828Ssklower bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader); 57352828Ssklower if (IF_QFULL(&ifp->if_snd)) { 57452828Ssklower IF_DROP(&ifp->if_snd); 57552828Ssklower /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", 57652828Ssklower ifp->if_name, ifp->if_unit);*/ 57752828Ssklower m_freem(m); 57852828Ssklower error = ENOBUFS; 57952828Ssklower } else { 58052828Ssklower IF_ENQUEUE(&ifp->if_snd, m); 58152828Ssklower if ((ifp->if_flags & IFF_OACTIVE) == 0) 58252828Ssklower (*ifp->if_start)(ifp); 58352828Ssklower } 58452828Ssklower splx(s); 58552828Ssklower return (error); 58652828Ssklower } 58752828Ssklower 58850824Ssklower #endif /* NAPX */ 589