📄 mv_eth.c
字号:
s = "eth1addr"; break; case 2: s = "eth2addr"; break; default: /* this should never happen */ printf ("%s: Invalid device number %d\n", __FUNCTION__, devnum); return; } temp = getenv_r (s, buf, sizeof (buf)); s = (temp > 0) ? buf : NULL;#ifdef DEBUG printf ("Setting MAC %d to %s\n", devnum, s);#endif for (x = 0; x < 6; ++x) { dev->enetaddr[x] = s ? simple_strtoul (s, &e, 16) : 0; if (s) s = (*e) ? e + 1 : e; } DP (printf ("Allocating descriptor and buffer rings\n")); ethernet_private->p_rx_desc_area_base[0] = (ETH_RX_DESC *) memalign (16, RX_DESC_ALIGNED_SIZE * MV64460_RX_QUEUE_SIZE + 1); ethernet_private->p_tx_desc_area_base[0] = (ETH_TX_DESC *) memalign (16, TX_DESC_ALIGNED_SIZE * MV64460_TX_QUEUE_SIZE + 1); ethernet_private->p_rx_buffer_base[0] = (char *) memalign (16, MV64460_RX_QUEUE_SIZE * MV64460_TX_BUFFER_SIZE + 1); ethernet_private->p_tx_buffer_base[0] = (char *) memalign (16, MV64460_RX_QUEUE_SIZE * MV64460_TX_BUFFER_SIZE + 1);#ifdef DEBUG_MV_ETH /* DEBUG OUTPUT prints adresses of globals */ print_globals (dev);#endif eth_register (dev); miiphy_register(dev->name, mv_miiphy_read, mv_miiphy_write); } DP (printf ("%s: exit\n", __FUNCTION__));}/********************************************************************** * mv64460_eth_open * * This function is called when openning the network device. The function * should initialize all the hardware, initialize cyclic Rx/Tx * descriptors chain and buffers and allocate an IRQ to the network * device. * * Input : a pointer to the network device structure * / / ronen - changed the output to match net/eth.c needs * Output : nonzero of success , zero if fails. * under construction **********************************************************************/int mv64460_eth_open (struct eth_device *dev){ return (mv64460_eth_real_open (dev));}/* Helper function for mv64460_eth_open */static int mv64460_eth_real_open (struct eth_device *dev){ unsigned int queue; ETH_PORT_INFO *ethernet_private; struct mv64460_eth_priv *port_private; unsigned int port_num; u32 port_status; ushort reg_short; int speed; int duplex; int i; int reg; ethernet_private = (ETH_PORT_INFO *) dev->priv; /* ronen - when we update the MAC env params we only update dev->enetaddr see ./net/eth.c eth_set_enetaddr() */ memcpy (ethernet_private->port_mac_addr, dev->enetaddr, 6); port_private = (struct mv64460_eth_priv *) ethernet_private->port_private; port_num = port_private->port_num; /* Stop RX Queues */ MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (port_num), 0x0000ff00); /* Clear the ethernet port interrupts */ MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_REG (port_num), 0); MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_EXTEND_REG (port_num), 0); /* Unmask RX buffer and TX end interrupt */ MV_REG_WRITE (MV64460_ETH_INTERRUPT_MASK_REG (port_num), INT_CAUSE_UNMASK_ALL); /* Unmask phy and link status changes interrupts */ MV_REG_WRITE (MV64460_ETH_INTERRUPT_EXTEND_MASK_REG (port_num), INT_CAUSE_UNMASK_ALL_EXT); /* Set phy address of the port */ ethernet_private->port_phy_addr = 0x1 + (port_num << 1); reg = ethernet_private->port_phy_addr; /* Activate the DMA channels etc */ eth_port_init (ethernet_private); /* "Allocate" setup TX rings */ for (queue = 0; queue < MV64460_TX_QUEUE_NUM; queue++) { unsigned int size; port_private->tx_ring_size[queue] = MV64460_TX_QUEUE_SIZE; size = (port_private->tx_ring_size[queue] * TX_DESC_ALIGNED_SIZE); /*size = no of DESCs times DESC-size */ ethernet_private->tx_desc_area_size[queue] = size; /* first clear desc area completely */ memset ((void *) ethernet_private->p_tx_desc_area_base[queue], 0, ethernet_private->tx_desc_area_size[queue]); /* initialize tx desc ring with low level driver */ if (ether_init_tx_desc_ring (ethernet_private, ETH_Q0, port_private->tx_ring_size[queue], MV64460_TX_BUFFER_SIZE /* Each Buffer is 1600 Byte */ , (unsigned int) ethernet_private-> p_tx_desc_area_base[queue], (unsigned int) ethernet_private-> p_tx_buffer_base[queue]) == false) printf ("### Error initializing TX Ring\n"); } /* "Allocate" setup RX rings */ for (queue = 0; queue < MV64460_RX_QUEUE_NUM; queue++) { unsigned int size; /* Meantime RX Ring are fixed - but must be configurable by user */ port_private->rx_ring_size[queue] = MV64460_RX_QUEUE_SIZE; size = (port_private->rx_ring_size[queue] * RX_DESC_ALIGNED_SIZE); ethernet_private->rx_desc_area_size[queue] = size; /* first clear desc area completely */ memset ((void *) ethernet_private->p_rx_desc_area_base[queue], 0, ethernet_private->rx_desc_area_size[queue]); if ((ether_init_rx_desc_ring (ethernet_private, ETH_Q0, port_private->rx_ring_size[queue], MV64460_RX_BUFFER_SIZE /* Each Buffer is 1600 Byte */ , (unsigned int) ethernet_private-> p_rx_desc_area_base[queue], (unsigned int) ethernet_private-> p_rx_buffer_base[queue])) == false) printf ("### Error initializing RX Ring\n"); } eth_port_start (ethernet_private); /* Set maximum receive buffer to 9700 bytes */ MV_REG_WRITE (MV64460_ETH_PORT_SERIAL_CONTROL_REG (port_num), (0x5 << 17) | (MV_REG_READ (MV64460_ETH_PORT_SERIAL_CONTROL_REG (port_num)) & 0xfff1ffff)); /* * Set ethernet MTU for leaky bucket mechanism to 0 - this will * disable the leaky bucket mechanism . */ MV_REG_WRITE (MV64460_ETH_MAXIMUM_TRANSMIT_UNIT (port_num), 0); port_status = MV_REG_READ (MV64460_ETH_PORT_STATUS_REG (port_num));#if defined(CONFIG_PHY_RESET) /* * Reset the phy, only if its the first time through * otherwise, just check the speeds & feeds */ if (port_private->first_init == 0) { port_private->first_init = 1; ethernet_phy_reset (port_num); /* Start/Restart autonegotiation */ phy_setup_aneg (dev->name, reg); udelay (1000); }#endif /* defined(CONFIG_PHY_RESET) */ miiphy_read (dev->name, reg, PHY_BMSR, ®_short); /* * Wait if PHY is capable of autonegotiation and autonegotiation is not complete */ if ((reg_short & PHY_BMSR_AUTN_ABLE) && !(reg_short & PHY_BMSR_AUTN_COMP)) { puts ("Waiting for PHY auto negotiation to complete"); i = 0; while (!(reg_short & PHY_BMSR_AUTN_COMP)) { /* * Timeout reached ? */ if (i > PHY_AUTONEGOTIATE_TIMEOUT) { puts (" TIMEOUT !\n"); break; } if ((i++ % 1000) == 0) { putc ('.'); } udelay (1000); /* 1 ms */ miiphy_read (dev->name, reg, PHY_BMSR, ®_short); } puts (" done\n"); udelay (500000); /* another 500 ms (results in faster booting) */ } speed = miiphy_speed (dev->name, reg); duplex = miiphy_duplex (dev->name, reg); printf ("ENET Speed is %d Mbps - %s duplex connection\n", (int) speed, (duplex == HALF) ? "HALF" : "FULL"); port_private->eth_running = MAGIC_ETH_RUNNING; return 1;}static int mv64460_eth_free_tx_rings (struct eth_device *dev){ unsigned int queue; ETH_PORT_INFO *ethernet_private; struct mv64460_eth_priv *port_private; unsigned int port_num; volatile ETH_TX_DESC *p_tx_curr_desc; ethernet_private = (ETH_PORT_INFO *) dev->priv; port_private = (struct mv64460_eth_priv *) ethernet_private->port_private; port_num = port_private->port_num; /* Stop Tx Queues */ MV_REG_WRITE (MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG (port_num), 0x0000ff00); /* Free TX rings */ DP (printf ("Clearing previously allocated TX queues... ")); for (queue = 0; queue < MV64460_TX_QUEUE_NUM; queue++) { /* Free on TX rings */ for (p_tx_curr_desc = ethernet_private->p_tx_desc_area_base[queue]; ((unsigned int) p_tx_curr_desc <= (unsigned int) ethernet_private->p_tx_desc_area_base[queue] + ethernet_private->tx_desc_area_size[queue]); p_tx_curr_desc = (ETH_TX_DESC *) ((unsigned int) p_tx_curr_desc + TX_DESC_ALIGNED_SIZE)) { /* this is inside for loop */ if (p_tx_curr_desc->return_info != 0) { p_tx_curr_desc->return_info = 0; DP (printf ("freed\n")); } } DP (printf ("Done\n")); } return 0;}static int mv64460_eth_free_rx_rings (struct eth_device *dev){ unsigned int queue; ETH_PORT_INFO *ethernet_private; struct mv64460_eth_priv *port_private; unsigned int port_num; volatile ETH_RX_DESC *p_rx_curr_desc; ethernet_private = (ETH_PORT_INFO *) dev->priv; port_private = (struct mv64460_eth_priv *) ethernet_private->port_private; port_num = port_private->port_num; /* Stop RX Queues */ MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (port_num), 0x0000ff00); /* Free RX rings */ DP (printf ("Clearing previously allocated RX queues... ")); for (queue = 0; queue < MV64460_RX_QUEUE_NUM; queue++) { /* Free preallocated skb's on RX rings */ for (p_rx_curr_desc = ethernet_private->p_rx_desc_area_base[queue]; (((unsigned int) p_rx_curr_desc < ((unsigned int) ethernet_private-> p_rx_desc_area_base[queue] + ethernet_private->rx_desc_area_size[queue]))); p_rx_curr_desc = (ETH_RX_DESC *) ((unsigned int) p_rx_curr_desc + RX_DESC_ALIGNED_SIZE)) { if (p_rx_curr_desc->return_info != 0) { p_rx_curr_desc->return_info = 0; DP (printf ("freed\n")); } } DP (printf ("Done\n")); } return 0;}/********************************************************************** * mv64460_eth_stop * * This function is used when closing the network device. * It updates the hardware, * release all memory that holds buffers and descriptors and release the IRQ. * Input : a pointer to the device structure * Output : zero if success , nonzero if fails *********************************************************************/int mv64460_eth_stop (struct eth_device *dev){ ETH_PORT_INFO *ethernet_private; struct mv64460_eth_priv *port_private; unsigned int port_num; ethernet_private = (ETH_PORT_INFO *) dev->priv; port_private = (struct mv64460_eth_priv *) ethernet_private->port_private; port_num = port_private->port_num; /* Disable all gigE address decoder */ MV_REG_WRITE (MV64460_ETH_BASE_ADDR_ENABLE_REG, 0x3f); DP (printf ("%s Ethernet stop called ... \n", __FUNCTION__)); mv64460_eth_real_stop (dev); return 0;};/* Helper function for mv64460_eth_stop */static int mv64460_eth_real_stop (struct eth_device *dev){ ETH_PORT_INFO *ethernet_private; struct mv64460_eth_priv *port_private; unsigned int port_num; ethernet_private = (ETH_PORT_INFO *) dev->priv; port_private = (struct mv64460_eth_priv *) ethernet_private->port_private; port_num = port_private->port_num; mv64460_eth_free_tx_rings (dev); mv64460_eth_free_rx_rings (dev); eth_port_reset (ethernet_private->port_num); /* Disable ethernet port interrupts */ MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_REG (port_num), 0); MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_EXTEND_REG (port_num), 0); /* Mask RX buffer and TX end interrupt */ MV_REG_WRITE (MV64460_ETH_INTERRUPT_MASK_REG (port_num), 0); /* Mask phy and link status changes interrupts */ MV_REG_WRITE (MV64460_ETH_INTERRUPT_EXTEND_MASK_REG (port_num), 0); MV_RESET_REG_BITS (MV64460_CPU_INTERRUPT0_MASK_HIGH, BIT0 << port_num); /* Print Network statistics */#ifndef UPDATE_STATS_BY_SOFTWARE /* * Print statistics (only if ethernet is running), * then zero all the stats fields in memory */ if (port_private->eth_running == MAGIC_ETH_RUNNING) { port_private->eth_running = 0; mv64460_eth_print_stat (dev); } memset (port_private->stats, 0, sizeof (struct net_device_stats));#endif DP (printf ("\nEthernet stopped ... \n")); return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -