📄 sl_lepus_gmac.c
字号:
GMAC1_TXPERR_INT_BIT | GMAC1_RXPERR_INT_BIT | GMAC1_SWTQ15_FIN_INT_BIT | GMAC1_SWTQ14_FIN_INT_BIT | GMAC1_SWTQ13_FIN_INT_BIT | GMAC1_SWTQ12_FIN_INT_BIT | GMAC1_SWTQ11_FIN_INT_BIT | GMAC1_SWTQ10_FIN_INT_BIT | GMAC1_SWTQ15_EOF_INT_BIT | GMAC1_SWTQ14_EOF_INT_BIT | GMAC1_SWTQ13_EOF_INT_BIT | GMAC1_SWTQ12_EOF_INT_BIT | GMAC1_SWTQ11_EOF_INT_BIT | GMAC1_SWTQ10_EOF_INT_BIT; toe->intr1_select.bits32 = DEFAULT_Q1_INT_BIT; if (!toe->gmac.existed) { for (i=0; i<TOE_CLASS_QUEUE_NUM; i++) toe->intr1_select.bits32 |= CLASS_RX_INT_BIT(i); toe->intr1_select.bits32 |= TOE_IQ0_INT_BIT | TOE_IQ1_INT_BIT | TOE_IQ2_INT_BIT | TOE_IQ3_INT_BIT | TOE_IQ0_FULL_INT_BIT | TOE_IQ1_FULL_INT_BIT | TOE_IQ2_FULL_INT_BIT | TOE_IQ3_FULL_INT_BIT; } toe->intr2_select.bits32 = 0; toe->intr3_select.bits32 = 0; if (!toe->gmac.existed) { toe->intr2_select.bits32 = 0xffffffff; toe->intr3_select.bits32 = 0xffffffff; } toe->intr4_select.bits32 = GMAC1_RESERVED_INT_BIT | GMAC1_MIB_INT_BIT | GMAC1_RX_PAUSE_ON_INT_BIT | GMAC1_TX_PAUSE_ON_INT_BIT | GMAC1_RX_PAUSE_OFF_INT_BIT | GMAC1_TX_PAUSE_OFF_INT_BIT | GMAC1_RX_OVERRUN_INT_BIT | GMAC1_STATUS_CHANGE_INT_BIT; if (!toe->gmac.existed) { for (i=0; i<TOE_CLASS_QUEUE_NUM; i++) toe->intr4_select.bits32 |= CLASS_RX_FULL_INT_BIT(i); } toe->intr0_device.bits32 = toe->intr0_select.bits32; toe->intr1_device.bits32 = toe->intr1_select.bits32; toe->intr2_device.bits32 = toe->intr2_select.bits32; toe->intr3_device.bits32 = toe->intr3_select.bits32; toe->intr4_device.bits32 = toe->intr4_select.bits32; // clear all status bits writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_0_REG); writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_1_REG); writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_2_REG); writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_3_REG); writel(0xffffffff, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_STATUS_4_REG); // set select registers writel(toe->intr0_device.bits32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_0_REG); writel(toe->intr1_device.bits32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_1_REG); writel(toe->intr2_device.bits32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_2_REG); writel(toe->intr3_device.bits32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_3_REG); writel(toe->intr4_device.bits32, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_SELECT_4_REG); // disable all interrupt writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_0_REG); writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_1_REG); writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_2_REG); writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_3_REG); writel(0, TOE_GLOBAL_BASE + GLOBAL_INTERRUPT_ENABLE_4_REG);}/*----------------------------------------------------------------------* mac_stop_txdma*----------------------------------------------------------------------*/void mac_stop_txdma(GMAC_INFO_T *tp){ GMAC_DMA_CTRL_T dma_ctrl, dma_ctrl_mask; GMAC_TXDMA_FIRST_DESC_T txdma_busy; // wait idle txdma_busy.bits32 = gmac_read_reg(tp->dma_base_addr, GMAC_DMA_TX_FIRST_DESC_REG); while (txdma_busy.bits.td_busy){}; /* program dma control register */ dma_ctrl.bits32 = 0; dma_ctrl.bits.rd_enable = 0; dma_ctrl.bits.td_enable = 0; dma_ctrl_mask.bits32 = 0; dma_ctrl_mask.bits.rd_enable = 1; dma_ctrl_mask.bits.td_enable = 1; gmac_write_reg(tp->dma_base_addr, GMAC_DMA_CTRL_REG, dma_ctrl.bits32, dma_ctrl_mask.bits32);}/*----------------------------------------------------------------------* toe_gmac_handle_default_rxq* (1) Get rx Buffer for default Rx queue* (2) notify or call upper-routine to handle it* (3) get a new buffer and insert it into SW free queue* (4) Note: The SW free queue Read-Write Pointer should be locked when accessing*----------------------------------------------------------------------*/// static inline void toe_gmac_handle_default_rxq(GMAC_INFO_T *tp)static void toe_gmac_handle_default_rxq(GMAC_INFO_T *tp){ TOE_INFO_T *toe; GMAC_RXDESC_T *curr_desc, *fq_desc; //struct sk_buff *skb; DMA_RWPTR_T rwptr, fq_rwptr; unsigned int pkt_size; unsigned int desc_count,counter; unsigned int good_frame, rx_status, chksum_status; struct ether_drv_stats *isPtr = (struct ether_drv_stats *)&tp->ifStatics; //register CYG_INTERRUPT_STATE oldints; // toe_gmac_disable_interrupt(tp->irq); isPtr->rx_deliver++; rwptr.bits32 = readl(&tp->default_qhdr->word1); if (rwptr.bits.rptr != tp->rx_rwptr.bits.rptr) { mac_stop_txdma(tp); printf("Default Queue HW RD ptr (0x%x) != SW RD Ptr (0x%x)\n", rwptr.bits32, tp->rx_rwptr.bits.rptr); while(1); } counter =0; toe = (TOE_INFO_T *)&toe_private_data; while (rwptr.bits.rptr != rwptr.bits.wptr&& counter++<16) { curr_desc = (GMAC_RXDESC_T *)tp->default_desc_base + rwptr.bits.rptr; //hal_cache_consistent_sync(curr_desc, sizeof(GMAC_RXDESC_T), PCI_DMA_FROMDEVICE); tp->default_q_cnt++; tp->rx_curr_desc = (unsigned int)curr_desc; rx_status = curr_desc->word0.bits.status; chksum_status = curr_desc->word0.bits.chksum_status; tp->rx_status_cnt[rx_status]++; tp->rx_chksum_cnt[chksum_status]++; good_frame = 1; if (curr_desc->word0.bits.derr || curr_desc->word0.bits.perr || rx_status ) // || (chksum_status & 0x4)) { good_frame = 0; isPtr->rx_crc_errors++; // all errors for UI dump if (curr_desc->word0.bits.derr) printk("%s::derr (GMAC-%d)!!!\n", __func__, tp->port_id); if (curr_desc->word0.bits.perr) printk("%s::perr (GMAC-%d)!!!\n", __func__, tp->port_id); if (rx_status) { //if (rx_status == 4 || rx_status == 7) // isPtr->rx_crc_errors++; //if (rx_status == 6 || rx_status == 7) // isPtr->rx_align_errors++; printk("%s::Status=%d (GMAC-%d)!!!\n", __func__, rx_status, tp->port_id); mac_status_error = 1; } if (chksum_status) printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id); if (mac_dump_rxpkt) { printf("Checksum Status=%d\n", chksum_status); printf("GMAC %d Rx %d Bytes:\n", tp->port_id, pkt_size); dm_byte((u32)curr_desc->word2.buf_adr, (pkt_size > 256) ? 256 : pkt_size); } //if ((unsigned long)skb>0x10000000 || skb->tag != NET_BUF_TAG) //{ // //mac_stop_txdma((struct eth_drv_sc *)tp->sc); // dbg_printf(("Illegal NETBUF header!\n")); // while(1); //} // curr_desc->word2.buf_adr = 0; } if (good_frame) { if (curr_desc->word0.bits.drop) printk("%s::Drop (GMAC-%d)!!!\n", __func__, tp->port_id); //if (chksum_status) // printk("%s::Checksum Status=%d (GMAC-%d)!!!\n", __func__, chksum_status, tp->port_id); /* get frame information from the first descriptor of the frame */ pkt_size = curr_desc->word1.bits.byte_count; /*total byte count in a frame*/ desc_count = curr_desc->word0.bits.desc_count; /* get descriptor count per frame */ isPtr->rx_good++; //hal_cache_consistent_sync(curr_desc->word2.buf_adr, pkt_size, PCI_DMA_FROMDEVICE); //skb = (struct sk_buff *)(REG32(curr_desc->word2.buf_adr - SKB_RESERVE_BYTES)); //if ((unsigned long)skb>0x10000000 || skb->tag != NET_BUF_TAG) //{ // mac_stop_txdma((struct eth_drv_sc *)tp->sc); // dbg_printf(("Illegal NETBUF header!\n")); // while(1); //} // curr_desc->word2.buf_adr = 0; // skb_reserve (skb, RX_INSERT_BYTES); /* 16 byte align the IP fields. */// // skb->dev = dev;// // skb->ip_summed = CHECKSUM_UNNECESSARY;// skb_put(skb, pkt_size);// // skb->protocol = eth_type_trans(skb,dev); /* set skb protocol */// // netif_rx(skb); /* socket rx */// // dev->last_rx = jiffies;// skb->rx_port_id = tp->port_id;// skb->rx_qid = tp->port_id + TOE_GMAC0_DEFAULT_QID;// skb->sw_id = curr_desc->word1.bits.sw_id;// skb->l3_offset = curr_desc->word3.bits.l3_offset;// skb->l4_offset = curr_desc->word3.bits.l4_offset;// skb->l7_offset = curr_desc->word3.bits.l7_offset;// skb->rx_chksum_status = chksum_status;// tp->curr_rx_skb = skb; if (mac_dump_rxpkt) { //printf("Checksum Status=%d, L3:0x%x, L4:0x%x, L7:0x%x\n", // chksum_status, skb->l3_offset, skb->l4_offset, skb->l7_offset); printf("GMAC %d Rx %d Bytes:\n", tp->port_id, pkt_size); dm_byte(curr_desc->word2.buf_adr, (pkt_size > 128) ? 128 : pkt_size); } enet_input(curr_desc->word2.buf_adr+RX_INSERT_BYTES, pkt_size); goto rx_next_frame; rx_next_frame: isPtr->rx_count++; } /* release buffer to Remaining Buffer Number Register */#if 0 if (tp->flow_control_enable ==1) { gmac_write_reg(tp->base_addr, GMAC_BNCR, desc_count, 0x0000ffff); }#endif // allocate a buffer and insert to sw free queue fq_rwptr.bits32 = readl(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG); if (toe_private_data.fq_rx_rwptr.bits.wptr != fq_rwptr.bits.wptr) { mac_stop_txdma(tp); //HAL_RESTORE_INTERRUPTS(oldints); printf("Free Queue HW Write ptr (0x%x) != SW Write Ptr(0x%x)\n", fq_rwptr.bits.wptr, toe_private_data.fq_rx_rwptr.bits.wptr); while(1); } fq_desc = (GMAC_RXDESC_T *)toe->swfq_desc_base + fq_rwptr.bits.wptr; //hal_cache_consistent_sync((unsigned int)fq_desc, sizeof(GMAC_RXDESC_T), PCI_DMA_TODEVICE); // advance one for Rx default Q 0/1 rwptr.bits.rptr = RWPTR_ADVANCE_ONE(rwptr.bits.rptr, tp->default_desc_num); SET_RPTR(&tp->default_qhdr->word1, rwptr.bits.rptr); tp->rx_rwptr.bits32 = rwptr.bits32; fq_rwptr.bits.wptr = RWPTR_ADVANCE_ONE(fq_rwptr.bits.wptr, TOE_SW_FREEQ_DESC_NUM); SET_WPTR(TOE_GLOBAL_BASE + GLOBAL_SWFQ_RWPTR_REG, fq_rwptr.bits.wptr); toe_private_data.fq_rx_rwptr.bits32 = fq_rwptr.bits32; //HAL_RESTORE_INTERRUPTS(oldints); }}/*----------------------------------------------------------------------* toe_gmac_deliver*----------------------------------------------------------------------*/void toe_gmac_deliver(void){ TOE_INFO_T *toe; GMAC_INFO_T *tp; int i; toe = (TOE_INFO_T *)&toe_private_data; tp = (GMAC_INFO_T *)&toe->gmac; if ((sys_get_ticks() - gmac_poll_phy_ticks) >= (BOARD_TPS * 3)) { gmac_get_phy_status(tp); gmac_poll_phy_ticks = sys_get_ticks(); } toe_gmac_handle_default_rxq(tp); //for (i=0; i<TOE_CLASS_QUEUE_NUM; i++) // toe_gmac_handle_classq(&toe->classq[i], tp->sc); // //toe_gmac_handle_toeq(tp); // toe_gmac_enable_interrupt(tp->irq); /* release buffer to Remaining Buffer Number Register */ } /*----------------------------------------------------------------------* toe_gmac_can_send* called by eCOS Ethernet I/O* check PHY status and TX Q0* return 1: if can send, 0: cannot send*----------------------------------------------------------------------*/int toe_gmac_can_send(void){ TOE_INFO_T *toe; GMAC_INFO_T *tp; GMAC_STATUS_T status; DMA_RWPTR_T rwptr; toe = (TOE_INFO_T *)&toe_private_data; tp = (GMAC_INFO_T *)&toe->gmac; status.bits32 = gmac_read_reg(tp->base_addr, GMAC_STATUS); if (!status.bits.link) return 0; rwptr.bits32 = gmac_read_reg(tp->base_addr, GMAC_SW_TX_QUEUE0_PTR_REG); // if (wptr + 1) == (rptr), then cannot send if (RWPTR_ADVANCE_ONE(rwptr.bits.wptr, tp->swtxq[0].total_desc_num) == rwptr.bits.rptr) return 0; else return 1;}/*----------------------------------------------------------------------* toe_gmac_send* key = 0 if called by mac_send_raw_pkt()* != 0 if called by eCOS Ethernet I/O** TX Queue Selection:* For diagnostics (called by mac_send_raw_pkt), the skb->priority = * 0: SW TX Q0, 1: SW TX Q1, 2: SW TX Q2, 3: SW TX Q3* 4: SW TX Q4, others: SW TX Q5* For eCOS Ethernet I/O, always use SW TX Q0*----------------------------------------------------------------------*///static void toe_gmac_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,// int total_len, unsigned long key)void toe_gmac_send(char *bufp, int total_len) { TOE_INFO_T *toe; GMAC_INFO_T *tp; DMA_RWPTR_T rwptr; unsigned char *tx_buf_adr; //struct sk_buff *skb; GMAC_TXDESC_T *curr_desc; unsigned int tx_qid; GMAC_SWTXQ_T *swtxq; int i, free_desc; struct ether_drv_stats *isPtr = (struct ether_drv_stats *)&tp->ifStatics; toe = (TOE_INFO_T *)&toe_private_data; tp = (GMAC_INFO_T *)&toe->gmac; //#ifdef _BYPASS_SEND// eth_drv_tx_done(sc, key, 0);// // return;//#endif #if 0 if (!eth_drv_initialized) { eth_drv_tx_done(sc,key,-EINVAL); return; }#endif#ifdef _DEBUG_TCP_PERFORMANCE net_dump_clock(4);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -