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

📄 if_tx.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*	$OpenBSD: if_tx.c,v 1.3 1998/10/10 04:30:09 jason Exp $	*//*	$Id: if_tx.c,v 1.20.2.3 1999/04/23 05:47:53 semenu Exp $ *//*- * Copyright (c) 1997 Semen Ustimenko (semen@iclub.nsu.ru) * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. * * *//* * EtherPower II 10/100  Fast Ethernet (tx0) * (aka SMC9432TX based on SMC83c170 EPIC chip) *  * Thanks are going to Steve Bauer and Jason Wright. * * todo: *	Deal with bus mastering, i.e. i realy don't know what to do with *	    it and how it can improve performance. *	Implement FULL IFF_MULTICAST support. *	Test, test and test again:-( *	 *//* We should define compile time options before if_txvar.h included *//*#define	EPIC_NOIFMEDIA	1*//*#define	EPIC_USEIOSPACE	1*/#define	EARLY_RX	1/*#define	EPIC_DEBUG	1*/#if defined(EPIC_DEBUG)#define dprintf(a) printf a#else#define dprintf(a)#endif/* Macro to get either mbuf cluster or nothing */#define EPIC_MGETCLUSTER(m) \	{ MGETHDR((m),M_DONTWAIT,MT_DATA); \	  if (m) { \	    MCLGET((m),M_DONTWAIT); \	    if( NULL == ((m)->m_flags & M_EXT) ){ \	      m_freem(m); \	      (m) = NULL; \	    } \	  } \	}#include "bpfilter.h"#include "pci.h"#include "opt_bdg.h"#if NPCI > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/mbuf.h>#include <sys/malloc.h>#include <sys/kernel.h>#include <sys/socket.h>#include <sys/sockio.h>#include <net/if.h>#include <net/if_dl.h>#include <net/if_types.h>#if !defined(SIOCSIFMEDIA) || defined(EPIC_NOIFMEDIA)#define EPIC_NOIFMEDIA	1#else#include <net/if_media.h>#endif#ifdef INET#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#endif#ifdef IPX#include <netipx/ipx.h>#include <netipx/ipx_if.h>#endif#ifdef NS#include <netns/ns.h>#include <netns/ns_if.h>#endif#if NBPFILTER > 0#include <net/bpf.h>#include <net/bpfdesc.h>#endif#if defined(__OpenBSD__)#include <sys/ioctl.h>#include <sys/errno.h>#include <sys/device.h>#include <netinet/if_ether.h>#include <vm/vm.h>#include <dev/pci/pcivar.h>#include <dev/pci/pcireg.h>#include <dev/pci/pcidevs.h>#include <dev/pci/if_txvar.h>#else /* __FreeBSD__ */#include <net/if_mib.h>#include <netinet/in.h>#include <netinet/if_ether.h>#include <vm/vm.h>#include <vm/pmap.h>#include <machine/clock.h>#include <pci/pcivar.h>#include <pci/if_txvar.h>#ifdef BRIDGE#include <net/bridge.h>#endif#endif#if defined(__FreeBSD__)#if __FreeBSD_version >= 300000#define EPIC_IFIOCTL_CMD_TYPE u_long#else#define EPIC_IFIOCTL_CMD_TYPE int#endif#define EPIC_INTR_RET_TYPE void#else /* __OpenBSD__ */#define EPIC_IFIOCTL_CMD_TYPE u_long#define EPIC_INTR_RET_TYPE int#endifstatic int epic_ifioctl __P((register struct ifnet *, EPIC_IFIOCTL_CMD_TYPE, caddr_t));static EPIC_INTR_RET_TYPE epic_intr __P((void *));static int epic_common_attach __P((epic_softc_t *));static void epic_ifstart __P((struct ifnet * const));static void epic_ifwatchdog __P((struct ifnet *));static int epic_init __P((epic_softc_t *));static void epic_stop __P((epic_softc_t *));static __inline void epic_rx_done __P((epic_softc_t *));static __inline void epic_tx_done __P((epic_softc_t *));static int epic_init_rings __P((epic_softc_t *));static void epic_free_rings __P((epic_softc_t *));static void epic_stop_activity __P((epic_softc_t *));static void epic_start_activity __P((epic_softc_t *));static void epic_set_rx_mode __P((epic_softc_t *));static void epic_set_tx_mode __P((epic_softc_t *));static void epic_set_mc_table __P((epic_softc_t *));static void epic_set_media_speed __P((epic_softc_t *));static void epic_init_phy __P((epic_softc_t *));static void epic_dump_state __P((epic_softc_t *));static int epic_autoneg __P((epic_softc_t *));static int epic_read_eeprom __P((epic_softc_t *,u_int16_t));static void epic_output_eepromw __P((epic_softc_t *, u_int16_t));static u_int16_t epic_input_eepromw __P((epic_softc_t *));static u_int8_t epic_eeprom_clock __P((epic_softc_t *,u_int8_t));static void epic_write_eepromreg __P((epic_softc_t *,u_int8_t));static u_int8_t epic_read_eepromreg __P((epic_softc_t *));static u_int16_t epic_read_phy_register __P((epic_softc_t *, u_int16_t));static void epic_write_phy_register __P((epic_softc_t *, u_int16_t, u_int16_t));#if !defined(EPIC_NOIFMEDIA)static int epic_ifmedia_change __P((struct ifnet *));static void epic_ifmedia_status __P((struct ifnet *, struct ifmediareq *));#endifint epic_mtypes [] = {	IFM_ETHER | IFM_10_T,	IFM_ETHER | IFM_10_T | IFM_FDX,	IFM_ETHER | IFM_100_TX,	IFM_ETHER | IFM_100_TX | IFM_FDX,	IFM_ETHER | IFM_10_T | IFM_LOOP,	IFM_ETHER | IFM_10_T | IFM_FDX | IFM_LOOP,	IFM_ETHER | IFM_10_T | IFM_LOOP | IFM_FLAG1,	IFM_ETHER | IFM_100_TX | IFM_LOOP,	IFM_ETHER | IFM_100_TX | IFM_LOOP | IFM_FLAG1,	IFM_ETHER | IFM_100_TX | IFM_FDX | IFM_LOOP,	IFM_ETHER | IFM_AUTO};#define	EPIC_MTYPESNUM (sizeof(epic_mtypes) / sizeof(epic_mtypes[0]))/* -------------------------------------------------------------------------   OS-specific part   ------------------------------------------------------------------------- */#if defined(__OpenBSD__)/* -----------------------------OpenBSD------------------------------------- */static int epic_openbsd_probe __P((struct device *,void *,void *));static void epic_openbsd_attach __P((struct device *, struct device *, void *));static void epic_shutdown __P((void *));struct cfattach tx_ca = {	sizeof(epic_softc_t), epic_openbsd_probe, epic_openbsd_attach };struct cfdriver tx_cd = {	NULL,"tx",DV_IFNET};/* Synopsis: Check if device id corresponds with SMC83C170 id. */static int epic_openbsd_probe(    struct device *parent,    void *match,    void *aux ){	struct pci_attach_args *pa = aux;	if( PCI_VENDOR(pa->pa_id) != SMC_VENDORID )		return 0;	if( PCI_PRODUCT(pa->pa_id) == CHIPID_83C170 )		return 1;	return 0;}static voidepic_openbsd_attach(    struct device *parent,    struct device *self,    void *aux ){	epic_softc_t *sc = (epic_softc_t*)self;	struct pci_attach_args *pa = aux;	pci_chipset_tag_t pc = pa->pa_pc;	pci_intr_handle_t ih;	const char *intrstr = NULL;	struct ifnet *ifp;	bus_space_tag_t iot = pa->pa_iot;	bus_addr_t iobase;	bus_size_t iosize; 	int i;#if !defined(EPIC_NOIFMEDIA)	int tmp;#endif	if( pci_io_find(pc, pa->pa_tag, PCI_CBIO, &iobase, &iosize)) {		printf(": can't find i/o space\n");		return;	}	if( bus_space_map(iot, iobase, iosize, 0, &sc->sc_sh)) {		printf(": can't map i/o space\n");		return;	}	sc->sc_st = iot;	ifp = &sc->sc_if;	bcopy(sc->sc_dev.dv_xname, ifp->if_xname,IFNAMSIZ);	ifp->if_softc = sc;	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;	ifp->if_ioctl = epic_ifioctl;	ifp->if_start = epic_ifstart;	ifp->if_watchdog = epic_ifwatchdog;	/* Do common attach procedure */	if( epic_common_attach(sc) ) return;	/* Map interrupt */	if( pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin,	    pa->pa_intrline, &ih)) {		printf(": can't map interrupt\n");		return;	}	intrstr = pci_intr_string(pc, ih);	sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, epic_intr, sc, 	    self->dv_xname);	if( NULL == sc->sc_ih ) {		printf(": can't establish interrupt");		if( intrstr )printf(" at %s",intrstr);		printf("\n");		return;	} 	printf(": %s",intrstr);	/* Display some info */	printf(" address %s",ether_sprintf(sc->sc_macaddr));	/* Read current media config and display it too */	i = PHY_READ_2( sc, DP83840_BMCR );#if !defined(EPIC_NOIFMEDIA)	tmp = IFM_ETHER;#endif	if( i & BMCR_AUTONEGOTIATION ){		printf(", Auto-Neg ");		/* To avoid bug in QS6612 read LPAR enstead of BMSR */		i = PHY_READ_2( sc, DP83840_LPAR );		if( i & (ANAR_100_TX|ANAR_100_TX_FD) ) printf("100Mbps");		else printf("10Mbps");		if( i & (ANAR_10_FD|ANAR_100_TX_FD) ) printf(" FD");#if !defined(EPIC_NOIFMEDIA)		tmp |= IFM_AUTO;#endif	} else {#if defined(EPIC_NOIFMEDIA)		ifp->if_flags |= IFF_LINK0;#endif		if( i & BMCR_100MBPS ) {			printf(", 100Mbps");#if !defined(EPIC_NOIFMEDIA)			tmp |= IFM_100_TX;#else			ifp->if_flags |= IFF_LINK2;#endif		} else {			printf(", 10Mbps");#if !defined(EPIC_NOIFMEDIA)			tmp |= IFM_10_T;#endif		}		if( i & BMCR_FULL_DUPLEX ) {			printf(" FD");#if !defined(EPIC_NOIFMEDIA)			tmp |= IFM_FDX;#else			ifp->if_flags |= IFF_LINK1;#endif		}	}	/* Init ifmedia interface */#if !defined(EPIC_NOIFMEDIA)	ifmedia_init(&sc->ifmedia,0,epic_ifmedia_change,epic_ifmedia_status);	for (i=0; i<EPIC_MTYPESNUM; i++)		ifmedia_add(&sc->ifmedia,epic_mtypes[i],0,NULL);	ifmedia_set(&sc->ifmedia, tmp);#endif	/* Attach os interface and bpf */	if_attach(ifp);	ether_ifattach(ifp);#if NBPFILTER > 0	bpfattach(&sc->sc_if.if_bpf, ifp, DLT_EN10MB,	    sizeof(struct ether_header));#endif	/* Set shutdown routine to stop DMA process */ 	shutdownhook_establish(epic_shutdown, sc);	printf("\n");}/* Simple call epic_stop() */static voidepic_shutdown(    void *sc){	epic_stop(sc);}#else /* __FreeBSD__ *//* -----------------------------FreeBSD------------------------------------- */static const char* epic_freebsd_probe __P((pcici_t, pcidi_t));static void epic_freebsd_attach __P((pcici_t, int));static void epic_shutdown __P((int, void *));/* Global variables */static u_long epic_pci_count;static struct pci_device txdevice = { 	"tx",	epic_freebsd_probe,	epic_freebsd_attach,	&epic_pci_count,	NULL };/* Append this driver to pci drivers list */DATA_SET ( pcidevice_set, txdevice );/* Synopsis: Check if device id corresponds with SMC83C170 id.  */static const char*epic_freebsd_probe(    pcici_t config_id,    pcidi_t device_id){	if( PCI_VENDORID(device_id) != SMC_VENDORID )		return NULL;	if( PCI_CHIPID(device_id) == CHIPID_83C170 )		return "SMC 83c170";	return NULL;}/* * Do FreeBSD-specific attach routine, like map registers, alloc softc * structure and etc. */static voidepic_freebsd_attach(    pcici_t config_id,    int unit){	struct ifnet *ifp;	epic_softc_t *sc;#if defined(EPIC_USEIOSPACE)	u_int32_t iobase;#else	caddr_t	pmembase;#endif	int i,s,tmp;	printf("tx%d",unit);	/* Allocate memory for softc, hardware descriptors and frag lists */	sc = (epic_softc_t *) malloc( sizeof(epic_softc_t), M_DEVBUF, M_NOWAIT);	if (sc == NULL)	return;	/* Preinitialize softc structure */    	bzero(sc, sizeof(epic_softc_t));			sc->unit = unit;	/* Fill ifnet structure */	ifp = &sc->sc_if;	ifp->if_unit = unit;	ifp->if_name = "tx";	ifp->if_softc = sc;	ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST;	ifp->if_ioctl = epic_ifioctl;	ifp->if_start = epic_ifstart;	ifp->if_watchdog = epic_ifwatchdog;	ifp->if_init = (if_init_f_t*)epic_init;	ifp->if_timer = 0;	ifp->if_output = ether_output;	ifp->if_snd.ifq_maxlen = TX_RING_SIZE;	/* Get iobase or membase */#if defined(EPIC_USEIOSPACE)	if (!pci_map_port(config_id, PCI_CBIO,(u_short *) &(sc->iobase))) {		printf(": cannot map port\n");		free(sc, M_DEVBUF);		return;	}#else	if (!pci_map_mem(config_id, PCI_CBMA,(vm_offset_t *) &(sc->csr),(vm_offset_t *) &pmembase)) {		printf(": cannot map memory\n"); 		free(sc, M_DEVBUF);		return;	}#endif	if( epic_common_attach(sc) ) return;	/* Display ethernet address ,... */	printf(": address %02x:%02x:%02x:%02x:%02x:%02x,",		sc->sc_macaddr[0],sc->sc_macaddr[1],sc->sc_macaddr[2],		sc->sc_macaddr[3],sc->sc_macaddr[4],sc->sc_macaddr[5]);	/* board type and ... */	printf(" type ");	for(i=0x2c;i<0x32;i++) {		tmp = epic_read_eeprom( sc, i );		if( ' ' == (u_int8_t)tmp ) break;		printf("%c",(u_int8_t)tmp);		tmp >>= 8;		if( ' ' == (u_int8_t)tmp ) break;		printf("%c",(u_int8_t)tmp);	}	/* Read current media config and display it too */	i = PHY_READ_2( sc, DP83840_BMCR );#if !defined(EPIC_NOIFMEDIA)	tmp = IFM_ETHER;#endif	if( i & BMCR_AUTONEGOTIATION ){		printf(", Auto-Neg ");		/* To avoid bug in QS6612 read LPAR enstead of BMSR */		i = PHY_READ_2( sc, DP83840_LPAR );		if( i & (ANAR_100_TX|ANAR_100_TX_FD) ) printf("100Mbps ");		else printf("10Mbps ");		if( i & (ANAR_10_FD|ANAR_100_TX_FD) ) printf("FD");#if !defined(EPIC_NOIFMEDIA)		tmp |= IFM_AUTO;#endif	} else {#if defined(EPIC_NOIFMEDIA)		ifp->if_flags |= IFF_LINK0;#endif		if( i & BMCR_100MBPS ) {			printf(", 100Mbps ");#if !defined(EPIC_NOIFMEDIA)			tmp |= IFM_100_TX;

⌨️ 快捷键说明

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