📄 if_apx.c
字号:
/* * Copyright (c) 1982, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)if_apx.c 8.1 (Berkeley) 6/11/93 *//* * Driver for SGS-THOMSON MK5025 based Link level controller. * The chip will do LAPB in hardware, although this driver only * attempts to use it for HDLC framing. * * Driver written by Keith Sklower, based on lance AMD7990 * driver by Van Jacobsen, and information graciously supplied * by the ADAX corporation of Berkeley, CA. */#include "apx.h"#if NAPX > 0#include <sys/param.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/errno.h>#include <sys/syslog.h>#include <net/if.h>#include <net/netisr.h>#include <net/if_types.h>#ifdef CCITT#include <netccitt/x25.h>int x25_rtrequest(), x25_ifoutput();#endif#include <i386/isa/if_apxreg.h>int apxprobe(), apxattach(), apxstart(), apx_uprim(), apx_meminit();int apxinit(), apxoutput(), apxioctl(), apxreset(), apxdebug = 0;void apx_ifattach(), apxtest(), apxinput(), apxintr(), apxtint(), apxrint();struct apx_softc { struct ifnet apx_if; caddr_t apx_device; /* e.g. isa_device, vme_device, etc. */ struct apc_reg *apx_reg; /* control regs for both subunits */ struct apc_mem *apx_hmem; /* Host addr for shared memory */ struct apc_mem *apx_dmem; /* Device (chip) addr for shared mem */ struct sgcp *apx_sgcp; /* IO control port for this subunit */ int apx_flags; /* Flags specific to this driver */#define APXF_CHIPHERE 0x01 /* mk5025 present */ int apx_rxnum; /* Last receiver dx we looked at */ int apx_txnum; /* Last tranmistter dx we stomped on */ int apx_txcnt; /* Number of packets queued for tx*/ u_int apx_msize; struct sgae apx_csr23; /* 24 bit init addr, as seen by chip */ u_short apx_csr4; /* byte gender, set in mach dep code */ struct apc_modes apx_modes; /* Parameters, as amended by ioctls */} apx_softc[2 * NAPX];struct apxstat { int rxnull; /* no rx bufs ready this interrupt */ int rxnrdy; /* expected rx buf not ready */ int rx2big; /* expected rx buf not ready */ int txnull; int pint; /* new primitive available interrupt */ int rint; /* receive interrupts */ int tint; /* transmit interrupts */ int anyint; /* note all interrupts */ int queued; /* got through apxinput */ int nxpctd; /* received while if was down */ int rstfld; /* reset didn't work */} apxstat;/* default operating paramters for devices */struct apc_modes apx_default_modes = { { 1, /* apm_sgob.lsaddr; */ 3, /* apm_sgob.rsaddr; */ -SGMTU, /* apm_sgob.n1; */ ((-10)<<8), /* apm_sgob.n2_scale; */ -1250, /* apm_sgob.t1; */ -10000, /* apm_sgob.t3; */ -80, /* apm_sgob.tp; */ }, 2, /* apm_txwin; */ 1, /* apm_apxmode: RS_232 connector and modem clock; */ 0, /* apm_apxaltmode: enable dtr, disable X.21 connector; */ IFT_X25, /* apm_iftype; */};/* Begin bus & endian dependence */#include <i386/isa/isa_device.h>struct isa_driver apxdriver = { apxprobe, apxattach, "apx",};#define SG_RCSR(apx, csrnum) \ (outw(&(apx->apx_sgcp->sgcp_rap), csrnum << 1), \ inw(&(apx->apx_sgcp->sgcp_rdp)))#define SG_WCSR(apx, csrnum, data) \ (outw(&(apx->apx_sgcp->sgcp_rap), csrnum << 1), \ outw(&(apx->apx_sgcp->sgcp_rdp), data))#define APX_RCSR(apx, csrname) inb(&(apx->apx_reg->csrname))#define APX_WCSR(apx, csrname, data) outb(&(apx->apx_reg->csrname), data)#define TIMO 10000 /* used in apx_uprim */apxprobe(id) register struct isa_device *id;{ int moffset = 0, nchips = 2, unit = id->id_unit << 1, subunit; struct apc_reg *reg = (struct apc_reg *)id->id_iobase; register struct apx_softc *apx = apx_softc + unit; /* * Probing for the second MK5025 on all ISA/EISA adax boards * manufactured prior to July 1992 (and some time following) * will hang the bus and the system. Thus, it is essential * not to probe for the second mk5025 if it is known not to be there. * As the current config scheme for 386BSD does not have a flags * field, we adopt the convention of using the low order bit of * the memsize to warn us that we have a single chip board. */ if (id->id_msize & 1) nchips = 1; for (subunit = 0; subunit < nchips; subunit++) { apx->apx_msize = id->id_msize >> 1; apx->apx_hmem = (struct apc_mem *) (id->id_maddr + moffset); apx->apx_dmem = (struct apc_mem *) moffset; apx->apx_device = (caddr_t) id; apx->apx_reg = reg; apx->apx_sgcp = reg->axr_sgcp + subunit; apx->apx_csr4 = 0x0210; /* no byte swapping for PC-AT */ apx->apx_modes = apx_default_modes; apx->apx_if.if_unit = unit++; moffset = apx->apx_msize; apxtest(apx++); } return 1;}apxattach(id) struct isa_device *id;{ register struct apx_softc *apx = apx_softc + (id->id_unit << 1); apx_ifattach(&((apx++)->apx_if)); apx_ifattach(&(apx->apx_if)); return 0;}/* End bus & endian dependence *//* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */voidapx_ifattach(ifp) register struct ifnet *ifp;{ /* * Initialize ifnet structure */ ifp->if_name = "apc"; ifp->if_mtu = SGMTU; ifp->if_init = apxinit; ifp->if_output = apxoutput; ifp->if_start = apxstart; ifp->if_ioctl = apxioctl; ifp->if_reset = apxreset; ifp->if_type = apx_default_modes.apm_iftype; ifp->if_hdrlen = 5; ifp->if_addrlen = 8; if_attach(ifp);}/* * Initialization of interface */apxinit(unit) int unit;{ struct ifnet *ifp = &apx_softc[unit].apx_if; int s = splimp(); ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); if (apxreset(unit) && (ifp->if_flags & IFF_UP)) { ifp->if_flags |= IFF_RUNNING; (void)apxstart(ifp); } splx(s); return 0;}apxctr(apx) register struct apx_softc *apx;{ APX_WCSR(apx, axr_ccr, 0xB0); /* select ctr 2, write lsb+msb, mode 0 */ APX_WCSR(apx, axr_cnt2, 0x1); APX_WCSR(apx, axr_cnt2, 0x0); DELAY(50); APX_WCSR(apx, axr_ccr, 0xE8); /* latch status, ctr 2; */ return (APX_RCSR(apx, axr_cnt2));}voidapxtest(apx) register struct apx_softc *apx;{ int i = 0; if ((apx->apx_if.if_unit & 1) == 0 && (i = apxctr(apx)) == 0) apxerror(apx, "no response from timer chip", 0); if (SG_RCSR(apx, 1) & 0x8000) SG_WCSR(apx, 1, 0x8040); SG_WCSR(apx, 4, apx->apx_csr4); SG_WCSR(apx, 5, 0x08); /* Set DTR mode in SGS thompson chip */ if (((i = SG_RCSR(apx, 5)) & 0xff08) != 0x08) apxerror(apx, "no mk5025, csr5 high bits are", i); else apx->apx_flags |= APXF_CHIPHERE; (void) apx_uprim(apx, SG_STOP, "stop after probing");}apxreset(unit) int unit;{ register struct apx_softc *apx = &apx_softc[unit ^ 1]; u_char apm_apxmode = 0, apm_apxaltmode = 0;#define MODE(m) (m |= apx->apx_modes.m << ((apx->apx_if.if_unit & 1) ? 1 : 0)) MODE(apm_apxmode); MODE(apm_apxaltmode); apx = apx_softc + unit; MODE(apm_apxmode); MODE(apm_apxaltmode); APX_WCSR(apx, axr_mode, apm_apxmode); APX_WCSR(apx, axr_altmode, apm_apxaltmode); (void) apxctr(apx); (void) apx_uprim(apx, SG_STOP, "stop to reset"); if ((apx->apx_if.if_flags & IFF_UP) == 0) return 0; apx_meminit(apx->apx_hmem, apx); SG_WCSR(apx, 4, apx->apx_csr4); SG_WCSR(apx, 2, apx->apx_csr23.f_hi); SG_WCSR(apx, 3, apx->apx_csr23.lo); if (apx_uprim(apx, SG_INIT, "init request") || apx_uprim(apx, SG_STAT, "status request") || apx_uprim(apx, SG_TRANS, "transparent mode")) return 0; SG_WCSR(apx, 0, SG_INEA); return 1;}apx_uprim(apx, request, ident) register struct apx_softc *apx; char *ident;{ register int timo = 0; int reply; if ((apx->apx_flags & APXF_CHIPHERE) == 0) return 1; /* maybe even should panic . . . */ if ((reply = SG_RCSR(apx, 1)) & 0x8040) SG_WCSR(apx, 1, 0x8040); /* Magic! */ if (request == SG_STOP && (SG_RCSR(apx, 0) & SG_STOPPED)) return 0; SG_WCSR(apx, 1, request | SG_UAV); do { reply = SG_RCSR(apx, 1); if (timo++ >= TIMO || (reply & 0x8000)) { apxerror(apx, ident, reply); return 1; } } while (reply & SG_UAV); return 0;}apx_meminit(apc, apx)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -