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*52672Ssklower * @(#)if_apx.c 7.3 (Berkeley) 02/25/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" 3350824Ssklower #include "netccitt/x25.h" 3450824Ssklower 3550825Ssklower #include "if_apxreg.h" 3650824Ssklower 3750824Ssklower int apxprobe(), apxattach(), apxstart(), apx_uprim(), apx_meminit(); 3850825Ssklower int apxinit(), x25_ifoutput(), x25_rtrequest(), apxioctl(), apxreset(); 39*52672Ssklower int apxctr(); 4050824Ssklower void apx_ifattach(), apxinput(), apxintr(), apxtint(), apaxrint(); 4150824Ssklower 4250824Ssklower struct apx_softc { 4350824Ssklower struct ifnet apx_if; 4450824Ssklower caddr_t apx_device; /* e.g. isa_device */ 4550824Ssklower u_short apx_csr4; /* byte gender, set in mach dep code */ 4650824Ssklower struct apc_reg *apx_reg; /* control regs for both subunits */ 4750824Ssklower struct apc_mem *apx_hmem; /* Host addr for shared memory */ 4850824Ssklower struct apc_mem *apx_dmem; /* Device (chip) addr for shared mem */ 4950824Ssklower struct sgcp *apx_sgcp; /* IO control port for this subunit */ 5050824Ssklower struct apc_modes apx_modes; /* Parameters, as amended by ioctls */ 5150824Ssklower int apx_rxnum; /* Last receiver dx we looked at */ 5250824Ssklower int apx_txnum; /* Last tranmistter dx we stomped on */ 5350824Ssklower int apx_txcnt; /* Number of packets queued for tx*/ 5450824Ssklower } apx_softc[2 * NAPX], *apx_lastsoftc = apx_softc; 5550824Ssklower 5650824Ssklower struct apxstat { 5750824Ssklower int nulltx; 5850824Ssklower int pint; 5950825Ssklower } apxstat; 6050824Ssklower 6150824Ssklower /* default operating paramters for devices */ 6250824Ssklower struct apc_modes apx_default_modes = { 6350824Ssklower { 1, /* apm_sgob.lsaddr; */ 6450824Ssklower 3, /* apm_sgob.rsaddr; */ 6550824Ssklower -SGMTU, /* apm_sgob.n1; */ 6650824Ssklower ((-10)<<8), /* apm_sgob.n2_scale; */ 6750824Ssklower -1250, /* apm_sgob.t1; */ 6850824Ssklower -10000, /* apm_sgob.t3; */ 6950824Ssklower -80, /* apm_sgob.tp; */ 7050824Ssklower }, 7150824Ssklower 2, /* apm_txwin; */ 7250824Ssklower 5, /* apm_apxmode; */ 7350824Ssklower 0, /* apm_apxaltmode; */ 7450824Ssklower IFT_X25, /* apm_iftype; */ 7550824Ssklower }; 7650824Ssklower 7750824Ssklower /* Begin bus & endian dependence */ 7850824Ssklower 7950825Ssklower #include "isa_device.h" 8050824Ssklower 8150824Ssklower struct isa_driver apxdriver = { 8250824Ssklower apxprobe, apxattach, "apx", 8350824Ssklower }; 8450824Ssklower 8550824Ssklower #define SG_RCSR(apx, csrnum) \ 8650825Ssklower (outw(&(apx->apx_sgcp->sgcp_rap), csrnum << 1), \ 8750825Ssklower inw(&(apx->apx_sgcp->sgcp_rdp))) 8850824Ssklower 8950824Ssklower #define SG_WCSR(apx, csrnum, data) \ 9050825Ssklower (outw(&(apx->apx_sgcp->sgcp_rap), csrnum << 1), \ 9150824Ssklower outw(&(apx->apx_sgcp->sgcp_rdp), data)) 9250824Ssklower 9350824Ssklower #define APX_RCSR(apx, csrname) inb(&(apx->apx_reg->csrname)) 9450824Ssklower #define APX_WCSR(apx, csrname, data) outb(&(apx->apx_reg->csrname), data) 9550824Ssklower 9650824Ssklower #define TIMO 10000 /* used in apx_uprim */ 9750824Ssklower 9850824Ssklower apxprobe(id) 9950824Ssklower register struct isa_device *id; 10050824Ssklower { 10150824Ssklower int moffset, subunit, unit = id->id_unit << 1; 10250825Ssklower struct apc_reg *reg = (struct apc_reg *)id->id_iobase; 10350824Ssklower register struct apx_softc *apx = apx_softc + unit; 10450824Ssklower 105*52672Ssklower apx->apx_if.if_unit = unit; 106*52672Ssklower apx->apx_reg = reg; 107*52672Ssklower if (apxctr(apx) == 0) { 108*52672Ssklower apxerror(apx, "no response from timer chip", 0); 10950824Ssklower return 0; /* No board present */ 110*52672Ssklower } 11150824Ssklower for (subunit = 0; subunit < 2; subunit++, apx++) { 11250824Ssklower /* Set and read DTR mode to test present of SGS thompson chip */ 11350824Ssklower apx->apx_if.if_unit = unit++; 11450825Ssklower apx->apx_sgcp = reg->axr_sgcp + subunit; 11550824Ssklower SG_WCSR(apx, 5, 0x08); 11650825Ssklower if (((SG_RCSR(apx, 5) & 0xff08) != 0x08)) { 11750824Ssklower apxerror(apx, "no mk5025 for channel", subunit); 11850824Ssklower continue; 11950824Ssklower } 12050824Ssklower moffset = subunit ? id->id_msize >> 1 : 0; 12150824Ssklower apx->apx_hmem = (struct apc_mem *) (id->id_maddr + moffset); 12250824Ssklower apx->apx_dmem = (struct apc_mem *) (moffset); 12350824Ssklower apx->apx_modes = apx_default_modes; 12450824Ssklower apx->apx_device = (caddr_t) id; 12550824Ssklower apx->apx_reg = reg; 12650824Ssklower apx->apx_csr4 = 0x0110; /* no byte swapping for PC-AT */ 12750824Ssklower } 12850824Ssklower return 1; 12950824Ssklower } 13050824Ssklower 13150824Ssklower apxattach(id) 13250824Ssklower register struct isa_device *id; 13350824Ssklower { 13450824Ssklower int unit = id->id_unit + id->id_unit; 13550824Ssklower 13650824Ssklower apx_ifattach(unit); 13750824Ssklower apx_ifattach(unit + 1); 13850824Ssklower return (0); 13950824Ssklower } 14050824Ssklower /* End bus & endian dependence */ 14150824Ssklower 14250824Ssklower /* 14350824Ssklower * Interface exists: make available by filling in network interface 14450824Ssklower * record. System will initialize the interface when it is ready 14550824Ssklower * to accept packets. 14650824Ssklower */ 14750825Ssklower void 14850824Ssklower apx_ifattach(unit) 14950824Ssklower { 15050824Ssklower register struct ifnet *ifp = &(apx_softc[unit].apx_if); 15150824Ssklower /* 15250824Ssklower * Initialize ifnet structure 15350824Ssklower */ 15450824Ssklower if (apx_softc[unit].apx_device == 0) 15550824Ssklower return; 15650824Ssklower ifp->if_name = "apc"; 15750824Ssklower ifp->if_mtu = SGMTU; 15850824Ssklower ifp->if_init = apxinit; 15950824Ssklower ifp->if_output = x25_ifoutput; 16050824Ssklower ifp->if_start = apxstart; 16150824Ssklower ifp->if_ioctl = apxioctl; 16250824Ssklower ifp->if_reset = apxreset; 16350825Ssklower ifp->if_type = apx_default_modes.apm_iftype; 16450824Ssklower ifp->if_hdrlen = 5; 16550824Ssklower 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 186*52672Ssklower apxctr(apx) 187*52672Ssklower register struct apx_softc *apx; 188*52672Ssklower { 189*52672Ssklower APX_WCSR(apx, axr_ccr, 0xb0); /* select ctr 2, write lsb+msb, mode 0 */ 190*52672Ssklower APX_WCSR(apx, axr_cnt2, 0x1); 191*52672Ssklower APX_WCSR(apx, axr_cnt2, 0x0); 192*52672Ssklower DELAY(50); 193*52672Ssklower APX_WCSR(apx, axr_ccr, 0xD4); /* latch status, ctr 2; */ 194*52672Ssklower return APX_RCSR(apx, axr_cnt2); 195*52672Ssklower } 196*52672Ssklower 19750824Ssklower apxreset(unit) 19850824Ssklower int unit; 19950824Ssklower { 20050824Ssklower register struct apx_softc *apx = &apx_softc[unit ^ 1]; 20150824Ssklower u_char apm_apxmode = 0, apm_apxaltmode = 0; 20250824Ssklower #define MODE(m) (m |= apx->apx_modes.m << ((apx->apx_if.if_unit & 1) ? 1 : 0)) 20350824Ssklower 20450824Ssklower MODE(apm_apxmode); 20550824Ssklower MODE(apm_apxaltmode); 20650824Ssklower apx = apx_softc + unit; 20750824Ssklower MODE(apm_apxmode); 20850824Ssklower MODE(apm_apxaltmode); 20950824Ssklower APX_WCSR(apx, axr_mode, apm_apxmode); 21050824Ssklower APX_WCSR(apx, axr_altmode, apm_apxaltmode); 21150825Ssklower apx->apx_txnum = apx->apx_rxnum = apx->apx_txcnt = 0; 21250824Ssklower 21350824Ssklower if (apx_uprim(apx, SG_STOP, "stop") || 21450824Ssklower !(apx->apx_if.if_flags & IFF_UP)) 21550824Ssklower return 0; 21650825Ssklower apx_meminit(apx->apx_hmem, apx); /* also sets CSR2 */ 21750824Ssklower SG_WCSR(apx, 3, (int)apx->apx_dmem); 21850824Ssklower SG_WCSR(apx, 4, apx->apx_csr4); 21950825Ssklower if (apx_uprim(apx, SG_INIT, "init request") || 22050824Ssklower apx_uprim(apx, SG_STAT, "status request") || 22150824Ssklower apx_uprim(apx, SG_TRANS, "transparent mode")) 22250824Ssklower return 0; 223*52672Ssklower (void) apxctr(apx); 22450824Ssklower SG_WCSR(apx, 0, SG_INEA); 22550825Ssklower return 1; 22650824Ssklower } 22750824Ssklower 22850824Ssklower apx_uprim(apx, request, ident) 22950824Ssklower int request; 23050824Ssklower char *ident; 23150824Ssklower register struct apx_softc *apx; 23250824Ssklower { 23350824Ssklower register int timo = 0; 23450824Ssklower int reply = SG_RCSR(apx, 1); 23550824Ssklower 23650825Ssklower if (reply & 0x8040) 23750825Ssklower SG_WCRS(1, 0x8040); /* Magic! */ 23850824Ssklower SG_WCSR(apx, 1, request | SG_UAV); 23950824Ssklower do { 24050824Ssklower reply = SG_RCRS(1); 241*52672Ssklower if (timo++ >= TIMO | reply & 0x8000) { 24250824Ssklower apxerror(apx, ident, reply); 24350824Ssklower return 1; 24450824Ssklower } 24550824Ssklower } while (reply & SG_UAV); 24650824Ssklower return 0; 24750824Ssklower } 24850824Ssklower 24950824Ssklower apx_meminit(apc, apx) 25050824Ssklower register struct apc_mem *apc; 25150824Ssklower struct apx_softc *apx; 25250824Ssklower { 25350824Ssklower register struct apc_mem *apcbase = apx->apx_dmem; 25450824Ssklower register int i; 25550825Ssklower #define LOWADDR(e) (((u_long)&(apcbase->e)) & 0xffff) 25650825Ssklower #define HIADDR(e) ((((u_long)&(apcbase->e)) >> 16) & 0xff) 25750824Ssklower #define SET_SGDX(dx, f, a, b, m) \ 25850824Ssklower { (dx).sgdx_addr = LOWADDR(a); (dx).sgdx_bcnt = (b);\ 25950824Ssklower (dx).sgdx_mcnt = (m); (dx).sgdx_flags = (f) | HIADDR(a); } 26050824Ssklower 26150824Ssklower bzero((caddr_t)apc, LOWADDR(apc_rxmd[0])); 26250824Ssklower apc->apc_mode = 0x8040; /* 2 flag spacing, trans mode, 16bit FCS */ 26350824Ssklower apc->apc_sgop = apx->apx_modes.apm_sgop; 26450824Ssklower apc->apc_rlen = SG_RLEN | HIADDR(apc_rxmd[0]); 26550824Ssklower apc->apc_rdra = LOWADDR(apc_rxmd[0]); 26650824Ssklower apc->apc_rlen = SG_TLEN | apx->apx_modes.apm_txwin |HIADDR(apc_txmd[0]); 26750824Ssklower apc->apc_tdra = LOWADDR(apc_txmd[0]); 26850824Ssklower SET_SGDX(apc->apc_rxtid, SG_OWN, apc_rxidbuf, -SGMTU, 0); 26950824Ssklower SET_SGDX(apc->apc_txtid, 0, apc_txidbuf, -SGMTU, 0); 27050824Ssklower apc->apc_stathi = HIADDR(apc_sgsb); 27150824Ssklower apc->apc_statlo = LOWADDR(apc_sgsb); 27250824Ssklower for (i = 0; i < SGRBUF; i++) 27350824Ssklower SET_SGDX(apc->apc_rxmd[i], SG_OWN, apc_rbuf[i][0], -SGMTU, 0) 27450824Ssklower for (i = 0; i < SGTBUF; i++) 27550824Ssklower SET_SGDX(apc->apc_txmd[i], SG_TUI, apc_tbuf[i][0], 0, 0) 27650824Ssklower SG_WCSR(apx, 2, SG_UIE | SG_PROM | HIADDR(apc_mode)); 27750824Ssklower } 27850824Ssklower 27950824Ssklower /* 28050824Ssklower * Start output on interface. Get another datagram to send 28150824Ssklower * off of the interface queue, and copy it to the interface 28250824Ssklower * before starting the output. 28350824Ssklower */ 28450824Ssklower apxstart(ifp) 28550824Ssklower struct ifnet *ifp; 28650824Ssklower { 28750824Ssklower register struct apx_softc *apx = &apx_softc[ifp->if_unit]; 28850824Ssklower register struct sgdx *dx; 28950825Ssklower struct apc_mem *apc = apx->apx_hmem; 29050824Ssklower struct mbuf *m; 29150824Ssklower int len; 29250824Ssklower 29350824Ssklower if ((ifp->if_flags & IFF_RUNNING) == 0) 29450824Ssklower return (0); 29550824Ssklower do { 29650825Ssklower dx = apc->apc_txmd + apx->apx_txnum; 29750824Ssklower if (dx->sgdx_flags & SG_OWN) 29850824Ssklower return (0); 29950824Ssklower IF_DEQUEUE(&ifp->if_snd, m); 30050824Ssklower if (m == 0) 30150824Ssklower return (0); 30250824Ssklower len = min(m->m_pkthdr.len, SGMTU); 30350825Ssklower m_copydata(m, 0, len, apc->apc_tbuf[apx->apx_txnum]); 30450824Ssklower dx->sgdx_mcnt = -len; 30550824Ssklower dx->sgdx_flags = SG_OWN | SG_TUI | (0xff & dx->sgdx_flags); 30650824Ssklower SG_WCSR(apx, 0, SG_INEA | SG_TDMD); 30750824Ssklower if (++apx->apx_txnum >= SGTBUF) 30850824Ssklower apx->apx_txnum = 0; 30950824Ssklower } while (++apx->apx_txcnt < SGTBUF); 31050824Ssklower apx->apx_txcnt = SGTBUF; 31150824Ssklower ifp->if_flags |= IFF_OACTIVE; 31250824Ssklower return (0); 31350824Ssklower } 31450824Ssklower 31550825Ssklower void 31650824Ssklower apxintr() 31750824Ssklower { 31850824Ssklower register struct apx_softc *apx = apx_lastsoftc; 31950824Ssklower struct apx_softc *apxlim = apx_softc + NAPX + NAPX; 32050824Ssklower int reply; 32150824Ssklower 32250824Ssklower do { 32350825Ssklower if (apx->apx_if.if_flags & IFF_UP) 32450824Ssklower /* Try to turn off interrupt cause */ 32550824Ssklower while ((reply = SG_RCSR(apx, 0)) & 0xff) { 32650824Ssklower SG_WCSR(apx, 0, SG_INEA | 0xfe); 32750824Ssklower if (reply & (SG_MERR|SG_TUR|SG_ROR)) { 32850824Ssklower apxerror(apx, "mem, rx, or tx error", reply); 32950824Ssklower apxinit(apx->apx_if.if_unit); 33050824Ssklower break; 33150824Ssklower } 33250824Ssklower if (reply & SG_RINT) 33350824Ssklower apxrint(apx); 33450824Ssklower if (reply & SG_TINT) 33550824Ssklower apxtint(apx); 33650824Ssklower if (reply & SG_PINT) 33750824Ssklower apxstat.pint++; 33850824Ssklower } 33950824Ssklower if (++apx >= apxlim) 34050824Ssklower apx = apx_softc; 34150824Ssklower } while (apx != apx_lastsoftc); 34250824Ssklower } 34350824Ssklower 34450825Ssklower void 34550824Ssklower apxtint(apx) 34650824Ssklower register struct apx_softc *apx; 34750824Ssklower { 34850825Ssklower register struct apc_mem *apc = apx->apx_hmem; 34950824Ssklower int i, loopcount = 0; 35050824Ssklower 35150824Ssklower do { 35250824Ssklower if ((i = apx->apx_txnum - apx->apx_txcnt) < 0) 35350824Ssklower i += SGTBUF; 35450824Ssklower if (apc->apc_txmd[i].sgdx_flags & SG_OWN) { 35550824Ssklower if (loopcount) 35650824Ssklower break; 35750824Ssklower apxstat.nulltx++; 35850824Ssklower return; 35950824Ssklower } 36050824Ssklower loopcount++; 36150824Ssklower apx->apx_if.if_flags &= ~IFF_OACTIVE; 36250824Ssklower } while (--apx->apx_txcnt > 0); 36350824Ssklower apxstart(&apx->apx_if); 36450824Ssklower } 36550824Ssklower 36650824Ssklower apxrint(apx) 36750824Ssklower register struct apx_softc *apx; 36850824Ssklower { 36950825Ssklower register struct apc_mem *apc = apx->apx_hmem; 37050824Ssklower register struct sgdx *dx = apc->apc_rxmd + apx->apx_rxnum; 37150824Ssklower #define SGNEXTRXMD \ 37250824Ssklower dx = ++apx->apx_rxnum == SGRBUF ? &apc->apc_rxmd[apx->apx_rxnum = 0] : dx + 1; 37350824Ssklower 37450824Ssklower /* 37550824Ssklower * Out of sync with hardware, should never happen? 37650824Ssklower */ 37750824Ssklower if (dx->sgdx_flags & SG_OWN) { 37850824Ssklower apxerror(apx, "out of sync"); 37950824Ssklower return; 38050824Ssklower } 38150824Ssklower /* 38250824Ssklower * Process all buffers with valid data 38350824Ssklower */ 38450824Ssklower while ((dx->sgdx_flags & SG_OWN) == 0) { 38550824Ssklower if ((dx->sgdx_flags & (SG_SLF|SG_ELF)) != (SG_SLF|SG_ELF)) { 38650824Ssklower /* 38750824Ssklower * Find the end of the packet so we can see how long 38850824Ssklower * it was. We still throw it away. 38950824Ssklower */ 39050825Ssklower apxerror(apx, "chained buffer", dx->sgdx_flags); 39150824Ssklower do { 39250824Ssklower dx->sgdx_bcnt = 0; 39350824Ssklower dx->sgdx_flags = SG_OWN | (0xff&dx->sgdx_flags); 39450824Ssklower SGNEXTRXMD; 39550824Ssklower } while (!(dx->sgdx_flags & (SG_OWN|SG_SLF|SG_ELF))); 39650824Ssklower /* 39750824Ssklower * If search terminated without successful completion 39850824Ssklower * we reset the hardware (conservative). 39950824Ssklower */ 40050824Ssklower if ((dx->sgdx_flags & (SG_OWN|SG_SLF|SG_ELF)) != 40150825Ssklower SG_ELF) { 40250824Ssklower apxreset(apx->apx_if.if_unit); 40350824Ssklower return; 40450824Ssklower } 40550824Ssklower } else 40650824Ssklower apxinput(&apx->apx_if, apc->apc_rbuf[apx->apx_rxnum], 40750824Ssklower -dx->sgdx_bcnt); 40850824Ssklower dx->sgdx_bcnt = 0; 40950824Ssklower dx->sgdx_flags = SG_OWN | (0xff & dx->sgdx_flags); 41050824Ssklower SGNEXTRXMD; 41150824Ssklower } 41250824Ssklower } 41350824Ssklower 41450825Ssklower void 41550824Ssklower apxinput(ifp, buffer, len) 41650824Ssklower register struct ifnet *ifp; 41750824Ssklower caddr_t buffer; 41850824Ssklower { 41950824Ssklower register struct ifqueue *inq; 420*52672Ssklower struct mbuf *m, *m_devget(); 42150824Ssklower extern struct ifqueue hdintrq, ipintrq; 42250824Ssklower int isr; 42350824Ssklower 42450824Ssklower ifp->if_ipackets++; 42550824Ssklower { 42650824Ssklower register u_char *cp = (u_char *)buffer; 42750824Ssklower 42850824Ssklower if (cp[0] == 0xff && cp[1] == 0x3) { 42950824Ssklower /* This is a UI HDLC Packet, so we'll assume PPP 43050824Ssklower protocol. for now, IP only. */ 43150824Ssklower buffer += 4; 43250824Ssklower len -= 4; 43350824Ssklower inq = &ipintrq; 43450824Ssklower isr = NETISR_IP; 43550824Ssklower } else { 43650824Ssklower inq = &hdintrq; 43750824Ssklower isr = NETISR_CCITT; 43850824Ssklower } 43950824Ssklower } 44050824Ssklower if (len <= 0) 44150824Ssklower return; 44250824Ssklower 443*52672Ssklower m = m_devget(buffer, len, 0, ifp, (void (*)())0); 44450824Ssklower if (m == 0) 44550824Ssklower return; 44650824Ssklower 44750824Ssklower if(IF_QFULL(inq)) { 44850824Ssklower IF_DROP(inq); 44950824Ssklower m_freem(m); 45050824Ssklower } else { 45150824Ssklower IF_ENQUEUE(inq, m); 45250824Ssklower schednetisr(isr); 45350824Ssklower } 45450824Ssklower } 45550824Ssklower 45650824Ssklower /* 45750824Ssklower * Process an ioctl request. 45850824Ssklower */ 45950824Ssklower apxioctl(ifp, cmd, data) 46050824Ssklower register struct ifnet *ifp; 46150824Ssklower int cmd; 46250824Ssklower caddr_t data; 46350824Ssklower { 46450824Ssklower register struct ifaddr *ifa = (struct ifaddr *)data; 46550824Ssklower int s = splimp(), error = 0; 46650824Ssklower struct apx_softc *apx = &apx_softc[ifp->if_unit]; 46750824Ssklower 46850824Ssklower switch (cmd) { 46950824Ssklower case SIOCSIFCONF_X25: 47050824Ssklower ifp->if_flags |= IFF_UP; 47150824Ssklower error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); 47250824Ssklower if (error == 0) 47350824Ssklower apxinit(ifp->if_unit); 47450824Ssklower break; 47550824Ssklower 47650824Ssklower case SIOCSIFADDR: 47750824Ssklower ifa->ifa_rtrequest = x25_rtrequest; 47850824Ssklower break; 47950824Ssklower 48050824Ssklower case SIOCSIFFLAGS: 48150824Ssklower if (((ifp->if_flags & IFF_UP) == 0 && 48250824Ssklower (ifp->if_flags & IFF_RUNNING)) || 48350824Ssklower (ifp->if_flags & IFF_UP) && 48450824Ssklower (ifp->if_flags & IFF_RUNNING) == 0) 48550824Ssklower apxinit(ifp->if_unit); 48650824Ssklower break; 48750824Ssklower 48850824Ssklower case SIOCSIFMODE: 48950824Ssklower if ((ifp->if_flags & IFF_UP) == 0) 49050825Ssklower apx->apx_modes = *(struct apc_modes *)data; 49150824Ssklower else 49250824Ssklower default: 49350824Ssklower error = EINVAL; 49450824Ssklower 49550824Ssklower } 49650824Ssklower splx(s); 49750824Ssklower return (error); 49850824Ssklower } 49950824Ssklower 50050824Ssklower apxerror(apx, msg, data) 50150824Ssklower register struct apx_softc *apx; 50250824Ssklower char *msg; 50350824Ssklower { 50450824Ssklower log(LOG_WARNING, "apc%d: %s, stat=0x%x\n", 50550824Ssklower apx->apx_if.if_unit, msg, data); 50650824Ssklower } 50750824Ssklower #endif /* NAPX */ 508