⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 am7990.c

📁 很好的一个嵌入式linux平台下的bootloader
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	$OpenBSD: am7990.c,v 1.15 1999/02/28 05:02:16 jason Exp $	*//*	$NetBSD: am7990.c,v 1.22 1996/10/13 01:37:19 christos Exp $	*//*- * Copyright (c) 1995 Charles M. Hannum.  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 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.2 (Berkeley) 11/16/93 */#ifdef PROM#include <sys/ioctl.h>#else#include "bpfilter.h"#include <sys/param.h>#include <sys/systm.h>#include <sys/mbuf.h> #include <sys/syslog.h>#include <sys/socket.h>#include <sys/device.h>#include <sys/malloc.h>#include <sys/ioctl.h>#include <sys/errno.h>#include <net/if.h>#include <net/if_media.h>#ifdef INET#include <netinet/in.h>#include <netinet/if_ether.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#endif#if NBPFILTER > 0#include <net/bpf.h>#include <net/bpfdesc.h>#endif#include <dev/ic/am7990reg.h>#include <dev/ic/am7990var.h>#endif#ifdef LEDEBUGvoid am7990_recv_print __P((struct am7990_softc *, int));void am7990_xmit_print __P((struct am7990_softc *, int));#endifintegrate void am7990_rint __P((struct am7990_softc *));integrate void am7990_tint __P((struct am7990_softc *));integrate int am7990_put __P((struct am7990_softc *, int, struct mbuf *));integrate struct mbuf *am7990_get __P((struct am7990_softc *, int, int));integrate void am7990_read __P((struct am7990_softc *, int, int)); hide void am7990_shutdown __P((void *));#define	ifp	(&sc->sc_arpcom.ac_if)#if 0	/* XXX what do we do about this?!  --thorpej */static inline u_int16_t ether_cmp __P((void *, void *));/* * Compare two Ether/802 addresses for equality, inlined and * unrolled for speed.  I'd love to have an inline assembler * version of this...   XXX: Who wanted that? mycroft? * I wrote one, but the following is just as efficient. * This expands to 10 short m68k instructions! -gwr * Note: use this like bcmp() */static inline u_shortether_cmp(one, two)	void *one, *two;{	register u_int16_t *a = (u_short *) one;	register u_int16_t *b = (u_short *) two;	register u_int16_t diff;	diff  = *a++ - *b++;	diff |= *a++ - *b++;	diff |= *a++ - *b++;	return (diff);}#define ETHER_CMP	ether_cmp#endif /* XXX */#ifndef	ETHER_CMP#define	ETHER_CMP(a, b) bcmp((a), (b), ETHER_ADDR_LEN)#endif#ifdef PROM#ifdef LEDEBUG#define printf(fmt, args...) _mon_printf(fmt , ## args)#endifstruct cfdriver le_cd = {    0,    "le",    le_pci_match,    le_pci_attach,    DV_IFNET,    sizeof(struct le_softc)};#ifndef IFF_MULTICAST#define IFF_MULTICAST 0#endif#define	UNIT_TO_SOFTC(unit)	((struct am7990_softc *) le_cd.cd_devs[unit])#define IFP_TO_SOFTC(ifp)	 UNIT_TO_SOFTC((ifp)->if_unit)#else#define IFP_TO_SOFTC(ifp)	 (ifp)->softc/* * am7990 configuration driver.  Attachments are provided by * machine-dependent driver front-ends. */struct cfdriver le_cd = {	NULL, "le", DV_IFNET};#endifvoidam7990_config(sc)	struct am7990_softc *sc;{	int mem;	/* Make sure the chip is stopped. */	am7990_stop(sc);	/* Initialize ifnet structure. */#ifdef PROM	{	/* boost FIFO thresholds */	    unsigned int val;	    val = 2 << 12;	/* RCVFW=112 */	    val |= 3 << 10;	/* XMTSP=220 */	    val |= 0 << 8;	/* XMTFW=16 */	    le_pci_wrcsr (sc, 80, val);	}#else	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);	ifp->if_softc = sc;#endif	ifp->if_start = am7990_start;	ifp->if_ioctl = am7990_ioctl;	ifp->if_watchdog = am7990_watchdog;	ifp->if_flags =	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;#ifdef LANCE_REVC_BUG	ifp->if_flags &= ~IFF_MULTICAST;#endif	/* Attach the interface. */#ifdef PROM	ifp->if_name = "en";	ether_attach(ifp);#else	if_attach(ifp);	ether_ifattach(ifp);#endif#if NBPFILTER > 0	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));#endif	if (sc->sc_memsize > 131072)		sc->sc_memsize = 131072;	switch (sc->sc_memsize) {	case 8192:		sc->sc_nrbuf = 4;		sc->sc_ntbuf = 1;		break;	case 16384:		sc->sc_nrbuf = 8;		sc->sc_ntbuf = 2;		break;	case 32768:		sc->sc_nrbuf = 16;		sc->sc_ntbuf = 4;		break;	case 65536:		sc->sc_nrbuf = 32;		sc->sc_ntbuf = 8;		break;	case 131072:		sc->sc_nrbuf = 64;		sc->sc_ntbuf = 16;		break;	default:#ifdef PROM		log(LOG_ERR, "am7990_config: weird memory size %d", sc->sc_memsize);		panic("am7990_config: weird memory size");#else		panic("am7990_config: weird memory size %d", sc->sc_memsize);#endif	}	printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));	printf("%s: %d receive buffers, %d transmit buffers\n",	    sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf);#ifndef PROM	sc->sc_sh = shutdownhook_establish(am7990_shutdown, sc);	if (sc->sc_sh == NULL)		panic("am7990_config: can't establish shutdownhook");#endif	mem = 0;	sc->sc_initaddr = mem;	mem += sizeof(struct leinit);	sc->sc_rmdaddr = mem;	mem += sizeof(struct lermd) * sc->sc_nrbuf;	sc->sc_tmdaddr = mem;	mem += sizeof(struct letmd) * sc->sc_ntbuf;	sc->sc_rbufaddr = mem;	mem += LEBLEN * sc->sc_nrbuf;	sc->sc_tbufaddr = mem;	mem += LEBLEN * sc->sc_ntbuf;#ifdef PROM #ifdef LEDEBUG	printf ("am7990_config: initaddr=%x rmdaddr=%x tmdaddr=%x rbufaddr=%x tbufaddr=%x\n", 	     sc->sc_initaddr,	     sc->sc_rmdaddr,	     sc->sc_tmdaddr,	     sc->sc_rbufaddr,	     sc->sc_tbufaddr);#endif#endif#ifdef notyet	if (mem > ...)		panic(...);#endif}voidam7990_reset(sc)	struct am7990_softc *sc;{	int s;	s = splimp();	am7990_init(sc);	splx(s);}/* * Set up the initialization block and the descriptor rings. */voidam7990_meminit(sc)	register struct am7990_softc *sc;{	u_long a;	int bix;	struct leinit init;	struct lermd rmd;	struct letmd tmd;#if NBPFILTER > 0	if (ifp->if_flags & IFF_PROMISC)		init.init_mode = htoms(LE_MODE_NORMAL | LE_MODE_PROM);	else#endif		init.init_mode = htoms(LE_MODE_NORMAL);#ifdef PROM	init.init_mode |= htoms(LE_MODE_PORTSEL);#endif	init.init_padr[0] =	    htoms((sc->sc_arpcom.ac_enaddr[1] << 8) | sc->sc_arpcom.ac_enaddr[0]);	init.init_padr[1] =	    htoms((sc->sc_arpcom.ac_enaddr[3] << 8) | sc->sc_arpcom.ac_enaddr[2]);	init.init_padr[2] =	    htoms((sc->sc_arpcom.ac_enaddr[5] << 8) | sc->sc_arpcom.ac_enaddr[4]);	am7990_setladrf(&sc->sc_arpcom, init.init_ladrf);	sc->sc_last_rd = 0;	sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;	a = sc->sc_addr + LE_RMDADDR(sc, 0);	init.init_rdra = htoms(a);	init.init_rlen = htoms(((a >> 16) & 0xff) | ((ffs(sc->sc_nrbuf) - 1) << 13));	a = sc->sc_addr + LE_TMDADDR(sc, 0);	init.init_tdra = htoms(a);	init.init_tlen = htoms(((a >> 16) & 0xff) | ((ffs(sc->sc_ntbuf) - 1) << 13));	(*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));	/*	 * Set up receive ring descriptors.	 */	for (bix = 0; bix < sc->sc_nrbuf; bix++) {		a = sc->sc_addr + LE_RBUFADDR(sc, bix);		rmd.rmd0 = htoms(a);		rmd.rmd1_hadr = a >> 16;		rmd.rmd1_bits = LE_R1_OWN;		rmd.rmd2 = htoms(-LEBLEN | LE_XMD2_ONES);		rmd.rmd3 = htoms(0);		(*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),		    sizeof(rmd));	}	/*	 * Set up transmit ring descriptors.	 */	for (bix = 0; bix < sc->sc_ntbuf; bix++) {		a = sc->sc_addr + LE_TBUFADDR(sc, bix);		tmd.tmd0 = htoms(a);		tmd.tmd1_hadr = a >> 16;		tmd.tmd1_bits = 0;		tmd.tmd2 = htoms(0 | LE_XMD2_ONES);		tmd.tmd3 = htoms(0);		(*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),		    sizeof(tmd));	}}voidam7990_stop(sc)	struct am7990_softc *sc;{	(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);}#ifdef PROMintam7990_linkstatus (struct am7990_softc *sc){    static int linkup = 0;    int status = le_pci_rdanr(sc, 30, 1);	    if (status & 4) {	status = le_pci_rdanr(sc, 30, 24);	if (linkup == 0) {	    linkup = 1;	    printf ("%s: %dMb/s %cD link up\n", sc->sc_dev.dv_xname, 		    (status & 1) ? 100 : 10, (status & 4) ? 'F' : 'H');	}    }    else {	if (linkup != 0) {	    linkup = 0;	    printf ("%s: link down\n", sc->sc_dev.dv_xname);	}    }    return linkup;}#endif/* * Initialization of interface; set up initialization block * and transmit/receive descriptor rings. */voidam7990_init(sc)	register struct am7990_softc *sc;{	register int timo;	u_long a;	(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);	DELAY(100);	/* Newer LANCE chips have a reset register */	if (sc->sc_hwreset)		(*sc->sc_hwreset)(sc);	/* Set the correct byte swapping mode, etc. */	(*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3);	/* Set up LANCE init block. */	am7990_meminit(sc);	/* Give LANCE the physical address of its init block. */	a = sc->sc_addr + LE_INITADDR(sc);	(*sc->sc_wrcsr)(sc, LE_CSR1, a);	(*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16);	/* Try to initialize the LANCE. */	DELAY(100);	(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT);	/* Wait for initialization to finish. */	for (timo = 100000; timo; timo--)		if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON)			break;	if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) {		/* Start the LANCE. */		(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT |		    LE_C0_IDON);		ifp->if_flags |= IFF_RUNNING;		ifp->if_flags &= ~IFF_OACTIVE;		ifp->if_timer = 0;		am7990_start(ifp);	} else		printf("%s: controller failed to initialize\n", sc->sc_dev.dv_xname);	if (sc->sc_hwinit)		(*sc->sc_hwinit)(sc);#if PROM	{	    /* wait a bit for the link to comw up */	    int timeout = 2400;		    while (timeout > 0) {		if (am7990_linkstatus (sc))		    break;		DELAY (100000);		timeout -= 100;	    }	}#endif}/* * Routine to copy from mbuf chain to transmit buffer in * network buffer memory. */integrate intam7990_put(sc, boff, m)	struct am7990_softc *sc;	int boff;	register struct mbuf *m;{	register struct mbuf *n;	register int len, tlen = 0;	for (; m; m = n) {		len = m->m_len;		if (len == 0) {			MFREE(m, n);			continue;		}		(*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, len);		boff += len;		tlen += len;		MFREE(m, n);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -