OK335xS 网络连接打印信息 hacking

/***********************************************************************
* OK335xS 网络连接打印信息 hacking
* 说明:
* 当我们插入网线的时候,经常会看到对应的网卡已连接,当前属于10M、
* 100M网卡工作状态等等信息,那么这些信息是如何被输出的,工作机制是什么,
* 网卡的速度是由phy决定的还是由mac决定的,是不是在phy对应的中断里处理,
* 等等,这些内容都需要去确认。
*
* 2016-2-2 深圳 南山平山村 曾剑锋
**********************************************************************/ /**
* 参考文章:
* Linux PHY几个状态的跟踪
* http://www.latelee.org/programming-under-linux/linux-phy-state.html
*/ static const struct dev_pm_ops cpsw_pm_ops = { <------+
.suspend = cpsw_suspend, |
.resume = cpsw_resume, -----------+
}; | |
| |
static struct platform_driver cpsw_driver = { <---|-+ |
.driver = { | | |
.name = "cpsw", | | |
.owner = THIS_MODULE, | | |
.pm = &cpsw_pm_ops, ----------+ | |
}, | |
.probe = cpsw_probe, | |
.remove = __devexit_p(cpsw_remove), | |
}; | |
| |
static int __init cpsw_init(void) | |
{ | |
return platform_driver_register(&cpsw_driver); -----+ |
} |
late_initcall(cpsw_init); |
|
static void __exit cpsw_exit(void) |
{ |
platform_driver_unregister(&cpsw_driver); |
} |
module_exit(cpsw_exit); |
|
MODULE_LICENSE("GPL"); |
MODULE_DESCRIPTION("TI CPSW Ethernet driver"); |
|
|
|
static int cpsw_resume(struct device *dev) <----------+
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev = platform_get_drvdata(pdev); pm_runtime_get_sync(&pdev->dev);
cpsw_start_slaves_interface(ndev); ----+
|
return ; |
} |
|
V
static inline void cpsw_start_slaves_interface(struct net_device *ndev)
{
struct cpsw_priv *priv = netdev_priv(ndev);
u32 i = ; for (i = ; i < priv->data.slaves; i++) {
ndev = cpsw_get_slave_ndev(priv, i);
if (netif_running(ndev))
cpsw_ndo_open(ndev); ----------+
} |
} |
|
|
static int cpsw_ndo_open(struct net_device *ndev) <--+
{
struct cpsw_priv *priv = netdev_priv(ndev);
int i, ret;
u32 reg; if (!cpsw_common_res_usage_state(priv))
cpsw_intr_disable(priv);
netif_carrier_off(ndev); if (priv->data.phy_control)
(*priv->data.phy_control)(true); reg = __raw_readl(&priv->regs->id_ver);
priv->version = reg; msg(info, ifup, "initializing cpsw version %d.%d (%d)\n",
(reg >> & 0x7), reg & 0xff, (reg >> ) & 0x1f); /* initialize host and slave ports */
if (!cpsw_common_res_usage_state(priv))
cpsw_init_host_port(priv);
for_each_slave(priv, cpsw_slave_open, priv); -----------+
|
/* Add default VLAN */ |
cpsw_add_default_vlan(priv); |
|
if (!cpsw_common_res_usage_state(priv)) { |
ret = device_create_file(&ndev->dev, &dev_attr_hw_stats); |
if (ret < ) { |
dev_err(priv->dev, "unable to add device attr\n"); |
return ret; |
} |
|
/* setup tx dma to fixed prio and zero offset */ |
cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, ); |
cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, ); |
|
/* disable priority elevation and enable statistics */ |
/* on all ports */ |
writel(, &priv->regs->ptype); |
writel(0x7, &priv->regs->stat_port_en); |
|
if (WARN_ON(!priv->data.rx_descs)) |
priv->data.rx_descs = ; |
|
for (i = ; i < priv->data.rx_descs; i++) { |
struct sk_buff *skb; |
|
ret = -ENOMEM; |
skb = netdev_alloc_skb_ip_align(priv->ndev, |
priv->rx_packet_max); |
if (!skb) |
break; |
ret = cpdma_chan_submit(priv->rxch, skb, skb->data, |
skb_tailroom(skb), , GFP_KERNEL); |
if (WARN_ON(ret < )) { |
dev_kfree_skb_any(skb); |
break; |
} |
} |
/* |
* continue even if we didn't manage to submit all |
* receive descs |
*/ |
msg(info, ifup, "submitted %d rx descriptors\n", i); |
|
if (cpts_register(&priv->pdev->dev, priv->cpts, |
priv->data.cpts_clock_mult, |
priv->data.cpts_clock_shift)) |
dev_err(priv->dev, "error registering cpts device\n"); |
} |
|
/* Enable Interrupt pacing if configured */ |
if (priv->coal_intvl != ) { |
struct ethtool_coalesce coal; |
|
coal.rx_coalesce_usecs = (priv->coal_intvl << ); |
cpsw_set_coalesce(ndev, &coal); |
} |
|
/* Enable Timer for capturing cpsw rx interrupts */ |
omap_dm_timer_set_int_enable(dmtimer_rx, OMAP_TIMER_INT_CAPTURE);|
omap_dm_timer_set_capture(dmtimer_rx, , , ); |
omap_dm_timer_enable(dmtimer_rx); |
|
/* Enable Timer for capturing cpsw tx interrupts */ |
omap_dm_timer_set_int_enable(dmtimer_tx, OMAP_TIMER_INT_CAPTURE);|
omap_dm_timer_set_capture(dmtimer_tx, , , ); |
omap_dm_timer_enable(dmtimer_tx); |
|
cpdma_ctlr_start(priv->dma); |
cpsw_intr_enable(priv); |
napi_enable(&priv->napi); |
cpdma_ctlr_eoi(priv->dma); |
|
cpsw_update_slave_open_state(priv, true) |
|
return ; +-----------------------------------------------+
} |
|
V
static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
{
char name[];
u32 slave_port; sprintf(name, "slave-%d", slave->slave_num); soft_reset(name, &slave->sliver->soft_reset); /* setup priority mapping */
writel(0x76543210, &slave->sliver->rx_pri_map);
if (priv->version == CPSW_VERSION1)
slave_write(slave, 0x33221100, CPSW1_TX_PRI_MAP);
else
slave_write(slave, 0x33221100, CPSW2_TX_PRI_MAP); /* setup max packet size, and mac address */
__raw_writel(priv->rx_packet_max, &slave->sliver->rx_maxlen);
cpsw_set_slave_mac(slave, priv); slave->mac_control = ; /* no link yet */ slave_port = cpsw_get_slave_port(priv, slave->slave_num); cpsw_add_dual_emac_mode_default_ale_entries(priv, slave, slave_port);
cpsw_add_switch_mode_bcast_ale_entries(priv, slave_port);
priv->port_state[slave_port] = ALE_PORT_STATE_FORWARD; slave->phy = phy_connect(priv->ndev, slave->data->phy_id, ------+
&cpsw_adjust_link, , slave->data->phy_if); ------*--------+
if (IS_ERR(slave->phy)) { | |
msg(err, ifup, "phy %s not found on slave %d\n", | |
slave->data->phy_id, slave->slave_num); | |
slave->phy = NULL; | |
} else { | |
dev_info(priv->dev, "CPSW phy found : id is : 0x%x\n", | |
slave->phy->phy_id); | |
cpsw_set_phy_config(priv, slave->phy); | |
phy_start(slave->phy); | |
} +-------------------------------------------+ |
} | |
| |
V |
struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, |
void (*handler)(struct net_device *), u32 flags, |
phy_interface_t interface) |
{ |
struct phy_device *phydev; |
struct device *d; |
int rc; |
|
/* Search the list of PHY devices on the mdio bus for the |
* PHY with the requested name */ |
d = bus_find_device_by_name(&mdio_bus_type, NULL, bus_id); |
if (!d) { |
pr_err("PHY %s not found\n", bus_id); |
return ERR_PTR(-ENODEV); |
} |
phydev = to_phy_device(d); |
|
rc = phy_connect_direct(dev, phydev, handler, flags, interface); ----+ |
if (rc) | |
return ERR_PTR(rc); | |
| |
return phydev; | |
} | |
EXPORT_SYMBOL(phy_connect); | |
+----------------------------------------------------------+ |
V |
int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, |
void (*handler)(struct net_device *), u32 flags, |
phy_interface_t interface) |
{ |
int rc; |
|
rc = phy_attach_direct(dev, phydev, flags, interface); |
if (rc) |
return rc; |
|
phy_prepare_link(phydev, handler); ----------------+ |
phy_start_machine(phydev, NULL); ---------------------*--------+ |
if (phydev->irq > ) | | |
phy_start_interrupts(phydev); | | |
| | |
return ; | | |
} | | |
EXPORT_SYMBOL(phy_connect_direct); | | |
| | |
| | |
static void phy_prepare_link(struct phy_device *phydev, <-----+ | |
void (*handler)(struct net_device *)) | |
{ | |
phydev->adjust_link = handler; | |
} | |
| |
| |
/** | |
* phy_start_machine - start PHY state machine tracking | |
* @phydev: the phy_device struct | |
* @handler: callback function for state change notifications | |
* | |
* Description: The PHY infrastructure can run a state machine | |
* which tracks whether the PHY is starting up, negotiating, | |
* etc. This function starts the timer which tracks the state | |
* of the PHY. If you want to be notified when the state changes, | |
* pass in the callback @handler, otherwise, pass NULL. If you | |
* want to maintain your own state machine, do not call this | |
* function. | |
*/ | |
void phy_start_machine(struct phy_device *phydev, <--------------+ |
void (*handler)(struct net_device *)) |
{ |
phydev->adjust_state = handler; |
|
schedule_delayed_work(&phydev->state_queue, HZ); |
} |
|
|
static void cpsw_adjust_link(struct net_device *ndev) <------------------+
{
struct cpsw_priv *priv = netdev_priv(ndev);
bool link = false; for_each_slave(priv, _cpsw_adjust_link, priv, &link); ----------+
|
if (link) { |
netif_carrier_on(ndev); |
if (netif_running(ndev)) |
netif_wake_queue(ndev); |
} else { |
netif_carrier_off(ndev); |
netif_stop_queue(ndev); |
} |
} |
|
|
static void _cpsw_adjust_link(struct cpsw_slave *slave, <--------+
struct cpsw_priv *priv, bool *link)
{
struct phy_device *phy = slave->phy;
u32 mac_control = ;
u32 slave_port; if (!phy)
return; slave_port = cpsw_get_slave_port(priv, slave->slave_num); if (phy->link) {
/* enable forwarding */
cpsw_ale_control_set(priv->ale, slave_port,
ALE_PORT_STATE, priv->port_state[slave_port]); mac_control = priv->data.mac_control;
if (phy->speed == )
mac_control |= BIT(); /* In Band mode */
if (phy->speed == ) {
mac_control |= BIT(); /* Enable gigabit mode */
}
if (phy->speed == )
mac_control |= BIT();
if (phy->duplex)
mac_control |= BIT(); /* FULLDUPLEXEN */
if (phy->interface == PHY_INTERFACE_MODE_RGMII) /* RGMII */
mac_control |= (BIT()|BIT());
*link = true;
} else {
cpsw_ale_control_set(priv->ale, slave_port,
ALE_PORT_STATE, ALE_PORT_STATE_DISABLE);
mac_control = ;
} if (mac_control != slave->mac_control) {
phy_print_status(phy); ---------------+
__raw_writel(mac_control, &slave->sliver->mac_control); |
} |
|
slave->mac_control = mac_control; |
} |
|
/** |
* phy_print_status - Convenience function to print out the current phy status |
* @phydev: the phy_device struct |
*/ |
void phy_print_status(struct phy_device *phydev) <-------------+
{
pr_info("PHY: %s - Link is %s", dev_name(&phydev->dev),
phydev->link ? "Up" : "Down");
if (phydev->link)
printk(KERN_CONT " - %d/%s", phydev->speed,
DUPLEX_FULL == phydev->duplex ?
"Full" : "Half"); printk(KERN_CONT "\n");
}
EXPORT_SYMBOL(phy_print_status); /*
* 1. LAN8710A/LAN8710Ai datasheet
* 1. http://ww1.microchip.com/downloads/en/DeviceDoc/8710a.pdf
* 2. 1.2 General Description
* ......
* The LAN8710A/LAN8710Ai supports communication with an Ethernet MAC via a standard MII (IEEE 802.3u)/RMII interface. It contains a full-duplex 10-BASE-T/100BASE-TX transceiver and supports 10Mbps (10BASE-T) and 100Mbps (100BASE-TX) operation. The LAN8710A/LAN8710Ai implements auto-negotiation to automatically determine the best possible speed and duplex mode of operation. HP Auto-MDIX support allows the use of direct connect or cross-over LAN cables.
* ......
* 2. 由上面可知,决定网卡的工作速度的是phy自动决定。
*/
上一篇:网页布局之bootStrap栅格系统(2020年7月19日)


下一篇:asp.net批量下载图片