📄 sl_lepus_gmac.c
字号:
//if (total_len > GMAC_MAX_ETH_FRAME_SIZE || !sg_len || !sg_list->buf) if (total_len > GMAC_MAX_ETH_FRAME_SIZE) { // too long isPtr->tx_dropped++; //eth_drv_tx_done(sc,key,-EINVAL); return; } // Select TX Queue tx_qid = 0; swtxq = &tp->swtxq[tx_qid]; // cyg_drv_mutex_lock((cyg_drv_mutex_t *)tp->tx_mutex); // if (wptr + 1) == (rptr), then cannot send rwptr.bits32 = readl(swtxq->rwptr_reg); // if (RWPTR_ADVANCE_ONE(rwptr.bits.wptr, swtxq->total_desc_num) == rwptr.bits.rptr) // check finished desc or empty BD // cannot check by read ptr of RW PTR register, // because the HW complete to send but the SW may NOT handle it if (rwptr.bits.wptr >= rwptr.bits.rptr) free_desc = swtxq->total_desc_num - rwptr.bits.wptr - 1 + rwptr.bits.rptr; else free_desc = rwptr.bits.rptr - rwptr.bits.wptr - 1; if (!free_desc) { //cyg_drv_mutex_unlock((cyg_drv_mutex_t *)tp->tx_mutex); isPtr->tx_dropped++; //eth_drv_tx_done(sc,key,-EINVAL); printk("Stop here due to no available descriptor!\n"); while(1); return; }#if 0 for (i=0; i<1; i++) { int wptr, rptr; wptr = rwptr.bits.wptr; rptr = rwptr.bits.rptr; if (wptr == rptr) break; wptr = RWPTR_ADVANCE_ONE(wptr, swtxq->total_desc_num); if (wptr == rptr) { //cyg_drv_mutex_unlock((cyg_drv_mutex_t *)tp->tx_mutex); isPtr->tx_dropped++; //eth_drv_tx_done(sc,key,-EINVAL); while(1); return; } }#endif curr_desc = (GMAC_TXDESC_T *)swtxq->desc_base + rwptr.bits.wptr; //hal_cache_consistent_sync(curr_desc, sizeof(GMAC_TXDESC_T), PCI_DMA_FROMDEVICE);/* #if (GMAC_DEBUG==1) // if curr_desc->word2.buf_adr !=0 means that the ISR does NOT handle it // if (curr_desc->word2.buf_adr) if (swtxq->tx_skb[rwptr.bits.wptr]) { printk("Error! TX descriptor's buffer is not freed!\n"); dev_kfree_skb(swtxq->tx_skb[rwptr.bits.wptr]); swtxq->tx_skb[rwptr.bits.wptr] = NULL; }#endif*/ // called by eCOS Ethernet I/O //skb = (struct sk_buff *)dev_alloc_skb(total_len); //if (!skb) //{ // isPtr->tx_dropped++; // goto send_end; //} //tx_buf_adr = skb->data; //skb->len = total_len; //while (sg_len) //{ // memcpy(tx_buf_adr,(unsigned char*)sg_list->buf,sg_list->len); // tx_buf_adr += sg_list->len; // ++sg_list; // --sg_len; //} if (mac_dump_txpkt) { printf("\nGMAC %d TxQid = %d Tx (Size = %d):\n", tp->port_id, tx_qid, total_len); dm_byte((u32)bufp, (total_len > 64) ? 64 : total_len); } swtxq->total_sent++; //swtxq->tx_skb[rwptr.bits.wptr] = skb; /* set TX descriptor */ /* copy packet to descriptor buffer address */ curr_desc->word0.bits32 = 0; curr_desc->word0.bits.buffer_size = total_len; /* total frame byte count */ curr_desc->word1.bits32 = 0; curr_desc->word1.bits.udp_chksum = 1;//skb->hw_udp_chksum; curr_desc->word1.bits.tcp_chksum = 1;//skb->hw_tcp_chksum; curr_desc->word1.bits.ip_chksum = 1;//skb->hw_ip_chksum; curr_desc->word1.bits.ipv6_enable = 1;//skb->ipv6_enable; curr_desc->word1.bits.mtu_enable = 0;//skb->mtu_enable; curr_desc->word1.bits.byte_count = total_len; //if(curr_desc->word2.buf_adr==NULL) //{ memcpy((unsigned char *)(txbuf_ptr[rwptr.bits.wptr]), bufp, total_len); curr_desc->word2.buf_adr = (unsigned int)txbuf_ptr[rwptr.bits.wptr]; //skb->data; //} curr_desc->word3.bits32 = 0; curr_desc->word3.bits.sof_eof = 3; curr_desc->word3.bits.eofie = 1; curr_desc->word3.bits.mtu_size = 1500;//(skb->mtu_size) ? skb->mtu_size : 1500; swtxq->tx_curr_desc = curr_desc; //hal_cache_consistent_sync(skb->data, total_len, PCI_DMA_TODEVICE); //hal_cache_consistent_sync(curr_desc, sizeof(GMAC_TXDESC_T), PCI_DMA_TODEVICE); // Share Pin issue //HAL_LOCK_SHARE_PIN(); SET_WPTR(swtxq->rwptr_reg, RWPTR_ADVANCE_ONE(rwptr.bits.wptr, swtxq->total_desc_num)); //HAL_UNLOCK_SHARE_PIN(); send_end: //cyg_drv_mutex_unlock((cyg_drv_mutex_t *)tp->tx_mutex); //eth_drv_tx_done(sc, key, 0);; }//static int __init gmac_init_module(void)int toe_gmac_sl2312_init(void){ int i; TOE_INFO_T *toe; unsigned long data,val; mac_dump_rxpkt = 0; mac_dump_txpkt = 0; if (!gmac_initialized) { gmac_initialized = 1; if(SPI_get_identifier()) { gmac_num = 1; SPI_default(); } else gmac_num = 0; #ifdef LEPUS_ASIC /* set GMAC global register */ val = REG32(SL2312_GLOBAL_BASE+0x10); val = val | 0x005f0000; REG32(SL2312_GLOBAL_BASE+0x10)=val; if(gmac_num) REG32(SL2312_GLOBAL_BASE+0x1c)=0x5787a7f0; else REG32(SL2312_GLOBAL_BASE+0x1c)=0xa7f0a7f0; REG32(SL2312_GLOBAL_BASE+0x20)=0x77777777; REG32(SL2312_GLOBAL_BASE+0x24)=0x77777777; REG32(SL2312_GLOBAL_BASE+0x2c)=0x09200030; //if(gmac_num) { val = readl(SL2312_GLOBAL_BASE+0x04); if((val&(1<<20))==0){ // GMAC1 enable val = readl(SL2312_GLOBAL_BASE+0x30); val = (val & 0xe7ffffff) | 0x08000000; writel(val,SL2312_GLOBAL_BASE+0x30); } }#endif // init private data toe = (TOE_INFO_T *)&toe_private_data; memset((void *)toe, 0, sizeof(TOE_INFO_T)); if(gmac_num) { //printf("gmac_num : %x\n",gmac_num); toe->gmac.base_addr = TOE_GMAC1_BASE; //TOE_GMAC0_BASE; toe->gmac.dma_base_addr = TOE_GMAC1_DMA_BASE;//TOE_GMAC0_DMA_BASE; toe->gmac.auto_nego_cfg = 1;//cfg_get_mac_auto_nego(0);#ifdef LEPUS_ASIC toe->gmac.speed_cfg = GMAC_SPEED_1000; toe->gmac.phy_mode = GMAC_PHY_RGMII_1000;//GMAC_PHY_MII;#else toe->gmac.speed_cfg = GMAC_SPEED_100; toe->gmac.phy_mode = GMAC_PHY_RGMII_100;//GMAC_PHY_MII;#endif toe->gmac.full_duplex_cfg = 1; //toe->gmac.phy_mode = GMAC_PHY_RGMII_1000;//GMAC_PHY_RGMII_100;//GMAC_PHY_MII; toe->gmac.port_id = GMAC_PORT1;//GMAC_PORT0; toe->gmac.phy_id = 1;//0; toe->gmac.phy_addr = 2;//0x11; toe->gmac.irq = SL2312_INTERRUPT_GMAC1;//SL2312_INTERRUPT_GMAC0; memcpy(toe->gmac.mac_addr1, sys_get_mac_addr(1), ETHER_ADDR_LEN); // check GMAC 0/1 existed on not // for (i=0; i<gmac_num; i++) // { gmac_write_reg(toe->gmac.base_addr, GMAC_STA_ADD2, 0x55aa55aa, 0xffffffff); data = gmac_read_reg(toe->gmac.base_addr, GMAC_STA_ADD2); if (data == 0x55aa55aa) toe->gmac.existed = GMAC_EXISTED_FLAG; // } } else { toe->gmac.base_addr = TOE_GMAC0_BASE; //TOE_GMAC0_BASE; toe->gmac.dma_base_addr = TOE_GMAC0_DMA_BASE;//TOE_GMAC0_DMA_BASE; toe->gmac.auto_nego_cfg = 1;//cfg_get_mac_auto_nego(0);#ifdef LEPUS_ASIC toe->gmac.speed_cfg = GMAC_SPEED_1000; toe->gmac.phy_mode = GMAC_PHY_RGMII_1000;//GMAC_PHY_MII;#else toe->gmac.speed_cfg = GMAC_SPEED_100; toe->gmac.phy_mode = GMAC_PHY_RGMII_100;//GMAC_PHY_MII;#endif toe->gmac.full_duplex_cfg = 1; toe->gmac.port_id = GMAC_PORT0;//GMAC_PORT0; toe->gmac.phy_id = 0;//0; toe->gmac.phy_addr = 0x1;//1;//0x11; toe->gmac.irq = SL2312_INTERRUPT_GMAC0;//SL2312_INTERRUPT_GMAC0; memcpy(toe->gmac.mac_addr1, sys_get_mac_addr(0), ETHER_ADDR_LEN); // check GMAC 0/1 existed on not // for (i=0; i<GMAC_NUM; i++) // { gmac_write_reg(toe->gmac.base_addr, GMAC_STA_ADD2, 0x55aa55aa, 0xffffffff); data = gmac_read_reg(toe->gmac.base_addr, GMAC_STA_ADD2); if (data == 0x55aa55aa) toe->gmac.existed = GMAC_EXISTED_FLAG; // } } //FLAG_SWITCH = 0; toe_gmac_sw_reset(); toe_init_free_queue(); toe_init_swtx_queue(); //toe_init_hwtx_queue(); toe_init_default_queue(); //toe_init_toe_queue(); //toe_init_class_queue(); //toe_init_interrupt_queue(); //toe_init_interrupt_config(); // Write GLOBAL_QUEUE_THRESHOLD_REG // TBD if (toe->gmac.existed) toe_init_gmac(&toe->gmac); } //printf("toe->gmac.port_id : %x\n",toe->gmac.port_id); return TRUE;} /*----------------------------------------------------------------------* toe_init_gmac*----------------------------------------------------------------------*/bool toe_init_gmac(GMAC_INFO_T *tp){ TOE_INFO_T *toe; struct ether_drv_stats *isPtr = (struct ether_drv_stats *)&tp->ifStatics; if (!gmac_initialized) return TRUE; //tp->ndt = (void *)tab; //tp->sc = sc; //tp->flow_control_enable = 1; tp->pre_phy_status = LINK_DOWN; tp->full_duplex_status = tp->full_duplex_cfg; tp->speed_status = tp->speed_status; //cyg_drv_mutex_init((cyg_drv_mutex_t *)&tx_mutex[tp->port_id]); //tp->tx_mutex = (void *)&tx_mutex[tp->port_id]; /* set PHY register to start autonegition process */ gmac_set_phy_status(tp); //tp->flow_control_enable = 1; /* GMAC initialization */ if ( toe_gmac_init_chip(tp) ) { printk ("GMAC %d init fail\n", tp->port_id); } /* allocates tx/rx descriptor and buffer memory */ /* enable tx/rx register */ toe_gmac_enable_tx_rx(); /* clear statistic counter */ toe_gmac_clear_counter(tp); memset((void *)&tp->ifStatics, 0, sizeof(struct ether_drv_stats)); isPtr->duplex = 3; isPtr->speed = 100000000; isPtr->rx_resource = gmac_num ? TOE_DEFAULT_Q1_DESC_NUM : TOE_DEFAULT_Q0_DESC_NUM; isPtr->tx_queue_len = tp->swtxq[0].total_desc_num; strcpy(isPtr->description, LEPUS_DRIVER_NAME); strcpy(isPtr->snmp_chipset, DRV_NAME); /* ----------------------------------------------------------- Enable GMAC interrupt & disable loopback Notes: GMACx init routine (for eCOS) or open routine (for Linux) enable the interrupt bits only which are selected for him. --------------------------------------------------------------*/ toe = (TOE_INFO_T *)&toe_private_data; // Enable Interrupt Bits if (tp->port_id == 0) { tp->intr0_enabled = tp->intr0_selected = ~toe->intr0_select.bits32; tp->intr1_enabled = tp->intr1_selected = ~toe->intr1_select.bits32; tp->intr2_enabled = tp->intr2_selected = ~toe->intr2_select.bits32; tp->intr3_enabled = tp->intr3_selected = ~toe->intr3_select.bits32; tp->intr4_enabled = tp->intr4_selected = ~toe->intr4_select.bits32; } else { tp->intr0_enabled = tp->intr0_selected = toe->intr0_select.bits32; tp->intr1_enabled = tp->intr1_selected = toe->intr1_select.bits32; tp->intr2_enabled = tp->intr2_selected = toe->intr2_select.bits32; tp->intr3_enabled = tp->intr3_selected = toe->intr3_select.bits32; tp->intr4_enabled = tp->intr4_selected = toe->intr4_select.bits32; } // enable only selected bits gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_0_REG, tp->intr0_enabled, tp->intr0_selected); gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_1_REG, tp->intr1_enabled, tp->intr1_selected); gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_2_REG, tp->intr2_enabled, tp->intr2_selected); gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_3_REG, tp->intr3_enabled, tp->intr3_selected); gmac_write_reg(TOE_GLOBAL_BASE, GLOBAL_INTERRUPT_ENABLE_4_REG, tp->intr4_enabled, tp->intr4_selected); // Level Trigger, Actiev HIGH //hal_interrupt_configure(tp->irq, 1, 1); //cyg_drv_interrupt_create(tp->irq, // 0, // (unsigned int)sc, // toe_gmac_isr, // eth_drv_dsr, // &intr_handle[tp->port_id], // &intr_object[tp->port_id]); //cyg_drv_interrupt_attach(intr_handle[tp->port_id]); /* start DMA process */ if (tp->existed) { toe_gmac_hw_start(tp); //toe_gmac_enable_interrupt(tp->irq); // eth_drv_init(sc, tp->mac_addr1); } tp->flow_control_enable = 1; return TRUE;} #endif // LEPUS_FPGA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -