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

📄 if_gtx.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: if_gtx.c,v 1.10 2003/08/30 14:58:28 pefo Exp $ *//* * Copyright (c) 2001 Allegro Networks (www.allegronetworks.com) * Copyright (c) 2002, 2003 Opsycon AB (www.opsycon.se) * * 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 Allegro Networks Inc. *      This product includes software developed by Opsycon AB. * 4. The name of the author may not be used to endorse or promote products *    derived from this software without 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. * *//* *  This driver is based on the if_gt.c code. It was ported over to *  the GT64xx0 Gigabit ethernet and made simple and functional for *  PMON2000. It is not optimized for performance etc but tailored *  to be small and efficient for the task it is designed for, booting. */#include "bpfilter.h"#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/syslog.h>#include <net/if.h>#include <net/if_dl.h>#include <net/if_media.h>#include <net/if_types.h>#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 0#if NBPFILTER > 0#include <net/bpf.h>#include <net/bpfdesc.h>#endif#endif#include <sys/ioctl.h>#include <sys/errno.h>#include <sys/device.h>#include <netinet/if_ether.h>#include <vm/vm.h>#include <machine/cpu.h>#include <machine/bus.h>#include <machine/intr.h>#include <dev/mii/mii.h>#include <dev/pci/pcivar.h>#include <dev/pci/pcireg.h>#include <dev/pci/pcidevs.h>#include <dev/ic/if_gtx.h>extern int _pciverbose;/* Prototypes */static int gtx_match(struct device *, void *, void *);void gtx_attach(struct device *, struct device *, void *);static void reset_tx(struct gtx_softc *);static void reset_rx(struct gtx_softc *);static int gtx_ioctl(struct ifnet *, u_long, caddr_t);static void gtx_init(void *);static void gtx_start(struct ifnet *);static void gtx_reset(struct gtx_softc *, int);static void gtx_watchdog(struct ifnet *);static int gtx_add_rfabuf(struct gtx_softc *, struct mbuf **);static int gtx_intr(void *);static int gtx_rx(struct gtx_softc *, u_int32_t, u_int32_t);void gtx_read_mib_counters(struct gtx_softc *);void tgt_netstats(int);int initAddressTable(int, int, int, int);int addAddressTableEntry(int, uint, uint, uint, uint);/* Quick mechanism to allow allocations in the On-Chip SRAM */static char *ocram = (char *)OC_SRAM_BASE;#define ocramalloc(what, size) \	what = (typeof(what))ocram; bzero(ocram, size * sizeof(* what)); \	ocram += ALIGN(size * sizeof(* what)); /* Compensate for lack of a generic ether_ioctl() */static int      gtx_ether_ioctl (struct ifnet *, u_int32_t, caddr_t);#define ether_ioctl     gtx_ether_ioctl/* MII access functions */static void mii_write (int phyaddr, int reg, int value);static int  mii_read (int phyaddr, int reg);struct cfattach gtx_ca = {                                  sizeof(struct gtx_softc), gtx_match, gtx_attach };                                                                                                              struct cfdriver gtx_cd = {                                  NULL, "gtx", DV_IFNET                           };/* Define ethernet MAC address */extern char hwethadr[]; char phytab[] = {#ifdef DISCO_II_PHY0	DISCO_II_PHY0,#else	8,#endif#ifdef DISCO_II_PHY1	DISCO_II_PHY1,#else	9,#endif#ifdef DISCO_II_PHY2	DISCO_II_PHY2,#else	10#endif	};#define RFA_ALIGNMENT_FUDGE	2	/* RX buffer magic offset *//* * Check for Galileo gt643[46]0 */static intgtx_match(parent, match, aux)	struct device *parent;	void *match, *aux;{	return(1);		/* I suppose soooo... */}/* Attach the interface */void gtx_attach (parent, self, aux)	struct device *parent, *self;	void *aux;{	struct gtx_softc *sc = (struct gtx_softc *)self;	struct ifnet *ifp;	unsigned int tmp, regtmp;	int iftype;	ifp = &sc->arpcom.ac_if;	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);	bcopy(hwethadr, sc->arpcom.ac_enaddr, sizeof(sc->arpcom.ac_enaddr));	sc->arpcom.ac_enaddr[5] += sc->sc_dev.dv_unit;	sc->sc_port = sc->sc_dev.dv_unit;	printf(": adr %s ", ether_sprintf(sc->arpcom.ac_enaddr));	iftype = GT_READ(ETH_PORT_STATUS_REG(sc->sc_port));	printf(": %s", (iftype & 1) ? "10bit" : "GMII/MII");	/* Set PHY address for port */	sc->phy_addr = phytab[sc->sc_port]; 	regtmp = GT_READ(ETH_PHY_ADDR_REG);	regtmp &= ~(0x1f << (5 * sc->sc_port));	regtmp |= sc->phy_addr << (5 * sc->sc_port);	GT_WRITE(ETH_PHY_ADDR_REG, regtmp);	ifp->if_softc = sc;	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;	ifp->if_ioctl = gtx_ioctl;	ifp->if_start = gtx_start; 	ifp->if_watchdog = gtx_watchdog;	/* 	 *  Allocate Tx and Rx descriptor rings. These are located in the	 *  DiscoveryII on-chip SRAM.	 */	ocramalloc(sc->tx_ring, TX_RING_SIZE);	ocramalloc(sc->rx_ring, RX_RING_SIZE);	/* 	 *  Allocate Tx data buffers	 */#if defined JAGUAR_ATX	ocramalloc(sc->tx_buff, TX_RING_SIZE * TX_BUF_SZ);	ocramalloc(sc->rx_buff, RX_RING_SIZE * RX_BUF_SZ);#else	sc->tx_buff = (u_int8_t *)(malloc(TX_BUF_SZ*TX_RING_SIZE,                               M_DEVBUF, M_NOWAIT));#endif	/* Reset and disable port */	gtx_reset(sc, 0);	/* Initialize Tx and Rx descriptors */	reset_tx(sc);	reset_rx(sc);	/* 	 *  Setup eth Port Config Extend Reg, clear the MIB registers.	 *  When done set MIB counters clear mode to 'no effect' so each	 *  read doesn't zero the register.	 */	GT_WRITE(ETH_PORT_CONFIG_EXTEND_REG(sc->sc_port), PCXR_DEFAULT_SETTING);	GT_WRITE(ETH_PORT_CONFIG_REG(sc->sc_port), PCR_DEFAULT_SETTING);	GT_WRITE(ETH_PORT_SERIAL_CONTROL_REG(sc->sc_port), PSCR_DEFAULT_SETTING);	GT_WRITE(ETH_PORT_SERIAL_CONTROL_REG(sc->sc_port),		PSCR_DEFAULT_SETTING | PSCR_PORTEN);	/* Set port ethernet address and init unicast address table. */	tmp = (sc->arpcom.ac_enaddr[4] << 8) | sc->arpcom.ac_enaddr[5];	GT_WRITE(ETH_MAC_ADDR_LOW(sc->sc_port), tmp);	tmp = (sc->arpcom.ac_enaddr[0] << 24) | (sc->arpcom.ac_enaddr[1] << 16);	tmp |= (sc->arpcom.ac_enaddr[2] << 8) | sc->arpcom.ac_enaddr[3];	GT_WRITE(ETH_MAC_ADDR_HIGH(sc->sc_port), tmp);	tmp = sc->arpcom.ac_enaddr[5] & 0x0c;	regtmp = GT_READ(ETH_DA_FILTER_UNICAST_TABLE_BASE(sc->sc_port) + tmp);	regtmp |= 1 << ((sc->arpcom.ac_enaddr[5] & 0x03) * 8);	tmp = sc->arpcom.ac_enaddr[5] & 0x0c;	GT_WRITE(ETH_DA_FILTER_UNICAST_TABLE_BASE(sc->sc_port) + tmp, regtmp);	/* "Endian" DMA, burst size 8 64bit words, frame boundary interrupts */#if BYTE_ORDER == LITTLE_ENDIAN	GT_WRITE(ETH_SDMA_CONFIG_REG(sc->sc_port),		SDCR_DEFAULT_SETTING | SDCR_BLMRT);#else	GT_WRITE(ETH_SDMA_CONFIG_REG(sc->sc_port), SDCR_DEFAULT_SETTING);#endif	GT_WRITE(ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(sc->sc_port), 0x3fffffff);	GT_WRITE(ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(sc->sc_port), 0x3ffffcff);	GT_WRITE(ETH_MAXIMUM_TRANSMIT_UNIT(sc->sc_port), 0);	/* Start eth0 Rx DMA, only one queue */	GT_WRITE(ETH_RECEIVE_QUEUE_COMMAND_REG(sc->sc_port), 0x01);	if (0) {	/* reset the PHYs so that autoneg works out the initial state */	mii_write(phytab[sc->sc_port], MII_BMCR, BMCR_RESET);	while (mii_read(phytab[sc->sc_port], MII_BMCR) & BMCR_RESET);	}#ifdef OCELOT_C	/* set up LED indication */	mii_write(phytab[sc->sc_port], 0x18, 0x4108);#endif	/* Set up interrupt callback */	tgt_poll_register(IPL_NET, gtx_intr, sc);	/* Attach the interface */	if_attach(ifp);	/*	 * Let the system queue as many packets as we have available 	 * Tx descriptors	 */	ifp->if_snd.ifq_maxlen = TX_RING_SIZE - 1;	ether_ifattach(ifp);	printf("\n");}/* * Start packet transmission on the interface. */static voidgtx_start(ifp)    struct ifnet *ifp;{    struct gtx_softc *sc = ifp->if_softc;    u_int16_t total_len;    char *p;   /*    * Process all mbufs ready for transmit or until all available    * transmit buffers are full.    */    CACHESYNC(&sc->tx_ring[sc->tx_next_in], sizeof(TX_DESC), SYNC_R);    if(sc->tx_ring[sc->tx_next_in].cmdstat & TX_O) {	return;		/* No buffers */    }    while (ifp->if_snd.ifq_head != NULL) {        struct mbuf *m, *mb_head;        u_int32_t nextTx;        /*         *  Grab a packet to transmit.         */        IF_DEQUEUE(&ifp->if_snd, mb_head);        /*         *  Go through each of the mbufs in the chain and copy the data         *  collecting fragments to the transmit descriptors data buffer.	 *	 *  XXX For speed this should use multiple TX descs instead.         */        nextTx = sc->tx_next_in;	total_len = 0;	p = sc->tx_ring[nextTx].vbuff_ptr;        for (m = mb_head; m != NULL; m = m->m_next) {            bcopy((char *)(mtod(m, vm_offset_t)), p, m->m_len);            total_len += m->m_len;	    p += m->m_len;        }        sc->tx_ring[nextTx].byte_cnt = total_len;	CACHESYNC((void *)(p - total_len), total_len, SYNC_W);        sc->tx_next_in = (nextTx + 1) % TX_RING_SIZE;	/*          *  Free the mbuf chain         */        m_freem(mb_head);        sc->tx_ring[nextTx].cmdstat =			TX_O | TX_F | TX_L | TX_P | TX_EI | TX_GC;	CACHESYNC(&sc->tx_ring[nextTx], sizeof(TX_DESC), SYNC_W);	/* Send the packet out using queue 0 */	GT_WRITE(ETH_TRANSMIT_QUEUE_COMMAND_REG(sc->sc_port), 1);#if 0        /*         *  Set a 5 second timer just in case we don't hear  	 *  from the card again.	 */        ifp->if_timer = 300;#endif    } /* end while */    sc->tx_queued++;}/* *  Reset the interface, clear all tables. */voidgtx_reset(struct gtx_softc *sc, int drain){	u_int32_t status;	u_int32_t das, dao;	int index;	status = GT_READ(ETH_TRANSMIT_QUEUE_COMMAND_REG(sc->sc_port)) << 8;	if (status & 0xff00) {		GT_WRITE(ETH_TRANSMIT_QUEUE_COMMAND_REG(sc->sc_port), status);	}	status = GT_READ(ETH_RECEIVE_QUEUE_COMMAND_REG(sc->sc_port)) << 8;	if (status & 0xff00) {		GT_WRITE(ETH_RECEIVE_QUEUE_COMMAND_REG(sc->sc_port), status);	}	while((GT_READ(ETH_TRANSMIT_QUEUE_COMMAND_REG(sc->sc_port)) & 0xff) &&		(GT_READ(ETH_RECEIVE_QUEUE_COMMAND_REG(sc->sc_port)) & 0xff))		;	if (drain)		return;	status = GT_READ(ETH_PORT_SERIAL_CONTROL_REG(sc->sc_port));	status &= ~PSCR_PORTEN;	GT_WRITE(ETH_PORT_SERIAL_CONTROL_REG(sc->sc_port), status);	/*	 * Reset and clear the Mac tables. It is mandatory for	 * code caling this code non-drain to call reinit.	 */	das = ETH_DA_FILTER_UNICAST_TABLE_BASE(sc->sc_port);	GT_WRITE(das + 0x0, 0);	GT_WRITE(das + 0x4, 0);	GT_WRITE(das + 0x8, 0);	GT_WRITE(das + 0xc, 0);	das = ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(sc->sc_port);	dao = ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(sc->sc_port);	for (index = 0; index < 256; index += 4) {		GT_WRITE(das + index, 0);		GT_WRITE(dao + index, 0);	}}/*  * Watchdog timeout handler.  This routine is called when  * transmission has started on the interface and no * interrupt was received before the timeout. */voidgtx_watchdog(ifp)	struct ifnet *ifp;{	struct gtx_softc *sc = ifp->if_softc;	log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);	ifp->if_oerrors++;    //gtx_init(sc);}static voidreset_tx(struct gtx_softc *sc){	int i;	for (i = 0; i < TX_RING_SIZE; i++) {		TX_DESC *txp;		txp = &sc->tx_ring[i];		txp->cmdstat  = 0; /* CPU owns */		txp->byte_cnt = 0;		txp->next     = (u_int32_t)OCRAM_TO_PA(sc->tx_ring + (i+1));#if defined JAGUAR_ATX		txp->vbuff_ptr = (char *)(sc->tx_buff + (i * TX_BUF_SZ));		txp->buff_ptr = (u_int32_t)OCRAM_TO_PA(txp->vbuff_ptr);#else

⌨️ 快捷键说明

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