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*52828Ssklower * @(#)if_apx.c 7.4 (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" 33*52828Ssklower #ifdef CCITT 3450824Ssklower #include "netccitt/x25.h" 35*52828Ssklower int x25_rtrequest(), x25_ifoutput(); 36*52828Ssklower #endif 3750824Ssklower 3850825Ssklower #include "if_apxreg.h" 3950824Ssklower 4050824Ssklower int apxprobe(), apxattach(), apxstart(), apx_uprim(), apx_meminit(); 41*52828Ssklower int apxinit(), apxoutput(), apxioctl(), apxreset(), apxdebug = 1; 42*52828Ssklower void apx_ifattach(), apxtest(), apxinput(), apxintr(), apxtint(), apxrint(); 4350824Ssklower 4450824Ssklower struct apx_softc { 4550824Ssklower struct ifnet apx_if; 46*52828Ssklower 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 */ 51*52828Ssklower int apx_flags; /* Flags specific to this driver */ 52*52828Ssklower #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*52828Ssklower u_short apx_csr4; /* byte gender, set in mach dep code */ 57*52828Ssklower struct apc_modes apx_modes; /* Parameters, as amended by ioctls */ 58*52828Ssklower } 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 10950824Ssklower for (subunit = 0; subunit < 2; subunit++, apx++) { 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; 115*52828Ssklower apx->apx_sgcp = reg->axr_sgcp + subunit; 116*52828Ssklower apx->apx_csr4 = 0x0210; /* no byte swapping for PC-AT */ 117*52828Ssklower apx->apx_modes = apx_default_modes; 118*52828Ssklower apx->apx_if.if_unit = unit++; 119*52828Ssklower apxtest(apx); 12050824Ssklower } 12150824Ssklower return 1; 12250824Ssklower } 12350824Ssklower 12450824Ssklower apxattach(id) 12550824Ssklower register struct isa_device *id; 12650824Ssklower { 127*52828Ssklower int unit = id->id_unit << 1; 12850824Ssklower 12950824Ssklower apx_ifattach(unit); 13050824Ssklower apx_ifattach(unit + 1); 131*52828Ssklower 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 14150824Ssklower apx_ifattach(unit) 14250824Ssklower { 14350824Ssklower register struct ifnet *ifp = &(apx_softc[unit].apx_if); 14450824Ssklower /* 14550824Ssklower * Initialize ifnet structure 14650824Ssklower */ 14750824Ssklower if (apx_softc[unit].apx_device == 0) 14850824Ssklower return; 149*52828Ssklower ifp->if_name = "apc"; 150*52828Ssklower ifp->if_mtu = SGMTU; 151*52828Ssklower ifp->if_init = apxinit; 152*52828Ssklower ifp->if_output = apxoutput; 153*52828Ssklower ifp->if_start = apxstart; 154*52828Ssklower ifp->if_ioctl = apxioctl; 155*52828Ssklower ifp->if_reset = apxreset; 156*52828Ssklower ifp->if_type = apx_default_modes.apm_iftype; 157*52828Ssklower ifp->if_hdrlen = 5; 158*52828Ssklower ifp->if_addrlen = 8; 15950824Ssklower if_attach(ifp); 16050824Ssklower } 16150824Ssklower /* 16250824Ssklower * Initialization of interface 16350824Ssklower */ 16450824Ssklower apxinit(unit) 16550824Ssklower int unit; 16650824Ssklower { 16750824Ssklower struct ifnet *ifp = &apx_softc[unit].apx_if; 16850824Ssklower int s = splimp(); 16950824Ssklower 17050824Ssklower ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 17150824Ssklower if (apxreset(unit) && (ifp->if_flags & IFF_UP)) { 17250824Ssklower ifp->if_flags |= IFF_RUNNING; 17350824Ssklower (void)apxstart(ifp); 17450824Ssklower } 17550824Ssklower splx(s); 17650824Ssklower return 0; 17750824Ssklower } 17850824Ssklower 17952672Ssklower apxctr(apx) 18052672Ssklower register struct apx_softc *apx; 18152672Ssklower { 182*52828Ssklower int i; 183*52828Ssklower APX_WCSR(apx, axr_ccr, 0xB0); /* select ctr 2, write lsb+msb, mode 0 */ 18452672Ssklower APX_WCSR(apx, axr_cnt2, 0x1); 18552672Ssklower APX_WCSR(apx, axr_cnt2, 0x0); 18652672Ssklower DELAY(50); 187*52828Ssklower APX_WCSR(apx, axr_ccr, 0xE8); /* latch status, ctr 2; */ 188*52828Ssklower return (APX_RCSR(apx, axr_cnt2)); 18952672Ssklower } 19052672Ssklower 191*52828Ssklower void 192*52828Ssklower apxtest(apx) 193*52828Ssklower register struct apx_softc *apx; 194*52828Ssklower { 195*52828Ssklower int i = 0; 196*52828Ssklower 197*52828Ssklower if ((apx->apx_if.if_unit & 1) == 0 && (i = apxctr(apx)) == 0) 198*52828Ssklower apxerror(apx, "no response from timer chip", 0); 199*52828Ssklower if (SG_RCSR(apx, 1) & 0x8000) 200*52828Ssklower SG_WCSR(apx, 1, 0x8040); 201*52828Ssklower SG_WCSR(apx, 4, apx->apx_csr4); 202*52828Ssklower if (apxdebug && i) { 203*52828Ssklower apxerror(apx, "counter 2 value", i); 204*52828Ssklower apxerror(apx, "mk5025 csr4 value", SG_RCSR(apx, 4)); 205*52828Ssklower } 206*52828Ssklower SG_WCSR(apx, 5, 0x08); /* Set DTR mode in SGS thompson chip */ 207*52828Ssklower if (((i = SG_RCSR(apx, 5)) & 0xff08) != 0x08) 208*52828Ssklower apxerror(apx, "no mk5025, csr5 high bits are", i); 209*52828Ssklower else 210*52828Ssklower apx->apx_flags |= APXF_CHIPHERE; 211*52828Ssklower } 212*52828Ssklower 21350824Ssklower apxreset(unit) 21450824Ssklower int unit; 21550824Ssklower { 21650824Ssklower register struct apx_softc *apx = &apx_softc[unit ^ 1]; 21750824Ssklower u_char apm_apxmode = 0, apm_apxaltmode = 0; 21850824Ssklower #define MODE(m) (m |= apx->apx_modes.m << ((apx->apx_if.if_unit & 1) ? 1 : 0)) 21950824Ssklower 22050824Ssklower MODE(apm_apxmode); 22150824Ssklower MODE(apm_apxaltmode); 22250824Ssklower apx = apx_softc + unit; 22350824Ssklower MODE(apm_apxmode); 22450824Ssklower MODE(apm_apxaltmode); 22550824Ssklower APX_WCSR(apx, axr_mode, apm_apxmode); 22650824Ssklower APX_WCSR(apx, axr_altmode, apm_apxaltmode); 22750825Ssklower apx->apx_txnum = apx->apx_rxnum = apx->apx_txcnt = 0; 22850824Ssklower 22950824Ssklower if (apx_uprim(apx, SG_STOP, "stop") || 23050824Ssklower !(apx->apx_if.if_flags & IFF_UP)) 23150824Ssklower return 0; 23250825Ssklower apx_meminit(apx->apx_hmem, apx); /* also sets CSR2 */ 23350824Ssklower SG_WCSR(apx, 3, (int)apx->apx_dmem); 23450824Ssklower SG_WCSR(apx, 4, apx->apx_csr4); 23550825Ssklower if (apx_uprim(apx, SG_INIT, "init request") || 23650824Ssklower apx_uprim(apx, SG_STAT, "status request") || 23750824Ssklower apx_uprim(apx, SG_TRANS, "transparent mode")) 23850824Ssklower return 0; 23952672Ssklower (void) apxctr(apx); 24050824Ssklower SG_WCSR(apx, 0, SG_INEA); 24150825Ssklower return 1; 24250824Ssklower } 24350824Ssklower 24450824Ssklower apx_uprim(apx, request, ident) 24550824Ssklower int request; 24650824Ssklower char *ident; 24750824Ssklower register struct apx_softc *apx; 24850824Ssklower { 24950824Ssklower register int timo = 0; 25050824Ssklower int reply = SG_RCSR(apx, 1); 25150824Ssklower 25250825Ssklower if (reply & 0x8040) 253*52828Ssklower SG_WCSR(apx, 1, 0x8040); /* Magic! */ 25450824Ssklower SG_WCSR(apx, 1, request | SG_UAV); 25550824Ssklower do { 256*52828Ssklower reply = SG_RCSR(apx, 1); 25752672Ssklower if (timo++ >= TIMO | reply & 0x8000) { 25850824Ssklower apxerror(apx, ident, reply); 25950824Ssklower return 1; 26050824Ssklower } 26150824Ssklower } while (reply & SG_UAV); 26250824Ssklower return 0; 26350824Ssklower } 26450824Ssklower 26550824Ssklower apx_meminit(apc, apx) 26650824Ssklower register struct apc_mem *apc; 26750824Ssklower struct apx_softc *apx; 26850824Ssklower { 26950824Ssklower register struct apc_mem *apcbase = apx->apx_dmem; 27050824Ssklower register int i; 27150825Ssklower #define LOWADDR(e) (((u_long)&(apcbase->e)) & 0xffff) 27250825Ssklower #define HIADDR(e) ((((u_long)&(apcbase->e)) >> 16) & 0xff) 27350824Ssklower #define SET_SGDX(dx, f, a, b, m) \ 27450824Ssklower { (dx).sgdx_addr = LOWADDR(a); (dx).sgdx_bcnt = (b);\ 27550824Ssklower (dx).sgdx_mcnt = (m); (dx).sgdx_flags = (f) | HIADDR(a); } 27650824Ssklower 27750824Ssklower bzero((caddr_t)apc, LOWADDR(apc_rxmd[0])); 27850824Ssklower apc->apc_mode = 0x8040; /* 2 flag spacing, trans mode, 16bit FCS */ 27950824Ssklower apc->apc_sgop = apx->apx_modes.apm_sgop; 28050824Ssklower apc->apc_rlen = SG_RLEN | HIADDR(apc_rxmd[0]); 28150824Ssklower apc->apc_rdra = LOWADDR(apc_rxmd[0]); 28250824Ssklower apc->apc_rlen = SG_TLEN | apx->apx_modes.apm_txwin |HIADDR(apc_txmd[0]); 28350824Ssklower apc->apc_tdra = LOWADDR(apc_txmd[0]); 28450824Ssklower SET_SGDX(apc->apc_rxtid, SG_OWN, apc_rxidbuf, -SGMTU, 0); 28550824Ssklower SET_SGDX(apc->apc_txtid, 0, apc_txidbuf, -SGMTU, 0); 28650824Ssklower apc->apc_stathi = HIADDR(apc_sgsb); 28750824Ssklower apc->apc_statlo = LOWADDR(apc_sgsb); 28850824Ssklower for (i = 0; i < SGRBUF; i++) 28950824Ssklower SET_SGDX(apc->apc_rxmd[i], SG_OWN, apc_rbuf[i][0], -SGMTU, 0) 29050824Ssklower for (i = 0; i < SGTBUF; i++) 29150824Ssklower SET_SGDX(apc->apc_txmd[i], SG_TUI, apc_tbuf[i][0], 0, 0) 29250824Ssklower SG_WCSR(apx, 2, SG_UIE | SG_PROM | HIADDR(apc_mode)); 29350824Ssklower } 29450824Ssklower 29550824Ssklower /* 29650824Ssklower * Start output on interface. Get another datagram to send 29750824Ssklower * off of the interface queue, and copy it to the interface 29850824Ssklower * before starting the output. 29950824Ssklower */ 30050824Ssklower apxstart(ifp) 30150824Ssklower struct ifnet *ifp; 30250824Ssklower { 30350824Ssklower register struct apx_softc *apx = &apx_softc[ifp->if_unit]; 30450824Ssklower register struct sgdx *dx; 30550825Ssklower struct apc_mem *apc = apx->apx_hmem; 30650824Ssklower struct mbuf *m; 30750824Ssklower int len; 30850824Ssklower 30950824Ssklower if ((ifp->if_flags & IFF_RUNNING) == 0) 31050824Ssklower return (0); 31150824Ssklower do { 31250825Ssklower dx = apc->apc_txmd + apx->apx_txnum; 31350824Ssklower if (dx->sgdx_flags & SG_OWN) 31450824Ssklower return (0); 31550824Ssklower IF_DEQUEUE(&ifp->if_snd, m); 31650824Ssklower if (m == 0) 31750824Ssklower return (0); 31850824Ssklower len = min(m->m_pkthdr.len, SGMTU); 31950825Ssklower m_copydata(m, 0, len, apc->apc_tbuf[apx->apx_txnum]); 32050824Ssklower dx->sgdx_mcnt = -len; 32150824Ssklower dx->sgdx_flags = SG_OWN | SG_TUI | (0xff & dx->sgdx_flags); 32250824Ssklower SG_WCSR(apx, 0, SG_INEA | SG_TDMD); 32350824Ssklower if (++apx->apx_txnum >= SGTBUF) 32450824Ssklower apx->apx_txnum = 0; 32550824Ssklower } while (++apx->apx_txcnt < SGTBUF); 32650824Ssklower apx->apx_txcnt = SGTBUF; 32750824Ssklower ifp->if_flags |= IFF_OACTIVE; 32850824Ssklower return (0); 32950824Ssklower } 33050824Ssklower 33150825Ssklower void 33250824Ssklower apxintr() 33350824Ssklower { 334*52828Ssklower register struct apx_softc *apx; 33550824Ssklower int reply; 33650824Ssklower 337*52828Ssklower for (apx = apx_softc + NAPX + NAPX; --apx >= apx_softc;) { 338*52828Ssklower if (apx->apx_flags & APXF_CHIPHERE) 33950824Ssklower /* Try to turn off interrupt cause */ 34050824Ssklower while ((reply = SG_RCSR(apx, 0)) & 0xff) { 34150824Ssklower SG_WCSR(apx, 0, SG_INEA | 0xfe); 34250824Ssklower if (reply & (SG_MERR|SG_TUR|SG_ROR)) { 34350824Ssklower apxerror(apx, "mem, rx, or tx error", reply); 34450824Ssklower apxinit(apx->apx_if.if_unit); 34550824Ssklower break; 34650824Ssklower } 34750824Ssklower if (reply & SG_RINT) 34850824Ssklower apxrint(apx); 34950824Ssklower if (reply & SG_TINT) 35050824Ssklower apxtint(apx); 35150824Ssklower if (reply & SG_PINT) 35250824Ssklower apxstat.pint++; 35350824Ssklower } 354*52828Ssklower } 35550824Ssklower } 35650824Ssklower 35750825Ssklower void 35850824Ssklower apxtint(apx) 35950824Ssklower register struct apx_softc *apx; 36050824Ssklower { 36150825Ssklower register struct apc_mem *apc = apx->apx_hmem; 36250824Ssklower int i, loopcount = 0; 36350824Ssklower 36450824Ssklower do { 36550824Ssklower if ((i = apx->apx_txnum - apx->apx_txcnt) < 0) 36650824Ssklower i += SGTBUF; 36750824Ssklower if (apc->apc_txmd[i].sgdx_flags & SG_OWN) { 36850824Ssklower if (loopcount) 36950824Ssklower break; 37050824Ssklower apxstat.nulltx++; 37150824Ssklower return; 37250824Ssklower } 37350824Ssklower loopcount++; 37450824Ssklower apx->apx_if.if_flags &= ~IFF_OACTIVE; 37550824Ssklower } while (--apx->apx_txcnt > 0); 37650824Ssklower apxstart(&apx->apx_if); 37750824Ssklower } 37850824Ssklower 379*52828Ssklower void 38050824Ssklower apxrint(apx) 38150824Ssklower register struct apx_softc *apx; 38250824Ssklower { 38350825Ssklower register struct apc_mem *apc = apx->apx_hmem; 38450824Ssklower register struct sgdx *dx = apc->apc_rxmd + apx->apx_rxnum; 38550824Ssklower #define SGNEXTRXMD \ 38650824Ssklower dx = ++apx->apx_rxnum == SGRBUF ? &apc->apc_rxmd[apx->apx_rxnum = 0] : dx + 1; 38750824Ssklower 38850824Ssklower /* 38950824Ssklower * Out of sync with hardware, should never happen? 39050824Ssklower */ 39150824Ssklower if (dx->sgdx_flags & SG_OWN) { 39250824Ssklower apxerror(apx, "out of sync"); 39350824Ssklower return; 39450824Ssklower } 39550824Ssklower /* 39650824Ssklower * Process all buffers with valid data 39750824Ssklower */ 39850824Ssklower while ((dx->sgdx_flags & SG_OWN) == 0) { 39950824Ssklower if ((dx->sgdx_flags & (SG_SLF|SG_ELF)) != (SG_SLF|SG_ELF)) { 40050824Ssklower /* 40150824Ssklower * Find the end of the packet so we can see how long 40250824Ssklower * it was. We still throw it away. 40350824Ssklower */ 40450825Ssklower apxerror(apx, "chained buffer", dx->sgdx_flags); 40550824Ssklower do { 40650824Ssklower dx->sgdx_bcnt = 0; 40750824Ssklower dx->sgdx_flags = SG_OWN | (0xff&dx->sgdx_flags); 40850824Ssklower SGNEXTRXMD; 40950824Ssklower } while (!(dx->sgdx_flags & (SG_OWN|SG_SLF|SG_ELF))); 41050824Ssklower /* 41150824Ssklower * If search terminated without successful completion 41250824Ssklower * we reset the hardware (conservative). 41350824Ssklower */ 41450824Ssklower if ((dx->sgdx_flags & (SG_OWN|SG_SLF|SG_ELF)) != 41550825Ssklower SG_ELF) { 41650824Ssklower apxreset(apx->apx_if.if_unit); 41750824Ssklower return; 41850824Ssklower } 41950824Ssklower } else 42050824Ssklower apxinput(&apx->apx_if, apc->apc_rbuf[apx->apx_rxnum], 42150824Ssklower -dx->sgdx_bcnt); 42250824Ssklower dx->sgdx_bcnt = 0; 42350824Ssklower dx->sgdx_flags = SG_OWN | (0xff & dx->sgdx_flags); 42450824Ssklower SGNEXTRXMD; 42550824Ssklower } 42650824Ssklower } 42750824Ssklower 42850825Ssklower void 42950824Ssklower apxinput(ifp, buffer, len) 43050824Ssklower register struct ifnet *ifp; 43150824Ssklower caddr_t buffer; 43250824Ssklower { 43350824Ssklower register struct ifqueue *inq; 43452672Ssklower struct mbuf *m, *m_devget(); 43550824Ssklower extern struct ifqueue hdintrq, ipintrq; 43650824Ssklower int isr; 43750824Ssklower 43850824Ssklower ifp->if_ipackets++; 43950824Ssklower { 44050824Ssklower register u_char *cp = (u_char *)buffer; 44150824Ssklower 44250824Ssklower if (cp[0] == 0xff && cp[1] == 0x3) { 44350824Ssklower /* This is a UI HDLC Packet, so we'll assume PPP 44450824Ssklower protocol. for now, IP only. */ 44550824Ssklower buffer += 4; 44650824Ssklower len -= 4; 44750824Ssklower inq = &ipintrq; 44850824Ssklower isr = NETISR_IP; 44950824Ssklower } else { 45050824Ssklower inq = &hdintrq; 45150824Ssklower isr = NETISR_CCITT; 45250824Ssklower } 45350824Ssklower } 45450824Ssklower if (len <= 0) 45550824Ssklower return; 45650824Ssklower 45752672Ssklower m = m_devget(buffer, len, 0, ifp, (void (*)())0); 45850824Ssklower if (m == 0) 45950824Ssklower return; 46050824Ssklower 46150824Ssklower if(IF_QFULL(inq)) { 46250824Ssklower IF_DROP(inq); 46350824Ssklower m_freem(m); 46450824Ssklower } else { 46550824Ssklower IF_ENQUEUE(inq, m); 46650824Ssklower schednetisr(isr); 46750824Ssklower } 46850824Ssklower } 46950824Ssklower 47050824Ssklower /* 47150824Ssklower * Process an ioctl request. 47250824Ssklower */ 47350824Ssklower apxioctl(ifp, cmd, data) 47450824Ssklower register struct ifnet *ifp; 47550824Ssklower int cmd; 47650824Ssklower caddr_t data; 47750824Ssklower { 47850824Ssklower register struct ifaddr *ifa = (struct ifaddr *)data; 47950824Ssklower int s = splimp(), error = 0; 48050824Ssklower struct apx_softc *apx = &apx_softc[ifp->if_unit]; 48150824Ssklower 48250824Ssklower switch (cmd) { 483*52828Ssklower 484*52828Ssklower case SIOCSIFADDR: 485*52828Ssklower #ifdef CCITT 486*52828Ssklower ifa->ifa_rtrequest = x25_rtrequest; 487*52828Ssklower break; 488*52828Ssklower 48950824Ssklower case SIOCSIFCONF_X25: 490*52828Ssklower ifp->if_output = x25_ifoutput; 49150824Ssklower ifp->if_flags |= IFF_UP; 49250824Ssklower error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); 49350824Ssklower if (error == 0) 49450824Ssklower apxinit(ifp->if_unit); 495*52828Ssklower #endif 49650824Ssklower break; 49750824Ssklower 49850824Ssklower case SIOCSIFFLAGS: 49950824Ssklower if (((ifp->if_flags & IFF_UP) == 0 && 50050824Ssklower (ifp->if_flags & IFF_RUNNING)) || 50150824Ssklower (ifp->if_flags & IFF_UP) && 50250824Ssklower (ifp->if_flags & IFF_RUNNING) == 0) 50350824Ssklower apxinit(ifp->if_unit); 50450824Ssklower break; 50550824Ssklower 50650824Ssklower case SIOCSIFMODE: 50750824Ssklower if ((ifp->if_flags & IFF_UP) == 0) 50850825Ssklower apx->apx_modes = *(struct apc_modes *)data; 50950824Ssklower else 51050824Ssklower default: 51150824Ssklower error = EINVAL; 51250824Ssklower 51350824Ssklower } 51450824Ssklower splx(s); 51550824Ssklower return (error); 51650824Ssklower } 51750824Ssklower 51850824Ssklower apxerror(apx, msg, data) 51950824Ssklower register struct apx_softc *apx; 52050824Ssklower char *msg; 52150824Ssklower { 52250824Ssklower log(LOG_WARNING, "apc%d: %s, stat=0x%x\n", 52350824Ssklower apx->apx_if.if_unit, msg, data); 52450824Ssklower } 525*52828Ssklower /* 526*52828Ssklower * For debugging loopback activity. 527*52828Ssklower */ 528*52828Ssklower static char pppheader[4] = { -1, 3, 0, 0x21 }; 529*52828Ssklower 530*52828Ssklower apxoutput(ifp, m, dst, rt) 531*52828Ssklower register struct ifnet *ifp; 532*52828Ssklower register struct mbuf *m; 533*52828Ssklower struct sockaddr *dst; 534*52828Ssklower struct rtentry *rt; 535*52828Ssklower { 536*52828Ssklower /* 537*52828Ssklower * Queue message on interface, and start output if interface 538*52828Ssklower * not yet active. 539*52828Ssklower */ 540*52828Ssklower int s = splimp(), error = 0; 541*52828Ssklower M_PREPEND(m, sizeof pppheader, M_DONTWAIT); 542*52828Ssklower if (m == 0) { 543*52828Ssklower splx(s); 544*52828Ssklower return ENOBUFS; 545*52828Ssklower } 546*52828Ssklower bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader); 547*52828Ssklower if (IF_QFULL(&ifp->if_snd)) { 548*52828Ssklower IF_DROP(&ifp->if_snd); 549*52828Ssklower /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", 550*52828Ssklower ifp->if_name, ifp->if_unit);*/ 551*52828Ssklower m_freem(m); 552*52828Ssklower error = ENOBUFS; 553*52828Ssklower } else { 554*52828Ssklower IF_ENQUEUE(&ifp->if_snd, m); 555*52828Ssklower if ((ifp->if_flags & IFF_OACTIVE) == 0) 556*52828Ssklower (*ifp->if_start)(ifp); 557*52828Ssklower } 558*52828Ssklower splx(s); 559*52828Ssklower return (error); 560*52828Ssklower } 561*52828Ssklower 56250824Ssklower #endif /* NAPX */ 563