📄 tsi108_eth.c
字号:
printf ("%s link is up", dev->name); phy_spec_status = read_phy (ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG); if (phy_spec_status & SPEC_STAT_RESOLVED) { switch (phy_speed) { case LINK_SPEED_1000: printf (", 1000 Mbps"); break; case LINK_SPEED_100: printf (", 100 Mbps"); break; case LINK_SPEED_10: printf (", 10 Mbps"); break; } if (phy_duplex == LINK_DUPLEX_FULL) printf (", Full duplex"); else printf (", Half duplex"); } printf ("\n");#endif dump_phy_regs (TBI_ADDR); if (speed) *speed = phy_speed; if (duplex) *duplex = phy_duplex; return 1;}/* * External interface * * register the tsi108 ethernet controllers with the multi-ethernet system */int tsi108_eth_initialize (bd_t * bis){ struct eth_device *dev; int index; for (index = 0; index < CONFIG_TSI108_ETH_NUM_PORTS; index++) { dev = (struct eth_device *)malloc(sizeof(struct eth_device)); sprintf (dev->name, "TSI108_eth%d", index); dev->iobase = ETH_BASE + (index * ETH_PORT_OFFSET); dev->priv = (void *)(phy_address[index]); dev->init = tsi108_eth_probe; dev->halt = tsi108_eth_halt; dev->send = tsi108_eth_send; dev->recv = tsi108_eth_recv; eth_register(dev); } return index;}/* * probe for and initialize a single ethernet interface */static int tsi108_eth_probe (struct eth_device *dev, bd_t * bis){ unsigned long base; unsigned long value; int index; struct dma_descriptor *tx_descr; struct dma_descriptor *rx_descr; int speed; int duplex; base = dev->iobase; reg_PORT_CONTROL(base) = PORT_CONTROL_STE | PORT_CONTROL_BPT; /* Bring DMA/FIFO out of reset. */ reg_TX_CONFIG(base) = 0x00000000; reg_RX_CONFIG(base) = 0x00000000; reg_TX_THRESHOLDS(base) = (192 << 16) | 192; reg_RX_THRESHOLDS(base) = (192 << 16) | 112; /* Bring MAC out of reset. */ reg_MAC_CONFIG_1(base) = 0x00000000; /* DMA MAC configuration. */ reg_MAC_CONFIG_1(base) = MAC_CONFIG_1_RX_ENABLE | MAC_CONFIG_1_TX_ENABLE; reg_MII_MGMT_CONFIG(base) = MII_MGMT_CONFIG_NO_PREAMBLE; reg_MAXIMUM_FRAME_LENGTH(base) = RX_BUFFER_SIZE; /* Note: Early tsi108 manual did not have correct byte order * for the station address.*/ reg_STATION_ADDRESS_1(base) = (dev->enetaddr[5] << 24) | (dev->enetaddr[4] << 16) | (dev->enetaddr[3] << 8) | (dev->enetaddr[2] << 0); reg_STATION_ADDRESS_2(base) = (dev->enetaddr[1] << 24) | (dev->enetaddr[0] << 16); if (marvell_88e_phy_config(dev, &speed, &duplex) == 0) return 0; value = MAC_CONFIG_2_PREAMBLE_LENGTH(7) | MAC_CONFIG_2_PAD_CRC | MAC_CONFIG_2_CRC_ENABLE; if (speed == LINK_SPEED_1000) value |= MAC_CONFIG_2_INTERFACE_MODE(INTERFACE_MODE_BYTE); else { value |= MAC_CONFIG_2_INTERFACE_MODE(INTERFACE_MODE_NIBBLE); reg_PORT_CONTROL(base) |= PORT_CONTROL_SPD; } if (duplex == LINK_DUPLEX_FULL) { value |= MAC_CONFIG_2_FULL_DUPLEX; reg_PORT_CONTROL(base) &= ~PORT_CONTROL_BPT; } else reg_PORT_CONTROL(base) |= PORT_CONTROL_BPT; reg_MAC_CONFIG_2(base) = value; reg_RX_CONFIG(base) = RX_CONFIG_SE; reg_RX_QUEUE_0_CONFIG(base) = OCN_PORT_MEMORY; reg_RX_QUEUE_0_BUF_CONFIG(base) = OCN_PORT_MEMORY; /* initialize the RX DMA descriptors */ rx_descr = &rx_descr_array[0]; rx_descr_current = rx_descr; for (index = 0; index < NUM_RX_DESC; index++) { /* make sure the receive buffers are not in cache */ invalidate_dcache_range((unsigned long)NetRxPackets[index], (unsigned long)NetRxPackets[index] + RX_BUFFER_SIZE); rx_descr->start_addr0 = cpu_to_le32((vuint32) NetRxPackets[index]); rx_descr->start_addr1 = 0; rx_descr->next_descr_addr0 = cpu_to_le32((vuint32) (rx_descr + 1)); rx_descr->next_descr_addr1 = 0; rx_descr->vlan_byte_count = 0; rx_descr->config_status = cpu_to_le32((RX_BUFFER_SIZE << 16) | DMA_DESCR_RX_OWNER); rx_descr++; } rx_descr--; rx_descr->next_descr_addr0 = 0; rx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); /* Push the descriptors to RAM so the ethernet DMA can see them */ invalidate_dcache_range((unsigned long)rx_descr_array, (unsigned long)rx_descr_array + sizeof(rx_descr_array)); /* enable RX queue */ reg_RX_CONTROL(base) = TX_CONTROL_GO | 0x01; reg_RX_QUEUE_0_PTR_LOW(base) = (u32) rx_descr_current; /* enable receive DMA */ reg_RX_QUEUE_0_PTR_HIGH(base) = RX_QUEUE_0_PTR_HIGH_VALID; reg_TX_QUEUE_0_CONFIG(base) = OCN_PORT_MEMORY; reg_TX_QUEUE_0_BUF_CONFIG(base) = OCN_PORT_MEMORY; /* initialize the TX DMA descriptor */ tx_descr = &tx_descriptor; tx_descr->start_addr0 = 0; tx_descr->start_addr1 = 0; tx_descr->next_descr_addr0 = 0; tx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); tx_descr->vlan_byte_count = 0; tx_descr->config_status = cpu_to_le32(DMA_DESCR_TX_OK | DMA_DESCR_TX_SOF | DMA_DESCR_TX_EOF); /* enable TX queue */ reg_TX_CONTROL(base) = TX_CONTROL_GO | 0x01; return 1;}/* * send a packet */static int tsi108_eth_send (struct eth_device *dev, volatile void *packet, int length){ unsigned long base; int timeout; struct dma_descriptor *tx_descr; unsigned long status; base = dev->iobase; tx_descr = &tx_descriptor; /* Wait until the last packet has been transmitted. */ timeout = 0; do { /* make sure we see the changes made by the DMA engine */ invalidate_dcache_range((unsigned long)tx_descr, (unsigned long)tx_descr + sizeof(struct dma_descriptor)); if (timeout != 0) udelay (15); if (++timeout > 10000) { tx_diag_regs(base); debug_lev(1, "ERROR: timeout waiting for last transmit packet to be sent\n"); return 0; } } while (tx_descr->config_status & cpu_to_le32(DMA_DESCR_TX_OWNER)); status = le32_to_cpu(tx_descr->config_status); if ((status & DMA_DESCR_TX_OK) == 0) {#ifdef TX_PRINT_ERRORS printf ("TX packet error: 0x%08x\n %s%s%s%s\n", status, status & DMA_DESCR_TX_OK ? "tx error, " : "", status & DMA_DESCR_TX_RETRY_LIMIT ? "retry limit reached, " : "", status & DMA_DESCR_TX_UNDERRUN ? "underrun, " : "", status & DMA_DESCR_TX_LATE_COLLISION ? "late collision, " : "");#endif } debug_lev (9, "sending packet %d\n", length); tx_descr->start_addr0 = cpu_to_le32((vuint32) packet); tx_descr->start_addr1 = 0; tx_descr->next_descr_addr0 = 0; tx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); tx_descr->vlan_byte_count = cpu_to_le32(length); tx_descr->config_status = cpu_to_le32(DMA_DESCR_TX_OWNER | DMA_DESCR_TX_CRC | DMA_DESCR_TX_PAD | DMA_DESCR_TX_SOF | DMA_DESCR_TX_EOF); invalidate_dcache_range((unsigned long)tx_descr, (unsigned long)tx_descr + sizeof(struct dma_descriptor)); invalidate_dcache_range((unsigned long)packet, (unsigned long)packet + length); reg_TX_QUEUE_0_PTR_LOW(base) = (u32) tx_descr; reg_TX_QUEUE_0_PTR_HIGH(base) = TX_QUEUE_0_PTR_HIGH_VALID; return length;}/* * Check for received packets and send them up the protocal stack */static int tsi108_eth_recv (struct eth_device *dev){ struct dma_descriptor *rx_descr; unsigned long base; int length = 0; unsigned long status; volatile uchar *buffer; base = dev->iobase; /* make sure we see the changes made by the DMA engine */ invalidate_dcache_range ((unsigned long)rx_descr_array, (unsigned long)rx_descr_array + sizeof(rx_descr_array)); /* process all of the received packets */ rx_descr = rx_descr_current; while ((rx_descr->config_status & cpu_to_le32(DMA_DESCR_RX_OWNER)) == 0) { /* check for error */ status = le32_to_cpu(rx_descr->config_status); if (status & DMA_DESCR_RX_BAD_FRAME) {#ifdef RX_PRINT_ERRORS printf ("RX packet error: 0x%08x\n %s%s%s%s%s%s\n", status, status & DMA_DESCR_RX_FRAME_IS_TYPE ? "too big, " : "", status & DMA_DESCR_RX_SHORT_FRAME ? "too short, " : "", status & DMA_DESCR_RX_BAD_FRAME ? "bad frame, " : "", status & DMA_DESCR_RX_OVERRUN ? "overrun, " : "", status & DMA_DESCR_RX_MAX_FRAME_LEN ? "max length, " : "", status & DMA_DESCR_RX_CRC_ERROR ? "CRC error, " : "");#endif } else { length = le32_to_cpu(rx_descr->vlan_byte_count) & 0xFFFF; /*** process packet ***/ buffer = (volatile uchar *)(le32_to_cpu (rx_descr->start_addr0)); NetReceive (buffer, length); invalidate_dcache_range ((unsigned long)buffer, (unsigned long)buffer + RX_BUFFER_SIZE); } /* Give this buffer back to the DMA engine */ rx_descr->vlan_byte_count = 0; rx_descr->config_status = cpu_to_le32 ((RX_BUFFER_SIZE << 16) | DMA_DESCR_RX_OWNER); /* move descriptor pointer forward */ rx_descr = (struct dma_descriptor *)(le32_to_cpu (rx_descr->next_descr_addr0)); if (rx_descr == 0) rx_descr = &rx_descr_array[0]; } /* remember where we are for next time */ rx_descr_current = rx_descr; /* If the DMA engine has reached the end of the queue * start over at the begining */ if (reg_RX_EXTENDED_STATUS(base) & RX_EXTENDED_STATUS_EOQ_0) { reg_RX_EXTENDED_STATUS(base) = RX_EXTENDED_STATUS_EOQ_0; reg_RX_QUEUE_0_PTR_LOW(base) = (u32) & rx_descr_array[0]; reg_RX_QUEUE_0_PTR_HIGH(base) = RX_QUEUE_0_PTR_HIGH_VALID; } return length;}/* * disable an ethernet interface */static void tsi108_eth_halt (struct eth_device *dev){ unsigned long base; base = dev->iobase; /* Put DMA/FIFO into reset state. */ reg_TX_CONFIG(base) = TX_CONFIG_RST; reg_RX_CONFIG(base) = RX_CONFIG_RST; /* Put MAC into reset state. */ reg_MAC_CONFIG_1(base) = MAC_CONFIG_1_SOFT_RESET;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -