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

📄 if_gt.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: if_gt.c,v 1.8 2003/03/24 13:24:18 pefo Exp $ *//* * Copyright (c) 2001 Allegro Networks (www.allegronetworks.com) * Copyright (c) 2002 Opsycon AB. * * 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. * */#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 <autoconf.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/miivar.h>#include <dev/pci/pcivar.h>#include <dev/pci/pcireg.h>#include <dev/pci/pcidevs.h>#include <dev/ic/if_gt.h>extern int _pciverbose;/* Prototypes */static int gt_match 		(struct device *, void *, void *);void gt_attach 			(struct device *, struct device *, void *);static void abort 		(struct gt_softc *, u_int32_t);static void reset_tx 		(struct gt_softc *);static void reset_rx 		(struct gt_softc *);static int gt_ioctl 		(struct ifnet *, u_long, caddr_t);static void gt_init 		(void *);static void gt_start 		(struct ifnet *);static void gt_stop 		(struct gt_softc *, int);static void gt_watchdog 	(struct ifnet *);static int gt_add_rfabuf 	(struct gt_softc *, struct mbuf **);static int gt_intr 		(void *);static int gt_rx		(struct gt_softc *, u_int32_t);static void read_mib_counters 	(struct gt_softc *);int gt_miibus_readreg(void *, int, int);int gt_miibus_writereg(void *, int, int, int);void tgt_netstats 		(int);int initAddressTable 	(int, int, int, int);int addAddressTableEntry (int, uint, uint, uint, uint);/* Compensate for lack of a generic ether_ioctl() */static int      gt_ether_ioctl (struct ifnet *, u_int32_t, caddr_t);#define ether_ioctl     gt_ether_ioctlstruct cfattach gt_ca = {                                  sizeof(struct gt_softc), gt_match, gt_attach };                                                                                                              struct cfdriver gt_cd = {                                  NULL, "gt", DV_IFNET                           };/* Define ethernet MAC address */extern char hwethadr[]; #define RFA_ALIGNMENT_FUDGE	2/* * Check for Galileo gt642[46]0 */static intgt_match(parent, match, aux)    struct device *parent;    void *match, *aux;{	return(1);		/* I suppose soooo... */}/* Attach the interface */void gt_attach (parent, self, aux)    struct device *parent, *self;    void *aux;{    struct gt_softc *sc = (struct gt_softc *)self;    struct confargs *cf = aux;    struct ifnet *ifp;    u_int32_t macH, macL;    int i, isrmii;    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;    printf(": address %s\n", ether_sprintf(sc->arpcom.ac_enaddr));    sc->port_offset = sc->sc_dev.dv_unit * ETH_IO_SIZE;    sc->phy_addr = cf->ca_baseaddr;    ifp->if_softc = sc;    ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;    ifp->if_ioctl = gt_ioctl;    ifp->if_start = gt_start;     ifp->if_watchdog = gt_watchdog;   /*     *  Allocate Tx and Rx descriptor rings    */    sc->tx_ring = (TX_DESC *)(malloc(sizeof(TX_DESC) * TX_RING_SIZE,                              M_DEVBUF, M_NOWAIT));    sc->rx_ring = (RX_DESC *)(malloc(sizeof(RX_DESC) * RX_RING_SIZE,                              M_DEVBUF, M_NOWAIT));    sc->tx_m = (struct mbuf **)(malloc(sizeof(struct mbuf *) * TX_RING_SIZE,                              M_DEVBUF, M_NOWAIT));    sc->rx_m = (struct mbuf **)(malloc(sizeof(struct mbuf *) * RX_RING_SIZE,                              M_DEVBUF, M_NOWAIT));    bzero(sc->tx_m, sizeof(struct m_buf *) * TX_RING_SIZE);    bzero(sc->rx_m, sizeof(struct m_buf *) * RX_RING_SIZE);    /*      *  Allocate Tx data buffers     */    sc->tx_bp = malloc(TX_BUF_SZ*TX_RING_SIZE, M_DEVBUF, M_NOWAIT);   /*     *  Initialize hash table    */    sc->hash_mode = 0;    initAddressTable(sc->sc_dev.dv_unit,0,1,0);         macH = (sc->arpcom.ac_enaddr[0] << 8) | (sc->arpcom.ac_enaddr[1]);    macL = (sc->arpcom.ac_enaddr[5] << 0) | (sc->arpcom.ac_enaddr[4] << 8) |           (sc->arpcom.ac_enaddr[3] << 16)| (sc->arpcom.ac_enaddr[2] << 24);    addAddressTableEntry(sc->sc_dev.dv_unit,macH,macL,1,0);   /*     *  Reset port    */    gt_stop(sc,0);    gt_miibus_writereg(sc, sc->phy_addr, 0, 0x8000);    i = 100;    while (i && gt_miibus_readreg(sc, sc->phy_addr, 0) & 0x8000) {	delay(100);	i--;    }   /*     *  Initialize Tx and Rx descriptors    */    reset_tx(sc);    reset_rx(sc);    GTETH_WRITE(sc, ETH0_INTERRUPT_MASK_REG, 0x0);    /*      *  Setup eth0 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.     */    isrmii = gt_miibus_readreg(sc, sc->phy_addr, 2) << 16;    isrmii |= gt_miibus_readreg(sc, sc->phy_addr, 3) & 0xfff0;    switch(isrmii) {    case 0x1378e0:	/* Intel LTX972A */	isrmii = 0;	break;    default:	isrmii = pcxrRMIIen;	break;    }    GTETH_WRITE(sc, ETH0_PORT_CONFIG_EXT_REG,				isrmii | pcxrFCTL | pcxrFCTLen | pcxrFLP);    read_mib_counters(sc);    GTETH_WRITE(sc, ETH0_PORT_CONFIG_EXT_REG,				isrmii | pcxrFCTL | pcxrFCTLen | pcxrFLP |		                pcxrPRIOrxOverride | pcxrMIBclrMode);    /*      *  Big endian DMA, burst size 8 64bit words, frame boundary interrupts     */#if BYTE_ORDER == LITTLE_ENDIAN    GTETH_WRITE(sc, ETH0_SDMA_CONFIG_REG,				sdcrBLMR | sdcrBLMT |    			        (0xf<<sdcrRCBit) | sdcrRIFB | (3<<sdcrBSZBit));#else    GTETH_WRITE(sc, ETH0_SDMA_CONFIG_REG,    			        (0xf<<sdcrRCBit) | sdcrRIFB | (3<<sdcrBSZBit));#endif    /*      *  Start eth0 Rx DMA      */    GTETH_WRITE(sc, ETH0_SDMA_COMMAND_REG, sdcmrERD);        /*      *  Enable eth0 with 1/2K hash size     */    GTETH_WRITE(sc, ETH0_PORT_CONFIG_REG, pcrEN | pcrHS);    /*      *  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);}/* * Start packet transmission on the interface. */static voidgt_start(ifp)    struct ifnet *ifp;{    struct gt_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 & txOwn) {	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.         */        nextTx = sc->tx_next_in;	total_len = 0;	p = (char *)PA_TO_VA(sc->tx_ring[nextTx].buff_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_res = total_len << 16;	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 =			txOwn | txFirst | txLast | txPad | txEI | txGenCRC;	CACHESYNC(&sc->tx_ring[nextTx], sizeof(TX_DESC), SYNC_W);        /*          *  Send the packet out the low priority queue         */        if(!(GTETH_READ(sc, ETH0_PORT_STATUS_REG) & psrTxInProg)) {            GTETH_WRITE(sc, ETH0_SDMA_COMMAND_REG, sdcmrERD | sdcmrTXDL);	}#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++;}/* *  Stop the interface */voidgt_stop(struct gt_softc *sc, int drain){    /*     *   Disable port     */    abort(sc, sdcmrAR | sdcmrAT);    GTETH_WRITE(sc, ETH0_PORT_CONFIG_REG, 0);}static voidabort(struct gt_softc *sc, u_int32_t abort_bits){    /* Return if neither Rx or Tx abort bits are set */    if (!(abort_bits & (sdcmrAR | sdcmrAT)))	return;    /* Make sure only the Rx and Tx abort bits are set */    abort_bits &= (sdcmrAR | sdcmrAT);    /* Abort any Rx and Tx DMA immediately */    GTETH_WRITE(sc, ETH0_SDMA_COMMAND_REG, abort_bits);}/*  * Watchdog timeout handler.  This routine is called when  * transmission has started on the interface and no * interrupt was received before the timeout. */voidgt_watchdog(ifp)    struct ifnet *ifp;{    struct gt_softc *sc = ifp->if_softc;    log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);    ifp->if_oerrors++;    //gt_init(sc);}static voidreset_tx(struct gt_softc *sc){    int i;    abort(sc, sdcmrAT);    for (i=0; i < TX_RING_SIZE; i++) {	sc->tx_ring[i].cmdstat  = 0; /* CPU owns */	sc->tx_ring[i].byte_cnt_res = 0;	sc->tx_ring[i].buff_ptr = (u_int32_t)VA_TO_PA(sc->tx_bp+i*TX_BUF_SZ);	sc->tx_ring[i].next     = (u_int32_t)VA_TO_PA(sc->tx_ring + (i+1));    }    /* Wrap the ring. */    sc->tx_ring[i-1].next = VA_TO_PA(sc->tx_ring);    CACHESYNC(sc->tx_ring, TX_RING_SIZE * sizeof(TX_DESC), SYNC_W);    /* setup only the lowest priority TxCDP reg */    GTETH_WRITE(sc, ETH0_CURRENT_TX_DESC_PTR0, VA_TO_PA(sc->tx_ring));    GTETH_WRITE(sc, ETH0_CURRENT_TX_DESC_PTR1, 0);    /* Initialize Tx indeces and packet counter */    sc->tx_next_in = 0;    sc->tx_next_out = 0;    sc->tx_count = 0;}static voidreset_rx(struct gt_softc *sc){	struct mbuf *m;	int i;	abort(sc, sdcmrAR);    	/* Scan and release allocated mbufs */	for (i=0; i<RX_RING_SIZE; i++) {		if(sc->rx_m[i] != NULL) {			m_free(sc->rx_m[i]);		}	}	for (i=0; i < RX_RING_SIZE; i++) {		RX_DESC *rx_desc;		m = NULL;		if(gt_add_rfabuf(sc, &m) < 0) {			printf("%s: malloc failed\n", sc->sc_dev.dv_xname);			break;		}		sc->rx_m[i] = m;		rx_desc = &sc->rx_ring[i];		rx_desc->next     = VA_TO_PA((sc->rx_ring + (i+1)));		rx_desc->buff_ptr = VA_TO_PA(m->m_data);		rx_desc->byte_sz_cnt = RX_BUF_SZ << 16;		/*		 *  Give ownership to device, set first and last,		 * enable interrupt		 */		sc->rx_ring[i].cmdstat = (rxFirst | rxLast | rxOwn | rxEI);    }    /* Wrap the ring */    sc->rx_ring[i-1].next = VA_TO_PA(sc->rx_ring);    CACHESYNC(sc->rx_ring, RX_RING_SIZE * sizeof(RX_DESC), SYNC_W);    /* Setup only the lowest priority RxFDP and RxCDP regs */    for (i=0; i<4; i++) {	if (i == 0) {	    GTETH_WRITE(sc, ETH0_FIRST_RX_DESC_PTR0, VA_TO_PA(sc->rx_ring));	    GTETH_WRITE(sc, ETH0_CURRENT_RX_DESC_PTR0, VA_TO_PA(sc->rx_ring));	} else {	    GTETH_WRITE(sc, ETH0_FIRST_RX_DESC_PTR0 + i*4, 0);	    GTETH_WRITE(sc, ETH0_CURRENT_RX_DESC_PTR0 + i*4, 0);	}

⌨️ 快捷键说明

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