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*52830Ssklower * @(#)if_apx.c 7.5 (Berkeley) 03/03/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*/ 5652828Ssklower u_short apx_csr4; /* byte gender, set in mach dep code */ 5752828Ssklower struct apc_modes apx_modes; /* Parameters, as amended by ioctls */ 5852828Ssklower } apx_softc[2 * NAPX]; 5950824Ssklower 6050824Ssklower struct apxstat { 6150824Ssklower int nulltx; 6250824Ssklower int pint; 6350825Ssklower } apxstat; 6450824Ssklower 6550824Ssklower /* default operating paramters for devices */ 6650824Ssklower struct apc_modes apx_default_modes = { 6750824Ssklower { 1, /* apm_sgob.lsaddr; */ 6850824Ssklower 3, /* apm_sgob.rsaddr; */ 6950824Ssklower -SGMTU, /* apm_sgob.n1; */ 7050824Ssklower ((-10)<<8), /* apm_sgob.n2_scale; */ 7150824Ssklower -1250, /* apm_sgob.t1; */ 7250824Ssklower -10000, /* apm_sgob.t3; */ 7350824Ssklower -80, /* apm_sgob.tp; */ 7450824Ssklower }, 7550824Ssklower 2, /* apm_txwin; */ 7650824Ssklower 5, /* apm_apxmode; */ 7750824Ssklower 0, /* apm_apxaltmode; */ 7850824Ssklower IFT_X25, /* apm_iftype; */ 7950824Ssklower }; 8050824Ssklower 8150824Ssklower /* Begin bus & endian dependence */ 8250824Ssklower 8350825Ssklower #include "isa_device.h" 8450824Ssklower 8550824Ssklower struct isa_driver apxdriver = { 8650824Ssklower apxprobe, apxattach, "apx", 8750824Ssklower }; 8850824Ssklower 8950824Ssklower #define SG_RCSR(apx, csrnum) \ 9050825Ssklower (outw(&(apx->apx_sgcp->sgcp_rap), csrnum << 1), \ 9150825Ssklower inw(&(apx->apx_sgcp->sgcp_rdp))) 9250824Ssklower 9350824Ssklower #define SG_WCSR(apx, csrnum, data) \ 9450825Ssklower (outw(&(apx->apx_sgcp->sgcp_rap), csrnum << 1), \ 9550824Ssklower outw(&(apx->apx_sgcp->sgcp_rdp), data)) 9650824Ssklower 9750824Ssklower #define APX_RCSR(apx, csrname) inb(&(apx->apx_reg->csrname)) 9850824Ssklower #define APX_WCSR(apx, csrname, data) outb(&(apx->apx_reg->csrname), data) 9950824Ssklower 10050824Ssklower #define TIMO 10000 /* used in apx_uprim */ 10150824Ssklower 10250824Ssklower apxprobe(id) 10350824Ssklower register struct isa_device *id; 10450824Ssklower { 10550824Ssklower int moffset, subunit, unit = id->id_unit << 1; 10650825Ssklower struct apc_reg *reg = (struct apc_reg *)id->id_iobase; 10750824Ssklower register struct apx_softc *apx = apx_softc + unit; 10850824Ssklower 109*52830Ssklower for (subunit = 0; subunit < 2; subunit++) { 11050824Ssklower moffset = subunit ? id->id_msize >> 1 : 0; 11150824Ssklower apx->apx_hmem = (struct apc_mem *) (id->id_maddr + moffset); 11250824Ssklower apx->apx_dmem = (struct apc_mem *) (moffset); 11350824Ssklower apx->apx_device = (caddr_t) id; 11450824Ssklower apx->apx_reg = reg; 11552828Ssklower apx->apx_sgcp = reg->axr_sgcp + subunit; 11652828Ssklower apx->apx_csr4 = 0x0210; /* no byte swapping for PC-AT */ 11752828Ssklower apx->apx_modes = apx_default_modes; 11852828Ssklower apx->apx_if.if_unit = unit++; 119*52830Ssklower apxtest(apx++); 12050824Ssklower } 12150824Ssklower return 1; 12250824Ssklower } 12350824Ssklower 12450824Ssklower apxattach(id) 125*52830Ssklower struct isa_device *id; 12650824Ssklower { 127*52830Ssklower register struct apx_softc *apx = apx_softc + (id->id_unit << 1); 12850824Ssklower 129*52830Ssklower apx_ifattach(&((apx++)->apx_if)); 130*52830Ssklower apx_ifattach(&(apx->apx_if)); 13152828Ssklower return 0; 13250824Ssklower } 13350824Ssklower /* End bus & endian dependence */ 13450824Ssklower 13550824Ssklower /* 13650824Ssklower * Interface exists: make available by filling in network interface 13750824Ssklower * record. System will initialize the interface when it is ready 13850824Ssklower * to accept packets. 13950824Ssklower */ 14050825Ssklower void 141*52830Ssklower apx_ifattach(ifp) 142*52830Ssklower register struct ifnet *ifp; 14350824Ssklower { 14450824Ssklower /* 14550824Ssklower * Initialize ifnet structure 14650824Ssklower */ 14752828Ssklower ifp->if_name = "apc"; 14852828Ssklower ifp->if_mtu = SGMTU; 14952828Ssklower ifp->if_init = apxinit; 15052828Ssklower ifp->if_output = apxoutput; 15152828Ssklower ifp->if_start = apxstart; 15252828Ssklower ifp->if_ioctl = apxioctl; 15352828Ssklower ifp->if_reset = apxreset; 15452828Ssklower ifp->if_type = apx_default_modes.apm_iftype; 15552828Ssklower ifp->if_hdrlen = 5; 15652828Ssklower ifp->if_addrlen = 8; 15750824Ssklower if_attach(ifp); 15850824Ssklower } 15950824Ssklower /* 16050824Ssklower * Initialization of interface 16150824Ssklower */ 16250824Ssklower apxinit(unit) 16350824Ssklower int unit; 16450824Ssklower { 16550824Ssklower struct ifnet *ifp = &apx_softc[unit].apx_if; 16650824Ssklower int s = splimp(); 16750824Ssklower 16850824Ssklower ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 16950824Ssklower if (apxreset(unit) && (ifp->if_flags & IFF_UP)) { 17050824Ssklower ifp->if_flags |= IFF_RUNNING; 17150824Ssklower (void)apxstart(ifp); 17250824Ssklower } 17350824Ssklower splx(s); 17450824Ssklower return 0; 17550824Ssklower } 17650824Ssklower 17752672Ssklower apxctr(apx) 17852672Ssklower register struct apx_softc *apx; 17952672Ssklower { 18052828Ssklower int i; 18152828Ssklower APX_WCSR(apx, axr_ccr, 0xB0); /* select ctr 2, write lsb+msb, mode 0 */ 18252672Ssklower APX_WCSR(apx, axr_cnt2, 0x1); 18352672Ssklower APX_WCSR(apx, axr_cnt2, 0x0); 18452672Ssklower DELAY(50); 18552828Ssklower APX_WCSR(apx, axr_ccr, 0xE8); /* latch status, ctr 2; */ 18652828Ssklower return (APX_RCSR(apx, axr_cnt2)); 18752672Ssklower } 18852672Ssklower 18952828Ssklower void 19052828Ssklower apxtest(apx) 19152828Ssklower register struct apx_softc *apx; 19252828Ssklower { 19352828Ssklower int i = 0; 19452828Ssklower 19552828Ssklower if ((apx->apx_if.if_unit & 1) == 0 && (i = apxctr(apx)) == 0) 19652828Ssklower apxerror(apx, "no response from timer chip", 0); 19752828Ssklower if (SG_RCSR(apx, 1) & 0x8000) 19852828Ssklower SG_WCSR(apx, 1, 0x8040); 19952828Ssklower SG_WCSR(apx, 4, apx->apx_csr4); 20052828Ssklower if (apxdebug && i) { 20152828Ssklower apxerror(apx, "counter 2 value", i); 20252828Ssklower apxerror(apx, "mk5025 csr4 value", SG_RCSR(apx, 4)); 20352828Ssklower } 20452828Ssklower SG_WCSR(apx, 5, 0x08); /* Set DTR mode in SGS thompson chip */ 20552828Ssklower if (((i = SG_RCSR(apx, 5)) & 0xff08) != 0x08) 20652828Ssklower apxerror(apx, "no mk5025, csr5 high bits are", i); 20752828Ssklower else 20852828Ssklower apx->apx_flags |= APXF_CHIPHERE; 20952828Ssklower } 21052828Ssklower 21150824Ssklower apxreset(unit) 21250824Ssklower int unit; 21350824Ssklower { 21450824Ssklower register struct apx_softc *apx = &apx_softc[unit ^ 1]; 21550824Ssklower u_char apm_apxmode = 0, apm_apxaltmode = 0; 21650824Ssklower #define MODE(m) (m |= apx->apx_modes.m << ((apx->apx_if.if_unit & 1) ? 1 : 0)) 21750824Ssklower 21850824Ssklower MODE(apm_apxmode); 21950824Ssklower MODE(apm_apxaltmode); 22050824Ssklower apx = apx_softc + unit; 22150824Ssklower MODE(apm_apxmode); 22250824Ssklower MODE(apm_apxaltmode); 22350824Ssklower APX_WCSR(apx, axr_mode, apm_apxmode); 22450824Ssklower APX_WCSR(apx, axr_altmode, apm_apxaltmode); 22550825Ssklower apx->apx_txnum = apx->apx_rxnum = apx->apx_txcnt = 0; 22650824Ssklower 22750824Ssklower if (apx_uprim(apx, SG_STOP, "stop") || 22850824Ssklower !(apx->apx_if.if_flags & IFF_UP)) 22950824Ssklower return 0; 23050825Ssklower apx_meminit(apx->apx_hmem, apx); /* also sets CSR2 */ 23150824Ssklower SG_WCSR(apx, 3, (int)apx->apx_dmem); 23250824Ssklower SG_WCSR(apx, 4, apx->apx_csr4); 23350825Ssklower if (apx_uprim(apx, SG_INIT, "init request") || 23450824Ssklower apx_uprim(apx, SG_STAT, "status request") || 23550824Ssklower apx_uprim(apx, SG_TRANS, "transparent mode")) 23650824Ssklower return 0; 23752672Ssklower (void) apxctr(apx); 23850824Ssklower SG_WCSR(apx, 0, SG_INEA); 23950825Ssklower return 1; 24050824Ssklower } 24150824Ssklower 24250824Ssklower apx_uprim(apx, request, ident) 243*52830Ssklower register struct apx_softc *apx; 24450824Ssklower char *ident; 24550824Ssklower { 24650824Ssklower register int timo = 0; 247*52830Ssklower int reply; 24850824Ssklower 249*52830Ssklower if ((apx->apx_flags & APXF_CHIPHERE) == 0) 250*52830Ssklower return 1; /* maybe even should panic . . . */ 251*52830Ssklower if ((reply = SG_RCSR(apx, 1)) & 0x8040) 25252828Ssklower SG_WCSR(apx, 1, 0x8040); /* Magic! */ 25350824Ssklower SG_WCSR(apx, 1, request | SG_UAV); 25450824Ssklower do { 25552828Ssklower reply = SG_RCSR(apx, 1); 25652672Ssklower if (timo++ >= TIMO | reply & 0x8000) { 25750824Ssklower apxerror(apx, ident, reply); 25850824Ssklower return 1; 25950824Ssklower } 26050824Ssklower } while (reply & SG_UAV); 26150824Ssklower return 0; 26250824Ssklower } 26350824Ssklower 26450824Ssklower apx_meminit(apc, apx) 26550824Ssklower register struct apc_mem *apc; 26650824Ssklower struct apx_softc *apx; 26750824Ssklower { 26850824Ssklower register struct apc_mem *apcbase = apx->apx_dmem; 26950824Ssklower register int i; 27050825Ssklower #define LOWADDR(e) (((u_long)&(apcbase->e)) & 0xffff) 27150825Ssklower #define HIADDR(e) ((((u_long)&(apcbase->e)) >> 16) & 0xff) 27250824Ssklower #define SET_SGDX(dx, f, a, b, m) \ 27350824Ssklower { (dx).sgdx_addr = LOWADDR(a); (dx).sgdx_bcnt = (b);\ 27450824Ssklower (dx).sgdx_mcnt = (m); (dx).sgdx_flags = (f) | HIADDR(a); } 27550824Ssklower 27650824Ssklower bzero((caddr_t)apc, LOWADDR(apc_rxmd[0])); 27750824Ssklower apc->apc_mode = 0x8040; /* 2 flag spacing, trans mode, 16bit FCS */ 27850824Ssklower apc->apc_sgop = apx->apx_modes.apm_sgop; 27950824Ssklower apc->apc_rlen = SG_RLEN | HIADDR(apc_rxmd[0]); 28050824Ssklower apc->apc_rdra = LOWADDR(apc_rxmd[0]); 28150824Ssklower apc->apc_rlen = SG_TLEN | apx->apx_modes.apm_txwin |HIADDR(apc_txmd[0]); 28250824Ssklower apc->apc_tdra = LOWADDR(apc_txmd[0]); 28350824Ssklower SET_SGDX(apc->apc_rxtid, SG_OWN, apc_rxidbuf, -SGMTU, 0); 28450824Ssklower SET_SGDX(apc->apc_txtid, 0, apc_txidbuf, -SGMTU, 0); 28550824Ssklower apc->apc_stathi = HIADDR(apc_sgsb); 28650824Ssklower apc->apc_statlo = LOWADDR(apc_sgsb); 28750824Ssklower for (i = 0; i < SGRBUF; i++) 28850824Ssklower SET_SGDX(apc->apc_rxmd[i], SG_OWN, apc_rbuf[i][0], -SGMTU, 0) 28950824Ssklower for (i = 0; i < SGTBUF; i++) 29050824Ssklower SET_SGDX(apc->apc_txmd[i], SG_TUI, apc_tbuf[i][0], 0, 0) 29150824Ssklower SG_WCSR(apx, 2, SG_UIE | SG_PROM | HIADDR(apc_mode)); 29250824Ssklower } 29350824Ssklower 29450824Ssklower /* 29550824Ssklower * Start output on interface. Get another datagram to send 29650824Ssklower * off of the interface queue, and copy it to the interface 29750824Ssklower * before starting the output. 29850824Ssklower */ 29950824Ssklower apxstart(ifp) 30050824Ssklower struct ifnet *ifp; 30150824Ssklower { 30250824Ssklower register struct apx_softc *apx = &apx_softc[ifp->if_unit]; 30350824Ssklower register struct sgdx *dx; 30450825Ssklower struct apc_mem *apc = apx->apx_hmem; 30550824Ssklower struct mbuf *m; 30650824Ssklower int len; 30750824Ssklower 30850824Ssklower if ((ifp->if_flags & IFF_RUNNING) == 0) 30950824Ssklower return (0); 31050824Ssklower do { 31150825Ssklower dx = apc->apc_txmd + apx->apx_txnum; 31250824Ssklower if (dx->sgdx_flags & SG_OWN) 31350824Ssklower return (0); 31450824Ssklower IF_DEQUEUE(&ifp->if_snd, m); 31550824Ssklower if (m == 0) 31650824Ssklower return (0); 31750824Ssklower len = min(m->m_pkthdr.len, SGMTU); 31850825Ssklower m_copydata(m, 0, len, apc->apc_tbuf[apx->apx_txnum]); 31950824Ssklower dx->sgdx_mcnt = -len; 32050824Ssklower dx->sgdx_flags = SG_OWN | SG_TUI | (0xff & dx->sgdx_flags); 32150824Ssklower SG_WCSR(apx, 0, SG_INEA | SG_TDMD); 32250824Ssklower if (++apx->apx_txnum >= SGTBUF) 32350824Ssklower apx->apx_txnum = 0; 32450824Ssklower } while (++apx->apx_txcnt < SGTBUF); 325*52830Ssklower apx->apx_txcnt = SGTBUF; /* in case txcnt > SGTBUF by mistake */ 32650824Ssklower ifp->if_flags |= IFF_OACTIVE; 32750824Ssklower return (0); 32850824Ssklower } 32950824Ssklower 33050825Ssklower void 33150824Ssklower apxintr() 33250824Ssklower { 33352828Ssklower register struct apx_softc *apx; 33450824Ssklower int reply; 33550824Ssklower 33652828Ssklower for (apx = apx_softc + NAPX + NAPX; --apx >= apx_softc;) { 33752828Ssklower if (apx->apx_flags & APXF_CHIPHERE) 33850824Ssklower /* Try to turn off interrupt cause */ 33950824Ssklower while ((reply = SG_RCSR(apx, 0)) & 0xff) { 34050824Ssklower SG_WCSR(apx, 0, SG_INEA | 0xfe); 34150824Ssklower if (reply & (SG_MERR|SG_TUR|SG_ROR)) { 34250824Ssklower apxerror(apx, "mem, rx, or tx error", reply); 34350824Ssklower apxinit(apx->apx_if.if_unit); 34450824Ssklower break; 34550824Ssklower } 34650824Ssklower if (reply & SG_RINT) 34750824Ssklower apxrint(apx); 34850824Ssklower if (reply & SG_TINT) 34950824Ssklower apxtint(apx); 35050824Ssklower if (reply & SG_PINT) 35150824Ssklower apxstat.pint++; 35250824Ssklower } 35352828Ssklower } 35450824Ssklower } 35550824Ssklower 35650825Ssklower void 35750824Ssklower apxtint(apx) 35850824Ssklower register struct apx_softc *apx; 35950824Ssklower { 36050825Ssklower register struct apc_mem *apc = apx->apx_hmem; 36150824Ssklower int i, loopcount = 0; 36250824Ssklower 36350824Ssklower do { 36450824Ssklower if ((i = apx->apx_txnum - apx->apx_txcnt) < 0) 36550824Ssklower i += SGTBUF; 36650824Ssklower if (apc->apc_txmd[i].sgdx_flags & SG_OWN) { 36750824Ssklower if (loopcount) 36850824Ssklower break; 36950824Ssklower apxstat.nulltx++; 37050824Ssklower return; 37150824Ssklower } 37250824Ssklower loopcount++; 37350824Ssklower apx->apx_if.if_flags &= ~IFF_OACTIVE; 37450824Ssklower } while (--apx->apx_txcnt > 0); 37550824Ssklower apxstart(&apx->apx_if); 37650824Ssklower } 37750824Ssklower 37852828Ssklower void 37950824Ssklower apxrint(apx) 38050824Ssklower register struct apx_softc *apx; 38150824Ssklower { 38250825Ssklower register struct apc_mem *apc = apx->apx_hmem; 38350824Ssklower register struct sgdx *dx = apc->apc_rxmd + apx->apx_rxnum; 38450824Ssklower #define SGNEXTRXMD \ 38550824Ssklower dx = ++apx->apx_rxnum == SGRBUF ? &apc->apc_rxmd[apx->apx_rxnum = 0] : dx + 1; 38650824Ssklower 38750824Ssklower /* 38850824Ssklower * Out of sync with hardware, should never happen? 38950824Ssklower */ 39050824Ssklower if (dx->sgdx_flags & SG_OWN) { 391*52830Ssklower apxerror(apx, "out of sync", apx->apx_rxnum); 39250824Ssklower return; 39350824Ssklower } 39450824Ssklower /* 39550824Ssklower * Process all buffers with valid data 39650824Ssklower */ 39750824Ssklower while ((dx->sgdx_flags & SG_OWN) == 0) { 39850824Ssklower if ((dx->sgdx_flags & (SG_SLF|SG_ELF)) != (SG_SLF|SG_ELF)) { 39950824Ssklower /* 40050824Ssklower * Find the end of the packet so we can see how long 40150824Ssklower * it was. We still throw it away. 40250824Ssklower */ 40350825Ssklower apxerror(apx, "chained buffer", dx->sgdx_flags); 40450824Ssklower do { 40550824Ssklower dx->sgdx_bcnt = 0; 40650824Ssklower dx->sgdx_flags = SG_OWN | (0xff&dx->sgdx_flags); 40750824Ssklower SGNEXTRXMD; 40850824Ssklower } while (!(dx->sgdx_flags & (SG_OWN|SG_SLF|SG_ELF))); 40950824Ssklower /* 41050824Ssklower * If search terminated without successful completion 41150824Ssklower * we reset the hardware (conservative). 41250824Ssklower */ 41350824Ssklower if ((dx->sgdx_flags & (SG_OWN|SG_SLF|SG_ELF)) != 41450825Ssklower SG_ELF) { 41550824Ssklower apxreset(apx->apx_if.if_unit); 41650824Ssklower return; 41750824Ssklower } 41850824Ssklower } else 41950824Ssklower apxinput(&apx->apx_if, apc->apc_rbuf[apx->apx_rxnum], 42050824Ssklower -dx->sgdx_bcnt); 42150824Ssklower dx->sgdx_bcnt = 0; 42250824Ssklower dx->sgdx_flags = SG_OWN | (0xff & dx->sgdx_flags); 42350824Ssklower SGNEXTRXMD; 42450824Ssklower } 42550824Ssklower } 42650824Ssklower 42750825Ssklower void 42850824Ssklower apxinput(ifp, buffer, len) 429*52830Ssklower register struct ifnet *ifp; 430*52830Ssklower caddr_t buffer; 43150824Ssklower { 432*52830Ssklower extern struct ifqueue hdintrq, ipintrq; 43350824Ssklower register struct ifqueue *inq; 434*52830Ssklower register u_char *cp = (u_char *)buffer; 43552672Ssklower struct mbuf *m, *m_devget(); 43650824Ssklower int isr; 43750824Ssklower 43850824Ssklower ifp->if_ipackets++; 43950824Ssklower if (cp[0] == 0xff && cp[1] == 0x3) { 44050824Ssklower /* This is a UI HDLC Packet, so we'll assume PPP 44150824Ssklower protocol. for now, IP only. */ 44250824Ssklower buffer += 4; 44350824Ssklower len -= 4; 44450824Ssklower inq = &ipintrq; 44550824Ssklower isr = NETISR_IP; 44650824Ssklower } else { 447*52830Ssklower #ifdef CCITT 44850824Ssklower inq = &hdintrq; 44950824Ssklower isr = NETISR_CCITT; 45050824Ssklower } 451*52830Ssklower if (len <= 0) { 452*52830Ssklower #endif 45350824Ssklower return; 454*52830Ssklower } 45552672Ssklower m = m_devget(buffer, len, 0, ifp, (void (*)())0); 45650824Ssklower if (m == 0) 45750824Ssklower return; 45850824Ssklower if(IF_QFULL(inq)) { 45950824Ssklower IF_DROP(inq); 46050824Ssklower m_freem(m); 46150824Ssklower } else { 46250824Ssklower IF_ENQUEUE(inq, m); 46350824Ssklower schednetisr(isr); 46450824Ssklower } 46550824Ssklower } 46650824Ssklower 46750824Ssklower /* 46850824Ssklower * Process an ioctl request. 46950824Ssklower */ 47050824Ssklower apxioctl(ifp, cmd, data) 47150824Ssklower register struct ifnet *ifp; 47250824Ssklower int cmd; 47350824Ssklower caddr_t data; 47450824Ssklower { 47550824Ssklower register struct ifaddr *ifa = (struct ifaddr *)data; 47650824Ssklower int s = splimp(), error = 0; 47750824Ssklower struct apx_softc *apx = &apx_softc[ifp->if_unit]; 47850824Ssklower 47950824Ssklower switch (cmd) { 48052828Ssklower 48152828Ssklower case SIOCSIFADDR: 48252828Ssklower #ifdef CCITT 48352828Ssklower ifa->ifa_rtrequest = x25_rtrequest; 48452828Ssklower break; 48552828Ssklower 48650824Ssklower case SIOCSIFCONF_X25: 48752828Ssklower ifp->if_output = x25_ifoutput; 48850824Ssklower ifp->if_flags |= IFF_UP; 48950824Ssklower error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); 49050824Ssklower if (error == 0) 49150824Ssklower apxinit(ifp->if_unit); 49252828Ssklower #endif 49350824Ssklower break; 49450824Ssklower 49550824Ssklower case SIOCSIFFLAGS: 49650824Ssklower if (((ifp->if_flags & IFF_UP) == 0 && 49750824Ssklower (ifp->if_flags & IFF_RUNNING)) || 49850824Ssklower (ifp->if_flags & IFF_UP) && 49950824Ssklower (ifp->if_flags & IFF_RUNNING) == 0) 50050824Ssklower apxinit(ifp->if_unit); 50150824Ssklower break; 50250824Ssklower 50350824Ssklower case SIOCSIFMODE: 50450824Ssklower if ((ifp->if_flags & IFF_UP) == 0) 50550825Ssklower apx->apx_modes = *(struct apc_modes *)data; 50650824Ssklower else 50750824Ssklower default: 50850824Ssklower error = EINVAL; 50950824Ssklower 51050824Ssklower } 51150824Ssklower splx(s); 51250824Ssklower return (error); 51350824Ssklower } 51450824Ssklower 51550824Ssklower apxerror(apx, msg, data) 51650824Ssklower register struct apx_softc *apx; 51750824Ssklower char *msg; 51850824Ssklower { 51950824Ssklower log(LOG_WARNING, "apc%d: %s, stat=0x%x\n", 52050824Ssklower apx->apx_if.if_unit, msg, data); 52150824Ssklower } 52252828Ssklower /* 52352828Ssklower * For debugging loopback activity. 52452828Ssklower */ 52552828Ssklower static char pppheader[4] = { -1, 3, 0, 0x21 }; 52652828Ssklower 52752828Ssklower apxoutput(ifp, m, dst, rt) 52852828Ssklower register struct ifnet *ifp; 52952828Ssklower register struct mbuf *m; 53052828Ssklower struct sockaddr *dst; 53152828Ssklower struct rtentry *rt; 53252828Ssklower { 53352828Ssklower /* 53452828Ssklower * Queue message on interface, and start output if interface 53552828Ssklower * not yet active. 53652828Ssklower */ 53752828Ssklower int s = splimp(), error = 0; 53852828Ssklower M_PREPEND(m, sizeof pppheader, M_DONTWAIT); 53952828Ssklower if (m == 0) { 54052828Ssklower splx(s); 54152828Ssklower return ENOBUFS; 54252828Ssklower } 54352828Ssklower bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader); 54452828Ssklower if (IF_QFULL(&ifp->if_snd)) { 54552828Ssklower IF_DROP(&ifp->if_snd); 54652828Ssklower /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", 54752828Ssklower ifp->if_name, ifp->if_unit);*/ 54852828Ssklower m_freem(m); 54952828Ssklower error = ENOBUFS; 55052828Ssklower } else { 55152828Ssklower IF_ENQUEUE(&ifp->if_snd, m); 55252828Ssklower if ((ifp->if_flags & IFF_OACTIVE) == 0) 55352828Ssklower (*ifp->if_start)(ifp); 55452828Ssklower } 55552828Ssklower splx(s); 55652828Ssklower return (error); 55752828Ssklower } 55852828Ssklower 55950824Ssklower #endif /* NAPX */ 560