📄 dev_sb1250_ethernet.c
字号:
pkt->next = NULL; pkt->length = pktsize; if (s->sbe_rxqueue == NULL) { s->sbe_rxqueue = pkt; } else { listptr = s->sbe_rxqueue; while (listptr->next) listptr = listptr->next; listptr->next = pkt; } } else { sbeth_free_pkt(s,pkt); } sbeth_fillrxring(s,chan);}/* ********************************************************************* * SBETH_INITCHAN(s) * * Initialize the Ethernet channel (program the CSRs to * get the channel set up) * * Input parameters: * s - sbeth structure * * Return value: * nothing ********************************************************************* */static void sbeth_initchan(sbeth_t *s){ sbeth_port_t port; int idx; uint64_t cfg,fifo,framecfg; /* * Bring the controller out of reset, and set the "must be one" * bits. */ SBETH_WRITECSR(s->sbe_macenable,0); /* * Set up some stuff in the control registers, but do not * enable the channel */ cfg = M_MAC_RETRY_EN | M_MAC_TX_HOLD_SOP_EN | V_MAC_TX_PAUSE_CNT_16K | V_MAC_SPEED_SEL_100MBPS | M_MAC_AP_STAT_EN | M_MAC_FAST_SYNC | M_MAC_SS_EN | 0; fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */ V_MAC_TX_RD_THRSH(8) | V_MAC_TX_RL_THRSH(4) | V_MAC_RX_PL_THRSH(4) | V_MAC_RX_RD_THRSH(4) | /* Must be '4' */ V_MAC_RX_PL_THRSH(4) | V_MAC_RX_RL_THRSH(8) | 0; framecfg = V_MAC_MIN_FRAMESZ_DEFAULT | V_MAC_MAX_FRAMESZ_DEFAULT | V_MAC_BACKOFF_SEL(1); /* * Clear out the hash address map */ port = SBETH_PORT(s->sbe_baseaddr + R_MAC_HASH_BASE); for (idx = 0; idx < MAC_HASH_COUNT; idx++) { SBETH_WRITECSR(port,0); port += sizeof(uint64_t); } /* * Clear out the exact-match table */ port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ADDR_BASE); for (idx = 0; idx < MAC_ADDR_COUNT; idx++) { SBETH_WRITECSR(port,0); port += sizeof(uint64_t); } /* * Clear out the DMA Channel mapping table registers */ port = SBETH_PORT(s->sbe_baseaddr + R_MAC_CHUP0_BASE); for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { SBETH_WRITECSR(port,0); port += sizeof(uint64_t); } port = SBETH_PORT(s->sbe_baseaddr + R_MAC_CHLO0_BASE); for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { SBETH_WRITECSR(port,0); port += sizeof(uint64_t); } if (!s->sbe_zerormon) { s->sbe_zerormon =1; SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_BYTES),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_COLLISIONS),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_LATE_COL),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_EX_COL),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_FCS_ERROR),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_ABORT),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_BAD),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_GOOD),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_RUNT),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_OVERSIZE),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_BYTES),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_MCAST),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_BCAST),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_BAD),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_GOOD),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_RUNT),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_OVERSIZE),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_FCS_ERROR),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_LENGTH_ERROR),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_CODE_ERROR),0); SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_ALIGN_ERROR),0); } /* * Configure the receive filter for no packets */ SBETH_WRITECSR(s->sbe_rxfilter,0); SBETH_WRITECSR(s->sbe_imr,0); SBETH_WRITECSR(s->sbe_framecfg,framecfg); SBETH_WRITECSR(s->sbe_fifocfg,fifo); SBETH_WRITECSR(s->sbe_maccfg,cfg);}/* ********************************************************************* * SBETH_INITCTX(s,mac) * * Initialize an Ethernet context structure - this is called * once per MAC on the 1250. * * Input parameters: * s - sbeth context structure * mac - number of this MAC (0,1,2) * ifctx - interface context (reference saved by driver) * * Return value: * 0 ********************************************************************* */static int sbeth_initctx(sbeth_t *s,unsigned long baseaddr,void *ifctx){ /* * Start with all zeroes */ memset(s,0,sizeof(sbeth_t)); /* * Identify ourselves */ s->sbe_baseaddr = baseaddr; s->sbe_ifctx = ifctx; s->sbe_minrxring = 8; /* * Set default hardware address. This is in case there is *no* environment. */ s->sbe_hwaddr[0] = 0x02; s->sbe_hwaddr[1] = 0x10; s->sbe_hwaddr[2] = 0x18; s->sbe_hwaddr[3] = (s->sbe_baseaddr >> 24) & 0xFF; s->sbe_hwaddr[4] = (s->sbe_baseaddr >> 16) & 0xFF; s->sbe_hwaddr[5] = (s->sbe_baseaddr >> 8) & 0xFF; /* * figure out the addresses of some ports */ s->sbe_macenable = SBETH_PORT(s->sbe_baseaddr + R_MAC_ENABLE); s->sbe_maccfg = SBETH_PORT(s->sbe_baseaddr + R_MAC_CFG); s->sbe_fifocfg = SBETH_PORT(s->sbe_baseaddr + R_MAC_THRSH_CFG); s->sbe_framecfg = SBETH_PORT(s->sbe_baseaddr + R_MAC_FRAMECFG); s->sbe_rxfilter = SBETH_PORT(s->sbe_baseaddr + R_MAC_ADFILTER_CFG); s->sbe_isr = SBETH_PORT(s->sbe_baseaddr + R_MAC_STATUS); s->sbe_imr = SBETH_PORT(s->sbe_baseaddr + R_MAC_INT_MASK); s->sbe_mdio = SBETH_PORT(s->sbe_baseaddr + R_MAC_MDIO); /* * Initialize the DMA channels. */ sbdma_initctx(s,&(s->sbe_txdma[0]),0,DMA_TX,SBETH_MAX_TXDESCR,sbeth_tx_callback); sbdma_initctx(s,&(s->sbe_rxdma[0]),0,DMA_RX,SBETH_MAX_RXDESCR,sbeth_rx_callback);#if (SBETH_DMA_CHANNELS == 2) sbdma_initctx(s,&(s->sbe_txdma[1]),1,DMA_TX,SBETH_MAX_TXDESCR,sbeth_tx_callback); sbdma_initctx(s,&(s->sbe_rxdma[1]),1,DMA_RX,SBETH_MAX_RXDESCR,sbeth_rx_callback);#endif /* * initialize free list */ s->sbe_freelist = NULL; s->sbe_rxqueue = NULL; s->sbe_pktpool = KMALLOC(SBETH_PKTBUF_SIZE*SBETH_PKTPOOL_SIZE, SBDMA_CACHESIZE); /* * Set values for the PHY so that when we poll the phy status * we'll notice that it has changed. */ s->sbe_phy_oldbmsr = 0xFFFFFFFF; s->sbe_phy_oldbmcr = 0xFFFFFFFF; s->sbe_phy_oldanlpar = 0xFFFFFFFF; s->sbe_phy_oldk1stsr = 0xFFFFFFFF; /* * initial state is OFF */ s->sbe_state = sbeth_state_off; return 0;}/* ********************************************************************* * SBETH_START(s) * * Start packet processing on this MAC. * * Input parameters: * s - sbeth structure * * Return value: * nothing ********************************************************************* */static void sbeth_start(sbeth_t *s){ uint64_t ctl; sbdma_initchan(s,&(s->sbe_txdma[0])); sbdma_initchan(s,&(s->sbe_rxdma[0]));#if (SBETH_DMA_CHANNELS == 2) sbdma_initchan(s,&(s->sbe_txdma[1])); sbdma_initchan(s,&(s->sbe_rxdma[1]));#endif sbeth_initchan(s); sbeth_setspeed(s,s->sbe_speed); sbeth_set_duplex(s,s->sbe_duplex,s->sbe_fc); SBETH_WRITECSR(s->sbe_rxfilter,0); ctl = SBETH_READCSR(s->sbe_macenable); ctl |= M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0 |#if (SBETH_DMA_CHANNELS == 2) M_MAC_TXDMA_EN1 | M_MAC_RXDMA_EN1 |#endif M_MAC_RX_ENABLE | M_MAC_TX_ENABLE | 0; sbeth_initfreelist(s); SBETH_WRITECSR(s->sbe_macenable,ctl); sbeth_setaddr(s,s->sbe_hwaddr);#ifdef _SB1250_PASS1_WORKAROUNDS_ /* Must set the Ethernet address to zero in pass1 */ do { sbeth_port_t port; port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ETHERNET_ADDR); SBETH_WRITECSR(port,0); } while (0);#endif sbeth_fillrxring(s,0); SBETH_WRITECSR(s->sbe_rxfilter,M_MAC_UCAST_EN | M_MAC_BCAST_EN | V_MAC_IPHDR_OFFSET(15) | /* M_MAC_ALLPKT_EN |*/ /* uncomment for promisc mode */ 0 ); s->sbe_state = sbeth_state_on;}/* ********************************************************************* * SBETH_STOP(s) * * Stop packet processing on this MAC. * * Input parameters: * s - sbeth structure * * Return value: * nothing ********************************************************************* */static void sbeth_stop(sbeth_t *s){ uint64_t ctl; int mac_mdio_genc; SBETH_WRITECSR(s->sbe_rxfilter,0); ctl = SBETH_READCSR(s->sbe_macenable); ctl &= ~(M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0 | M_MAC_RXDMA_EN1 | M_MAC_TXDMA_EN1 | M_MAC_RX_ENABLE | M_MAC_TX_ENABLE); SBETH_WRITECSR(s->sbe_macenable,ctl); /* * The genc bit on the MAC MDIO register needs to be preserved through reset. * Read the MAC MDIO register and mask out genc bit. */ mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC; ctl |= M_MAC_PORT_RESET; SBETH_WRITECSR(s->sbe_macenable,ctl); /* Write back value of genc bit */ SBETH_WRITECSR(s->sbe_mdio,mac_mdio_genc); s->sbe_state = sbeth_state_off; sbdma_reset(&(s->sbe_txdma[0])); sbdma_reset(&(s->sbe_rxdma[0]));}/* ********************************************************************* * SBETH_SETADDR(s,addr) * * Set the ethernet address for the specified MAC * * Input parameters: * s - sbeth structure * addr - Ethernet address * * Return value: * nothing ********************************************************************* */static void sbeth_setaddr(sbeth_t *s,uint8_t *addr){ sbeth_port_t port; uint64_t regval = 0; int idx; /* * Pack the bytes into the register, with the first byte transmitted * in the lowest-order 8 bits of the register. */ for (idx = 0; idx < 6; idx++) { regval |= (((uint64_t) (*addr)) << (idx*8)); addr++; } /* * Write to the port. */ port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ETHERNET_ADDR); SBETH_WRITECSR(port,regval); port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ADDR_BASE); SBETH_WRITECSR(port,regval);}/* ********************************************************************* * SBETH_SETSPEED(s,speed) * * Configure LAN speed for the specified MAC * * Input parameters: * s - sbeth structure * speed - speed to set MAC to (see sbeth_speed_t enum) * * Return value: * 1 if successful * 0 indicates invalid parameters ********************************************************************* */static int sbeth_setspeed(sbeth_t *s,sbeth_speed_t speed){ uint64_t cfg; uint64_t framecfg; /* * Read current register values */ cfg = SBETH_READCSR(s->sbe_maccfg); framecfg = SBETH_READCSR(s->sbe_framecfg); /* * Mask out the stuff we want to change */ cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL); framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH | M_MAC_SLOT_SIZE); /* * Now add in the new bits */ switch (speed) { case sbeth_speed_10: framecfg |= V_MAC_IFG_RX_10 | V_MAC_IFG_TX_10 | K_MAC_IFG_THRSH_10 | V_MAC_SLOT_SIZE_10; cfg |= V_MAC_SPEED_SEL_10MBPS; break; case sbeth_speed_100: framecfg |= V_MAC_IFG_RX_100 | V_MAC_IFG_TX_100 | V_MAC_IFG_THRSH_100 | V_MAC_SLOT_SIZE_100; cfg |= V_MAC_SPEED_SEL_100MBPS ; break; case sbeth_speed_1000:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -