diff --git a/sys/arch/amiga/dev/if_ae.c b/sys/arch/amiga/dev/if_ae.c deleted file mode 100644 index ae860d796ee4..000000000000 --- a/sys/arch/amiga/dev/if_ae.c +++ /dev/null @@ -1,1127 +0,0 @@ -/* $NetBSD: if_ae.c,v 1.14 1997/03/18 18:44:53 veego Exp $ */ - -/* - * Copyright (c) 1995 Bernd Ernesti and Klaus Burkert. All rights reserved. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * 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 Bernd Ernesti, by Klaus - * Burkert, by Michael van Elst, and 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_le.c 8.1 (Berkeley) 6/10/93 - * - * This is based on the original LANCE files, as the PCnet-ISA used on - * the Ariadne is a LANCE-descendant optimized for the PC-ISA bus. - * This causes some modifications, all data that is to go into registers - * or to structures (buffer-descriptors, init-block) has to be - * byte-swapped. In addition ALL write accesses to the board have to be - * WORD or LONG, BYTE-access is prohibited!! - */ - -#include "bpfilter.h" - -/* - * AMD 79C960 PCnet-ISA - * - * This driver will generate and accept tailer encapsulated packets even - * though it buys us nothing. The motivation was to avoid incompatibilities - * with VAXen, SUNs, and others that handle and benefit from them. - * This reasoning is dubious. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#ifdef INET -#include -#include -#include -#include -#include -#endif - -#ifdef NS -#include -#include -#endif - -#if defined(CCITT) && defined(LLC) -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#if NBPFILTER > 0 -#include -#include -#endif - -#include -#include -#include -#include -#include -#include - -/* - * Ethernet software status per interface. - * - * Each interface is referenced by a network interface structure, - * ae_if, which the routing code uses to locate the interface. - * This structure contains the output queue for the interface, its address, ... - */ -struct ae_softc { - struct device sc_dev; - struct isr sc_isr; - struct ethercom sc_ethercom; /* common Ethernet structures */ - void *sc_base; /* base address of board */ - struct aereg1 *sc_r1; /* LANCE registers */ - struct aereg2 *sc_r2; /* dual-port RAM */ - int sc_rmd; /* predicted next rmd to process */ - int sc_tmd; /* next tmd to use */ - int sc_no_td; /* number of tmds in use */ - u_int16_t ae_rev; /* revision of the lance chip */ -}; - -/* offsets for: ID, REGS, MEM */ -int aestd[] = { 0, 0x0370, 0x8000 }; - -int aematch __P((struct device *, struct cfdata *, void *)); -void aeattach __P((struct device *, struct device *, void *)); -void aewatchdog __P((struct ifnet *)); -void aestop __P((struct ae_softc *)); -void aememinit __P((struct ae_softc *)); -void aereset __P((struct ae_softc *)); -void aeinit __P((struct ae_softc *)); -void aestart __P((struct ifnet *)); -int aeintr __P((void *)); -void aetint __P((struct ae_softc *)); -void aerint __P((struct ae_softc *)); -void aeread __P((struct ae_softc *, u_char *, int)); -static void wcopyfrom __P((char *, char *, int)); -static void wcopyto __P((char *, char *, int)); -static void wzero __P((char *, int)); -int aeput __P((char *, struct mbuf *)); -struct mbuf *aeget __P((struct ae_softc *, u_char *, int)); -int aeioctl __P((struct ifnet *, u_long, caddr_t)); -void aesetladrf __P((struct ethercom *, u_int16_t *)); - -struct cfattach ae_ca = { - sizeof(struct ae_softc), aematch, aeattach -}; - -struct cfdriver ae_cd = { - NULL, "ae", DV_IFNET -}; - -int -aematch(parent, cfp, aux) - struct device *parent; - struct cfdata *cfp; - void *aux; -{ - struct zbus_args *zap; - - zap = (struct zbus_args *)aux; - - /* Ariadne ethernet card */ - if (zap->manid == 2167 && zap->prodid == 201) - return (1); - - return (0); -} - -/* - * Interface exists: make available by filling in network interface - * record. System will initialize the interface when it is ready - * to accept packets. - */ -void -aeattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - register struct aereg2 *aer2; - struct zbus_args *zap; - struct ae_softc *sc = (void *)self; - struct ifnet *ifp = &sc->sc_ethercom.ec_if; - unsigned long ser; - int s = splhigh (); - u_int8_t myaddr[ETHER_ADDR_LEN]; - - zap =(struct zbus_args *)aux; - - /* - * Make config msgs look nicer. - */ - printf("\n"); - - sc->sc_base = zap->va; - sc->sc_r1 = (struct aereg1 *)(aestd[1] + (int)zap->va); - aer2 = sc->sc_r2 = (struct aereg2 *)(aestd[2] + (int)zap->va); - - /* - * Serial number for board is used as host ID. - */ - ser = (unsigned long) zap->serno; - - /* - * Manufacturer decides the 3 first bytes, i.e. ethernet vendor ID. - */ - - myaddr[0] = 0x00; - myaddr[1] = 0x60; - myaddr[2] = 0x30; - - myaddr[3] = (ser >> 16) & 0xff; - myaddr[4] = (ser >> 8) & 0xff; - myaddr[5] = ser & 0xff; - - printf("%s: hardware address %s 32K", sc->sc_dev.dv_xname, - ether_sprintf(myaddr)); - - aestop(sc); - delay(100); - - /* get the chip version of the lance chip */ - sc->sc_r1->aer1_rap = 0x5900; - sc->ae_rev = ((sc->sc_r1->aer1_rdp >> 4) -2); - printf(" chip-revision: B%x\n", sc->ae_rev); - - splx (s); - - bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); - ifp->if_softc = sc; - ifp->if_ioctl = aeioctl; - ifp->if_watchdog = aewatchdog; - ifp->if_output = ether_output; - ifp->if_start = aestart; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; - - if_attach(ifp); - ether_ifattach(ifp, myaddr); - -#if NBPFILTER > 0 - bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); -#endif - - sc->sc_isr.isr_intr = aeintr; - sc->sc_isr.isr_arg = sc; - sc->sc_isr.isr_ipl = 2; - add_isr (&sc->sc_isr); - return; -} - -void -aewatchdog(ifp) - struct ifnet *ifp; -{ - struct ae_softc *sc = ifp->if_softc; - - log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); - ++ifp->if_oerrors; - - aereset(sc); -} - -void -aestop(sc) - struct ae_softc *sc; -{ - sc->sc_r1->aer1_rap = AE_CSR0; - sc->sc_r1->aer1_rdp = AE_STOP; -} - - -/* - * Set up the initialization block and the descriptor rings. - */ -void -aememinit(sc) - register struct ae_softc *sc; -{ - register struct ifnet *ifp = &sc->sc_ethercom.ec_if; - u_int8_t *myaddr; - /* - * This structure is referenced from the CARD's/PCnet-ISA's point - * of view, thus the 0x8000 address which is the buffer RAM area - * of the Ariadne card. This pointer is manipulated - * with the PCnet-ISA's view of memory and NOT the Amiga's. FYI. - */ - register struct aereg2 *aemem = (struct aereg2 *) 0x8000; - register struct aereg2 *aer2 = sc->sc_r2; - register int i; - - -#if NBPFILTER > 0 - if (ifp->if_flags & IFF_PROMISC) - /* set the promiscuous bit */ - aer2->aer2_mode = AE_MODE | AE_PROM; - else -#endif - aer2->aer2_mode = AE_MODE; - /* you know: no BYTE access.... */ - myaddr = LLADDR(ifp->if_sadl); - aer2->aer2_padr[0] = (myaddr[0] << 8) | myaddr[1]; - aer2->aer2_padr[1] = (myaddr[2] << 8) | myaddr[3]; - aer2->aer2_padr[2] = (myaddr[4] << 8) | myaddr[5]; - aesetladrf(&sc->sc_ethercom, aer2->aer2_ladrf); - - sc->sc_no_td = sc->sc_tmd = sc->sc_rmd = 0; - - aer2->aer2_rlen = SWAP(AE_RLEN); - aer2->aer2_rdra = SWAP((int)aemem->aer2_rmd); - aer2->aer2_tlen = SWAP(AE_TLEN); - aer2->aer2_tdra = SWAP((int)aemem->aer2_tmd); - - for (i = 0; i < AERBUF; i++) { - aer2->aer2_rmd[i].rmd0 = SWAP((int)aemem->aer2_rbuf[i]); - aer2->aer2_rmd[i].rmd2 = SWAP(-ETHER_MAX_LEN); - aer2->aer2_rmd[i].rmd3 = 0; - aer2->aer2_rmd[i].rmd1 = AE_OWN; - } - - for (i = 0; i < AETBUF; i++) { - aer2->aer2_tmd[i].tmd0 = SWAP((int)aemem->aer2_tbuf[i]); - aer2->aer2_tmd[i].tmd1 = 0; - aer2->aer2_tmd[i].tmd2 = 0; - aer2->aer2_tmd[i].tmd3 = 0; - } -} - -void -aereset(sc) - struct ae_softc *sc; -{ - int s; - - s = splnet(); - aeinit(sc); - splx(s); -} - -/* - * Initialization of interface; set up initialization block - * and transmit/receive descriptor rings. - */ -void -aeinit(sc) - struct ae_softc *sc; -{ - register struct aereg1 *aer1 = sc->sc_r1; - register struct ifnet *ifp = &sc->sc_ethercom.ec_if; - register struct aereg2 *aemem = (struct aereg2 *) 0x8000; - - register int timo = 0; - volatile int dummy; - - aestop(sc); - delay(100); - - dummy = aer1->aer1_reset; /* Reset PCNet-ISA */ - - aememinit(sc); - - /* Give LANCE the physical address of its init block. */ - aer1->aer1_rap = AE_CSR1; - aer1->aer1_rdp = SWAP((int)&aemem->aer2_mode); - aer1->aer1_rap = AE_CSR2; - aer1->aer1_rdp = 0; - -/* - * re-program LEDs to match meaning used on the Ariadne board - */ - aer1->aer1_rap = 0x0500; - aer1->aer1_idp = 0x9000; - aer1->aer1_rap = 0x0600; - aer1->aer1_idp = 0x8100; - aer1->aer1_rap = 0x0700; - aer1->aer1_idp = 0x8400; - -/* - * you can `ifconfig (link0|-link0) ae0' to get the following - * behaviour: - * -link0 enable autoselect between 10Base-T (UTP) and 10Base2 (BNC) - * if an active 10Base-T line is connected then 10Base-T - * is used otherwise 10Base2. - * this is the default behaviour, so there is no need to set - * -link0 when you want autoselect. - * link0 -link1 disable autoselect. enable BNC. - * link0 link1 disable autoselect. enable UTP. - */ - if (!(ifp->if_flags & IFF_LINK0)) { - /* enable autoselect */ - aer1->aer1_rap = 0x0200; - aer1->aer1_idp = 0x0200; - } else { - /* disable autoselect */ - aer1->aer1_rap = 0x0200; - aer1->aer1_idp = 0x0000; - if (!(ifp->if_flags & IFF_LINK1)) { - /* enable BNC */ - sc->sc_r2->aer2_mode = 0x0000; - } else { - /* enable UTP */ - sc->sc_r2->aer2_mode = 0x8000; - } - } - - /* Try to initialize the LANCE. */ - delay(100); - aer1->aer1_rap = AE_CSR0; - aer1->aer1_rdp = AE_INIT; - - /* Wait for initialization to finish. */ - do { - if (++timo == 10000) { - printf("%s: card failed to initialize\n", sc->sc_dev.dv_xname); - break; - } - } while ((aer1->aer1_rdp & AE_IDON) == 0); - - /* Start the LANCE. */ - aer1->aer1_rap = AE_CSR0; - aer1->aer1_rdp = AE_STRT | AE_INEA | AE_IDON; - ifp->if_flags |= IFF_RUNNING; - ifp->if_flags &= ~IFF_OACTIVE; - ifp->if_timer = 0; - aestart(ifp); -} - -#define AENEXTTMP \ - if (++bix == AETBUF) bix = 0, tmd = sc->sc_r2->aer2_tmd; else ++tmd - -/* - * Start output on interface. Get another datagram to send - * off of the interface queue, and copy it to the interface - * before starting the output. - */ -void -aestart(ifp) - struct ifnet *ifp; -{ - register struct ae_softc *sc = ifp->if_softc; - register int bix; - register struct aetmd *tmd; - register struct mbuf *m; - int len; - - if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) - return; - - bix = sc->sc_tmd; - tmd = &sc->sc_r2->aer2_tmd[bix]; - - for (;;) { - if (sc->sc_no_td >= AETBUF) { - ifp->if_flags |= IFF_OACTIVE; - break; - } - - IF_DEQUEUE(&ifp->if_snd, m); - if (m == 0) - break; - - ++sc->sc_no_td; - -#if NBPFILTER > 0 - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m); -#endif - - sc->sc_r1->aer1_rdp = AE_TINT | AE_INEA; - len = aeput(sc->sc_r2->aer2_tbuf[bix], m); - -#ifdef AEDEBUG - if (len > ETHER_MAX_LEN) - printf("packet length %d\n", len); -#endif - - ifp->if_timer = 5; - - tmd->tmd2 = SWAP(-len); - tmd->tmd3 = 0; - tmd->tmd1 = AE_OWN | AE_STP | AE_ENP; - - sc->sc_r1->aer1_rdp = AE_INEA | AE_TDMD; - - AENEXTTMP; - } - - sc->sc_tmd = bix; -} - -int -aeintr(arg) - void *arg; -{ - register struct ae_softc *sc = arg; - register struct aereg1 *aer1; - register struct ifnet *ifp = &sc->sc_ethercom.ec_if; - register u_int16_t stat; - - /* if not even initialized, don't do anything further.. */ - if (sc->sc_base == 0) - return (0); - - aer1 = sc->sc_r1; - stat = aer1->aer1_rdp; - - if ((stat & AE_INTR) == 0) - return (0); - - aer1->aer1_rdp = (stat & (AE_INEA | AE_BABL | AE_MISS | AE_MERR | - AE_RINT | AE_TINT | AE_IDON)); - if (stat & AE_SERR) { - if (stat & AE_MERR) { - printf("%s: memory error\n", sc->sc_dev.dv_xname); - aereset(sc); - return (1); - } - if (stat & AE_BABL) { - printf("%s: babble\n", sc->sc_dev.dv_xname); - ifp->if_oerrors++; - } -#if 0 - if (stat & AE_CERR) { - printf("%s: collision error\n", sc->sc_dev.dv_xname); - ifp->if_collisions++; - } -#endif - if (stat & AE_MISS) { - printf("%s: missed packet\n", sc->sc_dev.dv_xname); - ifp->if_ierrors++; - } - aer1->aer1_rdp = AE_BABL | AE_CERR | AE_MISS | AE_INEA; - } - if ((stat & AE_RXON) == 0) { - printf("%s: receiver disabled\n", sc->sc_dev.dv_xname); - ifp->if_ierrors++; - aereset(sc); - return (1); - } - if ((stat & AE_TXON) == 0) { - printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname); - ifp->if_oerrors++; - aereset(sc); - return (1); - } - if (stat & AE_RINT) { - /* Reset watchdog timer. */ - ifp->if_timer = 0; - aerint(sc); - } - if (stat & AE_TINT) { - /* Reset watchdog timer. */ - ifp->if_timer = 0; - aetint(sc); - } - - return (1); -} - -/* - * Ethernet interface transmitter interrupt. - * Start another output if more data to send. - */ -void -aetint(sc) - struct ae_softc *sc; -{ - register int bix = (sc->sc_tmd - sc->sc_no_td + AETBUF) % AETBUF; - struct aetmd *tmd = &sc->sc_r2->aer2_tmd[bix]; - struct ifnet *ifp = &sc->sc_ethercom.ec_if; - - if (tmd->tmd1 & AE_OWN) { -#ifdef AEDEBUG - printf("%s: extra tint\n", sc->sc_dev.dv_xname); -#endif - return; - } - ifp->if_flags &= ~IFF_OACTIVE; - - do { - if (sc->sc_no_td <= 0) - break; - ifp->if_opackets++; - --sc->sc_no_td; - - if (tmd->tmd1 & AE_ERR) { - if (tmd->tmd3 & AE_TBUFF) - printf("%s: transmit buffer error\n", sc->sc_dev.dv_xname); - if (tmd->tmd3 & AE_UFLO) - printf("%s: underflow\n", sc->sc_dev.dv_xname); - if (tmd->tmd3 & (AE_TBUFF | AE_UFLO)) { - aereset(sc); - return; - } - if (tmd->tmd3 & AE_LCAR) - printf("%s: lost carrier\n", sc->sc_dev.dv_xname); - if (tmd->tmd3 & AE_LCOL) { - printf("%s: late collision\n", sc->sc_dev.dv_xname); - ifp->if_collisions++; - } - if (tmd->tmd3 & AE_RTRY) { - printf("%s: excessive collisions, tdr %d\n", - sc->sc_dev.dv_xname, tmd->tmd3 & AE_TDR_MASK); - ifp->if_collisions += 16; - } - } else if (tmd->tmd1 & AE_ONE) { - ifp->if_collisions++; - } - else if (tmd->tmd1 & AE_MORE) { - /* Real number is unknown. */ - ifp->if_collisions += 2; - } - AENEXTTMP; - } while ((tmd->tmd1 & AE_OWN) == 0); - - aestart(ifp); - if (sc->sc_no_td == 0) - ifp->if_timer = 0; -} - -#define AENEXTRMP \ - if (++bix == AERBUF) bix = 0, rmd = sc->sc_r2->aer2_rmd; else ++rmd - -/* - * Ethernet interface receiver interrupt. - * If input error just drop packet. - * Decapsulate packet based on type and pass to type specific - * higher-level input routine. - */ -void -aerint(sc) - struct ae_softc *sc; -{ - struct ifnet *ifp = &sc->sc_ethercom.ec_if; - register int bix = sc->sc_rmd; - register struct aermd *rmd = &sc->sc_r2->aer2_rmd[bix]; - - /* - * Out of sync with hardware, should never happen? - */ - if (rmd->rmd1 & AE_OWN) { -#ifdef AEDEBUG - printf("%s: extra rint\n", sc->sc_dev.dv_xname); -#endif - return; - } - - /* - * Process all buffers with valid data - */ - do { - sc->sc_r1->aer1_rdp = AE_RINT | AE_INEA; - if (rmd->rmd1 & (AE_FRAM | AE_OFLO | AE_CRC | AE_RBUFF)) { - ifp->if_ierrors++; - if ((rmd->rmd1 & (AE_OFLO | AE_ENP)) == AE_OFLO) - printf("%s: overflow\n", sc->sc_dev.dv_xname); - else if ((rmd->rmd1 & (AE_FRAM | AE_OFLO | AE_ENP)) == (AE_FRAM | AE_ENP)) - printf("%s: framing error\n", sc->sc_dev.dv_xname); - else if ((rmd->rmd1 & (AE_CRC | AE_OFLO | AE_ENP)) == (AE_CRC | AE_ENP)) - printf("%s: crc mismatch\n", sc->sc_dev.dv_xname); - if (rmd->rmd1 & AE_RBUFF) - printf("%s: receive buffer error\n", sc->sc_dev.dv_xname); - } else if ((rmd->rmd1 & (AE_STP | AE_ENP)) != (AE_STP | AE_ENP)) { - do { - rmd->rmd3 = 0; - rmd->rmd1 = AE_OWN; - AENEXTRMP; - } while ((rmd->rmd1 & (AE_OWN | AE_ERR | AE_STP | AE_ENP)) == 0); - - sc->sc_rmd = bix; - printf("%s: chained buffer\n", sc->sc_dev.dv_xname); - if ((rmd->rmd1 & (AE_OWN | AE_ERR | AE_STP | AE_ENP)) != AE_ENP) { - aereset(sc); - return; - } - } else - aeread(sc, sc->sc_r2->aer2_rbuf[bix], SWAP(rmd->rmd3) - 4); - - rmd->rmd3 = 0; - rmd->rmd2 = SWAP(-ETHER_MAX_LEN); - rmd->rmd1 = AE_OWN; - - AENEXTRMP; - } while ((rmd->rmd1 & AE_OWN) == 0); - - sc->sc_rmd = bix; -} - -void -aeread(sc, buf, len) - register struct ae_softc *sc; - u_char *buf; - int len; -{ - struct ifnet *ifp = &sc->sc_ethercom.ec_if; - struct mbuf *m; - struct ether_header *eh; - - if (len <= sizeof(struct ether_header) || len > ETHER_MAX_LEN) { - printf("%s: invalid packet size %d; dropping\n", - sc->sc_dev.dv_xname, len); - ifp->if_ierrors++; - return; - } - - /* Pull packet off interface. */ - m = aeget(sc, buf, len); - if (m == 0) { - ifp->if_ierrors++; - return; - } - - ifp->if_ipackets++; - - /* We assume that the header fit entirely in one mbuf. */ - eh = mtod(m, struct ether_header *); - -#if NBPFILTER > 0 - /* - * Check if there's a bpf filter listening on this interface. - * If so, hand off the raw packet to bpf, which must deal with - * trailers in its own way. - */ - if (ifp->if_bpf) { - bpf_mtap(ifp->if_bpf, m); - - /* - * Note that the interface cannot be in promiscuous mode if - * there are no bpf listeners. And if we are in promiscuous - * mode, we have to check if this packet is really ours. - */ - if ((ifp->if_flags & IFF_PROMISC) && - (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */ - bcmp(eh->ether_dhost, LLADDR(ifp->if_sadl), - sizeof(eh->ether_dhost)) != 0) { - m_freem(m); - return; - } - } -#endif - - /* We assume that the header fit entirely in one mbuf. */ - m_adj(m, sizeof(struct ether_header)); - ether_input(ifp, eh, m); -} - -/* - * Here come the two replacements for bcopy() and bzero() as - * WORD-access for writing to the board is absolutely required! - * They could use some tuning as this is time-critical (copying - * packet-data) and should be processed as fast as possible. - * - * Thanks to Michael van Elst for pointing me to the problems - * that kept the 1.3 code from running under NetBSD current - * although it did mystically under 1.0 ... - */ - -#define isodd(p) (((size_t)(p)) & 1) -#define align(p) ((ushort *)(((size_t)(p)) & ~1)) - -/* - * the first function copies WORD-aligned from the source to - * an arbitrary destination. It assumes that the CPU can handle - * mis-aligned writes to the destination itself. - */ -static void -wcopyfrom(a1, a2, length) /* bcopy() word-wise */ - char *a1, *a2; - int length; -{ - ushort i, *b1, *b2; - - if (length > 0 && isodd(a1)) { - b1 = align(a1); - *a2 = *b1 & 0x00ff; /* copy first byte with word access */ - ++a2; - ++b1; - --length; - } else - b1 = (ushort *)a1; - b2 = (ushort *)a2; - - i = length / 2; - - while(i--) /* copy all words */ - *b2++ = *b1++; - - if (length & 0x0001) /* copy trailing byte */ - a2[length-1] = *b1 >> 8; -} - -/* - * the second function copies WORD-aligned from an arbitrary - * source to the destination. It assumes that the CPU can handle - * mis-aligned reads from the source itself. - */ -static void -wcopyto(a1, a2, length) /* bcopy() word-wise */ - char *a1, *a2; - int length; -{ - ushort i, *b1, *b2; - - if (length > 0 && isodd(a2)) { - b2 = align(a2); - i = (*b2 & 0xff00) | (*a1 & 0x00ff); /* copy first byte with word access */ - *b2 = i; - ++a1; - ++b2; - --length; - } else - b2 = (ushort *)a2; - b1 = (ushort *)a1; - - i = length / 2; - - while(i--) /* copy all words */ - *b2++ = *b1++; - - if (length & 0x0001) { - i = (*b2 & 0x00ff) | (a1[length-1] & 0x00ff)<<8; /* copy trailing byte */ - *b2 = i; - } -} - -static void -wzero(a1, length) /* bzero() word-wise */ - char *a1; - int length; -{ - ushort i, *b1; - - /* - * Is the destination word-aligned? - * If not, handle the leading byte... - */ - - if((length > 0) && ((size_t)a1 & 1)) { - b1 = (ushort *)((size_t)a1 & ~1); - *b1 &= 0xff00; - --length; - ++a1; - } - - /* - * Perform the main zeroing word-wise... - */ - - b1 = (ushort *)a1; - i = length / 2; - while(i--) - *b1++ = 0; - - /* - * Do we have to handle a trailing byte? - */ - - if (length & 0x0001) - *b1 &= 0x00ff; -} - -/* - * Routine to copy from mbuf chain to transmit - * buffer in board local memory. - */ -int -aeput(buffer, m) - register char *buffer; - register struct mbuf *m; -{ - register struct mbuf *n; - register int len = 0, tlen = 0; - - for (; m; m = n) { - len = m->m_len; - if (len == 0) { - MFREE(m, n); - continue; - } - wcopyto(mtod(m, char *), buffer, len); - buffer += len; - tlen += len; - MFREE(m, n); - } - - if (tlen < ETHER_MIN_LEN) { - wzero(buffer, ETHER_MIN_LEN - tlen); - tlen = ETHER_MIN_LEN; - } - - return(tlen); -} - -/* - * Routine to copy from board local memory into mbufs. - */ -struct mbuf * -aeget(sc, buffer, totlen) - struct ae_softc *sc; - u_char *buffer; - int totlen; -{ - register struct mbuf *m; - struct mbuf *top, **mp; - int len; - - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == 0) - return (0); - m->m_pkthdr.rcvif = &sc->sc_ethercom.ec_if; - m->m_pkthdr.len = totlen; - len = MHLEN; - top = 0; - mp = ⊤ - - while (totlen > 0) { - if (top) { - MGET(m, M_DONTWAIT, MT_DATA); - if (m == 0) { - m_freem(top); - return (0); - } - len = MLEN; - } - - if (totlen >= MINCLSIZE) { - MCLGET(m, M_DONTWAIT); - if (m->m_flags & M_EXT) - len = MCLBYTES; - } - m->m_len = len = min(totlen, len); - wcopyfrom((caddr_t)buffer, mtod(m, caddr_t), len); - buffer += len; - totlen -= len; - *mp = m; - mp = &m->m_next; - } - - return (top); -} - -/* - * Process an ioctl request. - */ -int -aeioctl(ifp, cmd, data) - register struct ifnet *ifp; - u_long cmd; - caddr_t data; -{ - struct ae_softc *sc = ifp->if_softc; - struct ifaddr *ifa = (struct ifaddr *)data; - struct ifreq *ifr = (struct ifreq *)data; - int s, error = 0; - - s = splnet(); - - switch (cmd) { - - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - - switch (ifa->ifa_addr->sa_family) { -#ifdef INET - case AF_INET: - aeinit(sc); - arp_ifinit(ifp, ifa); - break; -#endif -#ifdef NS - case AF_NS: - { - register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; - - if (ns_nullhost(*ina)) - ina->x_host = - *(union ns_host *)LLADDR(ifp->if_sadl); - else - wcopyto(ina->x_host.c_host, - LLADDR(ifp->if_sadl), ETHER_ADDR_LEN); - aeinit(sc); /* does ae_setaddr() */ - break; - } -#endif - default: - aeinit(sc); - break; - } - break; - -#if defined(CCITT) && defined(LLC) - case SIOCSIFCONF_X25: - ifp->if_flags |= IFF_UP; - ifa->ifa_rtrequest = cons_rtrequest; /* XXX */ - error = x25_llcglue(PRC_IFUP, ifa->ifa_addr); - if (error == 0) - aeinit(sc); - break; -#endif /* CCITT && LLC */ - - case SIOCSIFFLAGS: - if ((ifp->if_flags & IFF_UP) == 0 && - (ifp->if_flags & IFF_RUNNING) != 0) { - /* - * If interface is marked down and it is running, then - * stop it. - */ - aestop(sc); - ifp->if_flags &= ~IFF_RUNNING; - } else if ((ifp->if_flags & IFF_UP) != 0 && - (ifp->if_flags & IFF_RUNNING) == 0) { - /* - * If interface is marked up and it is stopped, then - * start it. - */ - aeinit(sc); - } else { - /* - * Reset the interface to pick up changes in any other - * flags that affect hardware registers. - */ - aeinit(sc); - } - break; - - case SIOCADDMULTI: - case SIOCDELMULTI: - error = (cmd == SIOCADDMULTI) ? - ether_addmulti(ifr, &sc->sc_ethercom): - ether_delmulti(ifr, &sc->sc_ethercom); - - if (error == ENETRESET) { - /* - * Multicast list has changed; set the hardware filter - * accordingly. - */ - aereset(sc); - error = 0; - } - break; - - default: - error = EINVAL; - break; - } - splx(s); - return (error); -} - -/* - * Set up the logical address filter. - */ -void -aesetladrf(ac, af) - struct ethercom *ac; - u_int16_t *af; -{ - struct ifnet *ifp = &ac->ec_if; - struct ether_multi *enm; - register u_char *cp, c; - register u_int32_t crc; - register int i, len; - struct ether_multistep step; - - /* - * Set up multicast address filter by passing all multicast addresses - * through a crc generator, and then using the high order 6 bits as an - * index into the 64 bit logical address filter. The high order bit - * selects the word, while the rest of the bits select the bit within - * the word. - */ - - if (ifp->if_flags & IFF_PROMISC) - goto allmulti; - - af[0] = af[1] = af[2] = af[3] = 0x0000; - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { - if (bcmp(enm->enm_addrlo, enm->enm_addrhi, - sizeof(enm->enm_addrlo)) != 0) { - /* - * We must listen to a range of multicast addresses. - * For now, just accept all multicasts, rather than - * trying to set only those filter bits needed to match - * the range. (At this time, the only use of address - * ranges is for IP multicast routing, for which the - * range is big enough to require all bits set.) - */ - goto allmulti; - } - - cp = enm->enm_addrlo; - crc = 0xffffffff; - for (len = sizeof(enm->enm_addrlo); --len >= 0;) { - c = *cp++; - for (i = 8; --i >= 0;) { - if ((crc & 0x01) ^ (c & 0x01)) { - crc >>= 1; - crc ^= 0xedb88320; - } else - crc >>= 1; - c >>= 1; - } - } - /* Just want the 6 most significant bits. */ - crc >>= 26; - - /* Turn on the corresponding bit in the filter. */ - af[crc >> 4] |= 1 << SWAP(crc & 0x1f); - - ETHER_NEXT_MULTI(step, enm); - } - ifp->if_flags &= ~IFF_ALLMULTI; - return; - -allmulti: - ifp->if_flags |= IFF_ALLMULTI; - af[0] = af[1] = af[2] = af[3] = 0xffff; -} diff --git a/sys/arch/amiga/dev/if_aereg.h b/sys/arch/amiga/dev/if_aereg.h deleted file mode 100644 index 0d0ce51ee3d0..000000000000 --- a/sys/arch/amiga/dev/if_aereg.h +++ /dev/null @@ -1,155 +0,0 @@ -/* $NetBSD: if_aereg.h,v 1.2 1995/08/18 15:53:32 chopps Exp $ */ - -/* - * Copyright (c) 1995 Bernd Ernesti and Klaus Burkert. All rights reserved. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * 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 Bernd Ernesti, by Klaus - * Burkert, by Michael van Elst, and 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_lereg.h 8.1 (Berkeley) 6/10/93 - * - * This is based on the original LANCE files, as the PCnet-ISA used on - * the Ariadne is a LANCE-descendant optimized for the PC-ISA bus. - * This causes some modifications, all data that is to go into registers - * or to structures (buffer-descriptors, init-block) has to be - * byte-swapped. In addition ALL write accesses to the board have to be - * WORD or LONG, BYTE-access is prohibited!! - */ - -#define ETHER_MAX_LEN 1518 -#define ETHER_MIN_LEN 64 - -#define AERBUF 16 /* 16 receive buffers */ -#define AERBUFLOG2 4 -#define AETBUF 4 /* 4 transmit buffers */ -#define AETBUFLOG2 2 - -#define AE_RLEN (AERBUFLOG2 << 13) -#define AE_TLEN (AETBUFLOG2 << 13) - -/* - * PCnet-ISA registers. - */ - -struct aereg1 { - u_int16_t aer1_rdp; /* data port */ - u_int16_t aer1_rap; /* register select port */ - u_int16_t aer1_reset; /* reading this resets the PCnet-ISA */ - u_int16_t aer1_idp; /* isa configuration port */ -}; - -struct aereg2 { - /* init block */ - u_int16_t aer2_mode; /* +0x0000 */ - u_int16_t aer2_padr[3]; /* +0x0002 */ - u_int16_t aer2_ladrf[4]; /* +0x0008 */ - u_int16_t aer2_rdra; /* +0x0010 */ - u_int16_t aer2_rlen; /* +0x0012 */ - u_int16_t aer2_tdra; /* +0x0014 */ - u_int16_t aer2_tlen; /* +0x0016 */ - /* receive message descriptors */ - struct aermd { /* +0x0018 */ - u_int16_t rmd0; - u_int16_t rmd1; - int16_t rmd2; - u_int16_t rmd3; - } aer2_rmd[AERBUF]; - /* transmit message descriptors */ - struct aetmd { /* +0x0058 */ - u_int16_t tmd0; - u_int16_t tmd1; - int16_t tmd2; - u_int16_t tmd3; - } aer2_tmd[AETBUF]; - char aer2_rbuf[AERBUF][ETHER_MAX_LEN]; /* +0x0060 */ - char aer2_tbuf[AETBUF][ETHER_MAX_LEN]; /* +0x2FD0 */ -}; - - -/* - * Control and status bits -- aereg1 - */ -#define AE_CSR0 0x0000 /* Control and status register */ -#define AE_CSR1 0x0100 /* low address of init block */ -#define AE_CSR2 0x0200 /* high address of init block */ -#define AE_CSR3 0x0300 /* Bus master and control */ - -/* Control and status register 0 (csr0) */ -#define AE_SERR 0x0080 /* error summary */ -#define AE_BABL 0x0040 /* transmitter timeout error */ -#define AE_CERR 0x0020 /* collision */ -#define AE_MISS 0x0010 /* missed a packet */ -#define AE_MERR 0x0008 /* memory error */ -#define AE_RINT 0x0004 /* receiver interrupt */ -#define AE_TINT 0x0002 /* transmitter interrupt */ -#define AE_IDON 0x0001 /* initalization done */ -#define AE_INTR 0x8000 /* interrupt condition */ -#define AE_INEA 0x4000 /* interrupt enable */ -#define AE_RXON 0x2000 /* receiver on */ -#define AE_TXON 0x1000 /* transmitter on */ -#define AE_TDMD 0x0800 /* transmit demand */ -#define AE_STOP 0x0400 /* disable all external activity */ -#define AE_STRT 0x0200 /* enable external activity */ -#define AE_INIT 0x0100 /* begin initalization */ - -#define AE_PROM 0x0080 /* promiscuous mode */ -#define AE_MODE 0x0000 - -/* - * Control and status bits -- aereg2 - */ -#define AE_OWN 0x0080 /* LANCE owns the packet */ -#define AE_ERR 0x0040 /* error summary */ -#define AE_STP 0x0002 /* start of packet */ -#define AE_ENP 0x0001 /* end of packet */ - -#define AE_MORE 0x0010 /* multiple collisions */ -#define AE_ONE 0x0008 /* single collision */ -#define AE_DEF 0x0004 /* defferred transmit */ - -#define AE_FRAM 0x0020 /* framing error */ -#define AE_OFLO 0x0010 /* overflow error */ -#define AE_CRC 0x0008 /* CRC error */ -#define AE_RBUFF 0x0004 /* buffer error */ - -/* Transmit message descriptor 3 (tmd3) */ -#define AE_TBUFF 0x0080 /* buffer error */ -#define AE_UFLO 0x0040 /* underflow error */ -#define AE_LCOL 0x0010 /* late collision */ -#define AE_LCAR 0x0008 /* loss of carrier */ -#define AE_RTRY 0x0004 /* retry error */ -#define AE_TDR_MASK 0xff03 /* time domain reflectometry counter */ - -#define SWAP(x) (((x & 0xff) << 8 ) | (( x >> 8) & 0xff)) - diff --git a/sys/arch/amiga/dev/if_le.c b/sys/arch/amiga/dev/if_le.c index e8cd31ee5d23..9e7e2085c1db 100644 --- a/sys/arch/amiga/dev/if_le.c +++ b/sys/arch/amiga/dev/if_le.c @@ -1,6 +1,7 @@ -/* $NetBSD: if_le.c,v 1.25 1997/03/17 17:51:41 is Exp $ */ +/* $NetBSD: if_le.c,v 1.26 1997/03/27 21:15:13 veego Exp $ */ /*- + * Copyright (c) 1997 Jason R. Thorpe and Bernd Ernesti. All rights reserved. * Copyright (c) 1995 Charles M. Hannum. All rights reserved. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -18,6 +19,8 @@ * 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 for the NetBSD Project + * by Bernd Ernesti and Jason R. Thorpe. * 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 @@ -69,9 +72,6 @@ #include #include -/* offsets for: ID, REGS, MEM */ -int lestd[] = { 0, 0x4000, 0x8000 }; - int le_zbus_match __P((struct device *, struct cfdata *, void *)); void le_zbus_attach __P((struct device *, struct device *, void *)); @@ -79,9 +79,77 @@ struct cfattach le_zbus_ca = { sizeof(struct le_softc), le_zbus_match, le_zbus_attach }; +hide void lepcnet_reset __P((struct am7990_softc *)); hide void lewrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t)); hide u_int16_t lerdcsr __P((struct am7990_softc *, u_int16_t)); +hide u_int16_t ariadne_swapreg __P((u_int16_t)); +hide void ariadne_wrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t)); +hide u_int16_t ariadne_rdcsr __P((struct am7990_softc *, u_int16_t)); +hide void ariadne_wribcr __P((struct am7990_softc *, u_int16_t, u_int16_t)); +integrate void ariadne_copytodesc_word __P((struct am7990_softc *, void *, int, int)); +integrate void ariadne_copyfromdesc_word __P((struct am7990_softc *, void *, int, int)); +integrate void ariadne_copytobuf_word __P((struct am7990_softc *, void *, int, int)); +integrate void ariadne_copyfrombuf_word __P((struct am7990_softc *, void *, int, int)); +integrate void ariadne_zerobuf_word __P((struct am7990_softc *, int, int)); +void ariadne_autoselect __P((struct am7990_softc *, int)); +int ariadne_mediachange __P((struct am7990_softc *)); +void ariadne_hwinit __P((struct am7990_softc *)); + +/* + * Media types supported by the Ariadne. + */ +int lemedia_ariadne[] = { + IFM_ETHER | IFM_10_T, + IFM_ETHER | IFM_10_2, + IFM_ETHER | IFM_AUTO, +}; +#define NLEMEDIA_ARIADNE (sizeof(lemedia_ariadne) / sizeof(lemedia_ariadne[0])) + + +hide u_int16_t +ariadne_swapreg(val) + u_int16_t val; +{ + + return (((val & 0xff) << 8 ) | (( val >> 8) & 0xff)); +} + +hide void +ariadne_wrcsr(sc, port, val) + struct am7990_softc *sc; + u_int16_t port, val; +{ + struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; + + ler1->ler1_rap = ariadne_swapreg(port); + ler1->ler1_rdp = ariadne_swapreg(val); +} + +hide u_int16_t +ariadne_rdcsr(sc, port) + struct am7990_softc *sc; + u_int16_t port; +{ + struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; + u_int16_t val; + + ler1->ler1_rap = ariadne_swapreg(port); + val = ariadne_swapreg(ler1->ler1_rdp); + return (val); +} + +hide void +ariadne_wribcr(sc, port, val) + struct am7990_softc *sc; + u_int16_t port, val; +{ + struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; + + ler1->ler1_rap = ariadne_swapreg(port); + ler1->ler1_idp = ariadne_swapreg(val); +} + hide void lewrcsr(sc, port, val) struct am7990_softc *sc; @@ -106,6 +174,91 @@ lerdcsr(sc, port) return (val); } +hide void +lepcnet_reset(sc) + struct am7990_softc *sc; +{ + struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; + volatile int dummy; + + dummy = ler1->ler1_reset; /* Reset PCNet-ISA */ +} + +void +ariadne_autoselect(sc, on) + struct am7990_softc *sc; + int on; +{ + + /* + * on = 0: autoselect disabled + * on = 1: autoselect enabled + */ + if (on == 0) + ariadne_wribcr(sc, LE_BCR_MC, 0x0000); + else + ariadne_wribcr(sc, LE_BCR_MC, LE_MC_ASEL); +} + +int +ariadne_mediachange(sc) + struct am7990_softc *sc; +{ + struct ifmedia *ifm = &sc->sc_media; + + if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) + return (EINVAL); + + /* + * Switch to the selected media. If autoselect is + * set, switch it on otherwise disable it. We'll + * switch to the other media when we detect loss of + * carrier. + */ + switch (IFM_SUBTYPE(ifm->ifm_media)) { + case IFM_10_T: + sc->sc_initmodemedia = 1; + am7990_init(sc); + break; + + case IFM_10_2: + sc->sc_initmodemedia = 0; + am7990_init(sc); + break; + + case IFM_AUTO: + sc->sc_initmodemedia = 2; + ariadne_hwinit(sc); + break; + + default: + return (EINVAL); + } + + return (0); +} + +void +ariadne_hwinit(sc) + struct am7990_softc *sc; +{ + + /* + * Re-program LEDs to match meaning used on the Ariadne board. + */ + ariadne_wribcr(sc, LE_BCR_LED1, 0x0090); + ariadne_wribcr(sc, LE_BCR_LED2, 0x0081); + ariadne_wribcr(sc, LE_BCR_LED3, 0x0084); + + /* + * Enabel/Disable auto selection + */ + if (sc->sc_initmodemedia == 2) + ariadne_autoselect(sc, 1); + else + ariadne_autoselect(sc, 0); +} + int le_zbus_match(parent, cfp, aux) struct device *parent; @@ -122,6 +275,10 @@ le_zbus_match(parent, cfp, aux) if (zap->manid == 1053 && zap->prodid == 1) return (1); + /* Ariadne ethernet card */ + if (zap->manid == 2167 && zap->prodid == 201) + return (1); + return (0); } @@ -135,43 +292,79 @@ le_zbus_attach(parent, self, aux) struct zbus_args *zap = aux; u_long ser; - lesc->sc_r1 = (struct lereg1 *)(lestd[1] + (int)zap->va); - sc->sc_mem = (void *)(lestd[2] + (int)zap->va); - - sc->sc_copytodesc = am7990_copytobuf_contig; - sc->sc_copyfromdesc = am7990_copyfrombuf_contig; - sc->sc_copytobuf = am7990_copytobuf_contig; - sc->sc_copyfrombuf = am7990_copyfrombuf_contig; - sc->sc_zerobuf = am7990_zerobuf_contig; - - sc->sc_rdcsr = lerdcsr; - sc->sc_wrcsr = lewrcsr; - sc->sc_hwinit = NULL; - + /* This has no effect on PCnet-ISA LANCE chips */ sc->sc_conf3 = LE_C3_BSWP; - sc->sc_addr = 0x8000; /* * Manufacturer decides the 3 first bytes, i.e. ethernet vendor ID. */ switch (zap->manid) { - case 514: + case 514: /* Commodore */ sc->sc_memsize = 32768; sc->sc_enaddr[0] = 0x00; sc->sc_enaddr[1] = 0x80; sc->sc_enaddr[2] = 0x10; + lesc->sc_r1 = (struct lereg1 *)(0x4000 + (int)zap->va); + sc->sc_mem = (void *)(0x8000 + (int)zap->va); + sc->sc_addr = 0x8000; + sc->sc_copytodesc = am7990_copytobuf_contig; + sc->sc_copyfromdesc = am7990_copyfrombuf_contig; + sc->sc_copytobuf = am7990_copytobuf_contig; + sc->sc_copyfrombuf = am7990_copyfrombuf_contig; + sc->sc_zerobuf = am7990_zerobuf_contig; + sc->sc_rdcsr = lerdcsr; + sc->sc_wrcsr = lewrcsr; + sc->sc_hwreset = NULL; + sc->sc_hwinit = NULL; break; - case 1053: + case 1053: /* Ameristar */ sc->sc_memsize = 32768; sc->sc_enaddr[0] = 0x00; sc->sc_enaddr[1] = 0x00; sc->sc_enaddr[2] = 0x9f; + lesc->sc_r1 = (struct lereg1 *)(0x4000 + (int)zap->va); + sc->sc_mem = (void *)(0x8000 + (int)zap->va); + sc->sc_addr = 0x8000; + sc->sc_copytodesc = am7990_copytobuf_contig; + sc->sc_copyfromdesc = am7990_copyfrombuf_contig; + sc->sc_copytobuf = am7990_copytobuf_contig; + sc->sc_copyfrombuf = am7990_copyfrombuf_contig; + sc->sc_zerobuf = am7990_zerobuf_contig; + sc->sc_rdcsr = lerdcsr; + sc->sc_wrcsr = lewrcsr; + sc->sc_hwreset = NULL; + sc->sc_hwinit = NULL; break; - default: + case 2167: + /* Village Tronic */ + sc->sc_memsize = 32768; + sc->sc_enaddr[0] = 0x00; + sc->sc_enaddr[1] = 0x60; + sc->sc_enaddr[2] = 0x30; + lesc->sc_r1 = (struct lereg1 *)(0x0370 + (int)zap->va); + sc->sc_mem = (void *)(0x8000 + (int)zap->va); + sc->sc_addr = 0x8000; + sc->sc_copytodesc = ariadne_copytodesc_word; + sc->sc_copyfromdesc = ariadne_copyfromdesc_word; + sc->sc_copytobuf = ariadne_copytobuf_word; + sc->sc_copyfrombuf = ariadne_copyfrombuf_word; + sc->sc_zerobuf = ariadne_zerobuf_word; + sc->sc_rdcsr = ariadne_rdcsr; + sc->sc_wrcsr = ariadne_wrcsr; + sc->sc_hwreset = lepcnet_reset; + sc->sc_hwinit = ariadne_hwinit; + sc->sc_mediachange = ariadne_mediachange; + sc->sc_supmedia = lemedia_ariadne; + sc->sc_nsupmedia = NLEMEDIA_ARIADNE; + sc->sc_defaultmedia = IFM_ETHER | IFM_AUTO; + sc->sc_initmodemedia = 2; + break; + + default: panic("le_zbus_attach: bad manid"); } @@ -190,3 +383,114 @@ le_zbus_attach(parent, self, aux) lesc->sc_isr.isr_ipl = 2; add_isr(&lesc->sc_isr); } + + +integrate void +ariadne_copytodesc_word(sc, from, boff, len) + struct am7990_softc *sc; + void *from; + int boff, len; +{ + u_short *b1 = from; + volatile u_short *b2 = sc->sc_mem + boff; + + for (len >>= 1; len > 0; len--) + *b2++ = ariadne_swapreg(*b1++); +} + +integrate void +ariadne_copyfromdesc_word(sc, to, boff, len) + struct am7990_softc *sc; + void *to; + int boff, len; +{ + volatile u_short *b1 = sc->sc_mem + boff; + u_short *b2 = to; + + for (len >>= 1; len > 0; len--) + *b2++ = ariadne_swapreg(*b1++); +} + +#define isodd(n) ((n) & 1) + +integrate void +ariadne_copytobuf_word(sc, from, boff, len) + struct am7990_softc *sc; + void *from; + int boff, len; +{ + u_char *a1 = from; + volatile u_char *a2 = sc->sc_mem + boff; + u_short *b1; + volatile u_short *b2; + int i; + + if (len > 0 && isodd(boff)) { + b1 = (u_short *)(a1 + 1); + b2 = (u_short *)(a2 + 1); + b2[-1] = (b2[-1] & 0xff00) | (b1[-1] & 0x00ff); + --len; + } else { + b1 = (u_short *)a1; + b2 = (u_short *)a2; + } + + for (i = len >> 1; i > 0; i--) + *b2++ = *b1++; + + if (isodd(len)) + *b2 = (*b2 & 0x00ff) | (*b1 & 0xff00); +} + +integrate void +ariadne_copyfrombuf_word(sc, to, boff, len) + struct am7990_softc *sc; + void *to; + int boff, len; +{ + volatile u_char *a1 = sc->sc_mem + boff; + u_char *a2 = to; + volatile u_short *b1; + u_short *b2; + int i; + + if (len > 0 && isodd(boff)) { + b1 = (u_short *)(a1 + 1); + b2 = (u_short *)(a2 + 1); + b2[-1] = (b2[-1] & 0xff00) | (b1[-1] & 0x00ff); + --len; + } else { + b1 = (u_short *)a1; + b2 = (u_short *)a2; + } + + for (i = len >> 1; i > 0; i--) + *b2++ = *b1++; + + if (isodd(len)) + *b2 = (*b2 & 0x00ff) | (*b1 & 0xff00); +} + +integrate void +ariadne_zerobuf_word(sc, boff, len) + struct am7990_softc *sc; + int boff, len; +{ + volatile u_char *a1 = sc->sc_mem + boff; + volatile u_short *b1; + int i; + + if (len > 0 && isodd(boff)) { + b1 = (u_short *)(a1 + 1); + b1[-1] &= 0xff00; + --len; + } else { + b1 = (u_short *)a1; + } + + for (i = len >> 1; i > 0; i--) + *b1++ = 0; + + if (isodd(len)) + *b1 &= 0x00ff; +} diff --git a/sys/arch/amiga/dev/if_levar.h b/sys/arch/amiga/dev/if_levar.h index e9b1a532e64f..ddd73d6731ca 100644 --- a/sys/arch/amiga/dev/if_levar.h +++ b/sys/arch/amiga/dev/if_levar.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_levar.h,v 1.4 1997/03/15 18:09:27 is Exp $ */ +/* $NetBSD: if_levar.h,v 1.5 1997/03/27 21:15:14 veego Exp $ */ /* * Copyright (c) 1982, 1990 The Regents of the University of California. @@ -34,11 +34,16 @@ */ /* - * LANCE registers. + * LANCE and PCnet-ISA registers. */ struct lereg1 { - u_short ler1_rdp; /* data port */ - u_short ler1_rap; /* register select port */ + u_int16_t ler1_rdp; /* data port */ + u_int16_t ler1_rap; /* register select port */ + /* + * The next two registers are only available on PCnet-ISA cards. + */ + u_int16_t ler1_reset; /* reading this resets the PCnet-ISA */ + u_int16_t ler1_idp; /* isa configuration port */ }; /*