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

📄 if_de.c

📁 国产CPU-龙芯(loongson)BIOS源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*	$Id: if_de.c,v 1.1.1.1 2003/11/08 08:41:45 wlin Exp $	*//*	$OpenBSD: if_de.c,v 1.41 1999/07/18 03:20:18 csapuntz Exp $	*//*	$NetBSD: if_de.c,v 1.45 1997/06/09 00:34:18 thorpej Exp $	*//*- * Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com) * 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. The name of the author may not be used to endorse or promote products *    derived from this software withough specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. * * Id: if_de.c,v 1.89 1997/06/03 19:19:55 thomas Exp * *//* * DEC 21040 PCI Ethernet Controller * * Written by Matt Thomas * BPF support code stolen directly from if_ec.c * *   This driver supports the DEC DE435 or any other PCI *   board which support 21040, 21041, or 21140 (mostly). */#define	TULIP_HDR_DATA#define TULIP_NOIFMEDIA#include <sys/param.h>#include <sys/systm.h>#include <sys/mbuf.h>#include <sys/protosw.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/errno.h>#include <sys/malloc.h>#include <sys/kernel.h>#include <sys/proc.h>	/* only for declaration of wakeup() used by vm.h */#include <sys/device.h>#include <net/if.h>#if defined(SIOCSIFMEDIA) && !defined(TULIP_NOIFMEDIA)#include <net/if_media.h>#endif#include <net/if_types.h>#include <net/if_dl.h>#include <net/route.h>#include <net/netisr.h>#include "bpfilter.h"#if NBPFILTER > 0#include <net/bpf.h>#include <net/bpfdesc.h>#endif#ifdef INET#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#endif#ifdef NS#include <netns/ns.h>#include <netns/ns_if.h>#endif#include <vm/vm.h>#include <vm/vm_param.h>#include <vm/vm_kern.h>#if defined(__OpenBSD__)#include <netinet/if_ether.h>#endif#if defined(__OpenBSD__)#include <machine/bus.h>#include <dev/pci/pcireg.h>#include <dev/pci/pcivar.h>#include <dev/pci/pcidevs.h>#include <dev/ic/dc21040reg.h>#define	DEVAR_INCLUDE	"dev/pci/if_devar.h"#endif /* __OpenBSD__ *//* * Intel CPUs should use I/O mapped access. */#if defined(__i386__)#define	TULIP_IOMAPPED#endif/* * This turns on all sort of debugging stuff and make the * driver much larger. */#if 0#define TULIP_DEBUG#endif#define	TULIP_HZ	10#include DEVAR_INCLUDE/* * This module supports *	the DEC 21040 PCI Ethernet Controller. *	the DEC 21041 PCI Ethernet Controller. *	the DEC 21140 PCI Fast Ethernet Controller. */static void tulip_mii_autonegotiate(tulip_softc_t * const sc, const unsigned phyaddr);static tulip_intrfunc_t tulip_intr_shared(void *arg);static tulip_intrfunc_t tulip_intr_normal(void *arg);static void tulip_init(tulip_softc_t * const sc);static void tulip_reset(tulip_softc_t * const sc);static ifnet_ret_t tulip_ifstart_one(struct ifnet *ifp);static ifnet_ret_t tulip_ifstart(struct ifnet *ifp);static struct mbuf *tulip_txput(tulip_softc_t * const sc, struct mbuf *m);static void tulip_txput_setup(tulip_softc_t * const sc);static void tulip_rx_intr(tulip_softc_t * const sc);static void tulip_addr_filter(tulip_softc_t * const sc);static unsigned tulip_mii_readreg(tulip_softc_t * const sc, unsigned devaddr, unsigned regno);static void tulip_mii_writereg(tulip_softc_t * const sc, unsigned devaddr, unsigned regno, unsigned data);static int tulip_mii_map_abilities(tulip_softc_t * const sc, unsigned abilities);static tulip_media_t tulip_mii_phy_readspecific(tulip_softc_t * const sc);static int tulip_srom_decode(tulip_softc_t * const sc);#if defined(IFM_ETHER)static int tulip_ifmedia_change(struct ifnet * const ifp);static void tulip_ifmedia_status(struct ifnet * const ifp, struct ifmediareq *req);#endif/* static void tulip_21140_map_media(tulip_softc_t *sc); */static voidtulip_timeout_callback(    void *arg){    tulip_softc_t * const sc = arg;    tulip_spl_t s = TULIP_RAISESPL();    sc->tulip_flags &= ~TULIP_TIMEOUTPENDING;    sc->tulip_probe_timeout -= 1000 / TULIP_HZ;    (sc->tulip_boardsw->bd_media_poll)(sc, TULIP_MEDIAPOLL_TIMER);    TULIP_RESTORESPL(s);}static voidtulip_timeout(    tulip_softc_t * const sc){    if (sc->tulip_flags & TULIP_TIMEOUTPENDING)	return;    sc->tulip_flags |= TULIP_TIMEOUTPENDING;    timeout(tulip_timeout_callback, sc, (hz + TULIP_HZ / 2) / TULIP_HZ);}#if defined(TULIP_NEED_FASTTIMEOUT)static voidtulip_fasttimeout_callback(    void *arg){    tulip_softc_t * const sc = arg;    tulip_spl_t s = TULIP_RAISESPL();    sc->tulip_flags &= ~TULIP_FASTTIMEOUTPENDING;    (sc->tulip_boardsw->bd_media_poll)(sc, TULIP_MEDIAPOLL_FASTTIMER);    TULIP_RESTORESPL(s);}static voidtulip_fasttimeout(    tulip_softc_t * const sc){    if (sc->tulip_flags & TULIP_FASTTIMEOUTPENDING)	return;    sc->tulip_flags |= TULIP_FASTTIMEOUTPENDING;    timeout(tulip_fasttimeout_callback, sc, 1);}#endifstatic inttulip_txprobe(    tulip_softc_t * const sc){    struct mbuf *m;    /*     * Before we are sure this is the right media we need     * to send a small packet to make sure there's carrier.     * Strangely, BNC and AUI will "see" receive data if     * either is connected so the transmit is the only way     * to verify the connectivity.     */    MGETHDR(m, M_DONTWAIT, MT_DATA);    if (m == NULL)	return 0;    /*     * Construct a LLC TEST message which will point to ourselves.     */    bcopy(sc->tulip_enaddr, mtod(m, struct ether_header *)->ether_dhost, 6);    bcopy(sc->tulip_enaddr, mtod(m, struct ether_header *)->ether_shost, 6);    mtod(m, struct ether_header *)->ether_type = htons(3);    mtod(m, unsigned char *)[14] = 0;    mtod(m, unsigned char *)[15] = 0;    mtod(m, unsigned char *)[16] = 0xE3;	/* LLC Class1 TEST (no poll) */    m->m_len = m->m_pkthdr.len = sizeof(struct ether_header) + 3;    /*     * send it!     */    sc->tulip_cmdmode |= TULIP_CMD_TXRUN;    sc->tulip_intrmask |= TULIP_STS_TXINTR;    sc->tulip_flags |= TULIP_TXPROBE_ACTIVE;    TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);    TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);    if ((m = tulip_txput(sc, m)) != NULL)	m_freem(m);    sc->tulip_probe.probe_txprobes++;    return 1;}#ifdef BIG_PACKET#define TULIP_SIAGEN_WATCHDOG	(sc->tulip_if.if_mtu > ETHERMTU ? TULIP_WATCHDOG_RXDISABLE|TULIP_WATCHDOG_TXDISABLE : 0)#else#define	TULIP_SIAGEN_WATCHDOG	0#endifstatic voidtulip_media_set(    tulip_softc_t * const sc,    tulip_media_t media){    const tulip_media_info_t *mi = sc->tulip_mediums[media];    if (mi == NULL)	return;    /*     * If we are switching media, make sure we don't think there's     * any stale RX activity     */    sc->tulip_flags &= ~TULIP_RXACT;    if (mi->mi_type == TULIP_MEDIAINFO_SIA) {	TULIP_CSR_WRITE(sc, csr_sia_connectivity, TULIP_SIACONN_RESET);	TULIP_CSR_WRITE(sc, csr_sia_tx_rx,        mi->mi_sia_tx_rx);	if (sc->tulip_features & TULIP_HAVE_SIAGP) {	    TULIP_CSR_WRITE(sc, csr_sia_general,  mi->mi_sia_gp_control|mi->mi_sia_general|TULIP_SIAGEN_WATCHDOG);	    DELAY(50);	    TULIP_CSR_WRITE(sc, csr_sia_general,  mi->mi_sia_gp_data|mi->mi_sia_general|TULIP_SIAGEN_WATCHDOG);	} else {	    TULIP_CSR_WRITE(sc, csr_sia_general,  mi->mi_sia_general|TULIP_SIAGEN_WATCHDOG);	}	TULIP_CSR_WRITE(sc, csr_sia_connectivity, mi->mi_sia_connectivity);    } else if (mi->mi_type == TULIP_MEDIAINFO_GPR) {#define	TULIP_GPR_CMDBITS	(TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER|TULIP_CMD_TXTHRSHLDCTL)	/*	 * If the cmdmode bits don't match the currently operating mode,	 * set the cmdmode appropriately and reset the chip.	 */	if (((mi->mi_cmdmode ^ TULIP_CSR_READ(sc, csr_command)) & TULIP_GPR_CMDBITS) != 0) {	    sc->tulip_cmdmode &= ~TULIP_GPR_CMDBITS;	    sc->tulip_cmdmode |= mi->mi_cmdmode;	    tulip_reset(sc);	}	TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET|sc->tulip_gpinit);	DELAY(10);	TULIP_CSR_WRITE(sc, csr_gp, (u_int8_t) mi->mi_gpdata);    } else if (mi->mi_type == TULIP_MEDIAINFO_SYM) {	/*	 * If the cmdmode bits don't match the currently operating mode,	 * set the cmdmode appropriately and reset the chip.	 */	if (((mi->mi_cmdmode ^ TULIP_CSR_READ(sc, csr_command)) & TULIP_GPR_CMDBITS) != 0) {	    sc->tulip_cmdmode &= ~TULIP_GPR_CMDBITS;	    sc->tulip_cmdmode |= mi->mi_cmdmode;	    tulip_reset(sc);	}	TULIP_CSR_WRITE(sc, csr_sia_general, mi->mi_gpcontrol);	TULIP_CSR_WRITE(sc, csr_sia_general, mi->mi_gpdata);    } else if (mi->mi_type == TULIP_MEDIAINFO_MII	       && sc->tulip_probe_state != TULIP_PROBE_INACTIVE) {	int idx;	if (sc->tulip_features & TULIP_HAVE_SIAGP) {	    const u_int8_t *dp;	    dp = &sc->tulip_rombuf[mi->mi_reset_offset];	    for (idx = 0; idx < mi->mi_reset_length; idx++, dp += 2) {		DELAY(10);		TULIP_CSR_WRITE(sc, csr_sia_general, (dp[0] + 256 * dp[1]) << 16);	    }	    sc->tulip_phyaddr = mi->mi_phyaddr;	    dp = &sc->tulip_rombuf[mi->mi_gpr_offset];	    for (idx = 0; idx < mi->mi_gpr_length; idx++, dp += 2) {		DELAY(10);		TULIP_CSR_WRITE(sc, csr_sia_general, (dp[0] + 256 * dp[1]) << 16);	    }	} else {	    for (idx = 0; idx < mi->mi_reset_length; idx++) {		DELAY(10);		TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_rombuf[mi->mi_reset_offset + idx]);	    }	    sc->tulip_phyaddr = mi->mi_phyaddr;	    for (idx = 0; idx < mi->mi_gpr_length; idx++) {		DELAY(10);		TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_rombuf[mi->mi_gpr_offset + idx]);	    }	}	if (sc->tulip_flags & TULIP_TRYNWAY) {	    tulip_mii_autonegotiate(sc, sc->tulip_phyaddr);	} else if ((sc->tulip_flags & TULIP_DIDNWAY) == 0) {	    u_int32_t data = tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_CONTROL);	    data &= ~(PHYCTL_SELECT_100MB|PHYCTL_FULL_DUPLEX|PHYCTL_AUTONEG_ENABLE);	    data &= ~(PHYCTL_POWERDOWN|PHYCTL_ISOLATE);	    sc->tulip_flags &= ~TULIP_DIDNWAY;	    if (TULIP_IS_MEDIA_FD(media))		data |= PHYCTL_FULL_DUPLEX;	    if (TULIP_IS_MEDIA_100MB(media))		data |= PHYCTL_SELECT_100MB;	    tulip_mii_writereg(sc, sc->tulip_phyaddr, PHYREG_CONTROL, data);	}    }}static voidtulip_linkup(    tulip_softc_t * const sc,    tulip_media_t media){    if ((sc->tulip_flags & TULIP_LINKUP) == 0)	sc->tulip_flags |= TULIP_PRINTLINKUP;    sc->tulip_flags |= TULIP_LINKUP;    sc->tulip_if.if_flags &= ~IFF_OACTIVE;#if 0 /* XXX how does with work with ifmedia? */    if ((sc->tulip_flags & TULIP_DIDNWAY) == 0) {	if (sc->tulip_if.if_flags & IFF_FULLDUPLEX) {	    if (TULIP_CAN_MEDIA_FD(media)		    && sc->tulip_mediums[TULIP_FD_MEDIA_OF(media)] != NULL)		media = TULIP_FD_MEDIA_OF(media);	} else {	    if (TULIP_IS_MEDIA_FD(media)		    && sc->tulip_mediums[TULIP_HD_MEDIA_OF(media)] != NULL)		media = TULIP_HD_MEDIA_OF(media);	}    }#endif    if (sc->tulip_media != media) {#ifdef TULIP_DEBUG	sc->tulip_dbg.dbg_last_media = sc->tulip_media;#endif	sc->tulip_media = media;	sc->tulip_flags |= TULIP_PRINTMEDIA;	if (TULIP_IS_MEDIA_FD(sc->tulip_media)) {	    sc->tulip_cmdmode |= TULIP_CMD_FULLDUPLEX;	} else if (sc->tulip_chipid != TULIP_21041 || (sc->tulip_flags & TULIP_DIDNWAY) == 0) {	    sc->tulip_cmdmode &= ~TULIP_CMD_FULLDUPLEX;	}    }    /*     * We could set probe_timeout to 0 but setting to 3000 puts this     * in one central place and the only matters is tulip_link is     * followed by a tulip_timeout.  Therefore setting it should not     * result in aberrant behavour.     */    sc->tulip_probe_timeout = 3000;    sc->tulip_probe_state = TULIP_PROBE_INACTIVE;    sc->tulip_flags &= ~(TULIP_TXPROBE_ACTIVE|TULIP_TRYNWAY);    if (sc->tulip_flags & TULIP_INRESET) {	tulip_media_set(sc, sc->tulip_media);    } else if (sc->tulip_probe_media != sc->tulip_media) {	/*	 * No reason to change media if we have the right media.	 */	tulip_reset(sc);    }    tulip_init(sc);}static voidtulip_media_print(    tulip_softc_t * const sc){    if ((sc->tulip_flags & TULIP_LINKUP) == 0)	return;    if (sc->tulip_flags & TULIP_PRINTMEDIA) {	printf(TULIP_PRINTF_FMT ": enabling %s port\n",	       TULIP_PRINTF_ARGS,	       tulip_mediums[sc->tulip_media]);	sc->tulip_flags &= ~(TULIP_PRINTMEDIA|TULIP_PRINTLINKUP);    } else if (sc->tulip_flags & TULIP_PRINTLINKUP) {	printf(TULIP_PRINTF_FMT ": link up\n", TULIP_PRINTF_ARGS);	sc->tulip_flags &= ~TULIP_PRINTLINKUP;    }}#if defined(TULIP_DO_GPR_SENSE)static tulip_media_ttulip_21140_gpr_media_sense(    tulip_softc_t * const sc){    tulip_media_t maybe_media = TULIP_MEDIA_UNKNOWN;    tulip_media_t last_media = TULIP_MEDIA_UNKNOWN;    tulip_media_t media;    /*     * If one of the media blocks contained a default media flag,     * use that.     */    for (media = TULIP_MEDIA_UNKNOWN; media < TULIP_MEDIA_MAX; media++) {	const tulip_media_info_t *mi;	/*	 * Media is not supported (or is full-duplex).	 */	if ((mi = sc->tulip_mediums[media]) == NULL || TULIP_IS_MEDIA_FD(media))	    continue;	if (mi->mi_type != TULIP_MEDIAINFO_GPR)	    continue;	/*	 * Remember the media is this is the "default" media.	 */	if (mi->mi_default && maybe_media == TULIP_MEDIA_UNKNOWN)	    maybe_media = media;	/*

⌨️ 快捷键说明

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