设为首页 收藏本站
查看: 1068|回复: 0

[经验分享] I.MX6 Ethernet MAC (ENET) MAC Address hacking

[复制链接]

尚未签到

发表于 2017-7-6 14:28:12 | 显示全部楼层 |阅读模式
/*********************************************************************
*        I.MX6 Ethernet MAC (ENET) MAC Address hacking
* 说明:
*     Lee对相关的一些代码进行了修改,所以这边跟一下这边相关的设置原理,
* 主要是为了知道MAC address在Uboot、Linux kernel阶段的的设置,获取的
* 工作机制。
*
*                                   2016-7-27 深圳 南山平山村 曾剑锋
********************************************************************/
参考文档:
Freescale i.MX6 Linux Ethernet Driver驱动源码分析
http://blog.163.com/thinki_cao/blog/static/8394487520146308450620/


cat lib_arm/board.c                                                            
void start_armboot (void)                                                      
{                                                                              
......                                                                     
stdio_init ();    /* get the devices list going. */  ---------+            
......                                                        |            
eth_initialize(gd->bd);                       ----------------*-+           
......                                                        | |           
}                                                                 | |           
| |           
int stdio_init (void)               <-----------------------------+ |           
{                                                                   |           
......                                                          |           
#ifdef CONFIG_LCD                                                   |           
drv_lcd_init ();                   ------------+                |           
#endif                                             |                |           
......                                         |                |           
|                |           
return (0);                                    |                |           
}                                                  |                |           
|                |           
int drv_lcd_init (void)               <------------+                |           
{                                                                   |           
......                                                          |           
lcd_init (lcd_base);        /* LCD initialization */ --------+  |           
......                                                       |  |           
}                                                                |  |           
|  |           
static int lcd_init (void *lcdbase)                     <--------+  |           
{                                                                   |           
......                                                          |           
lcd_enable ();                                --------+         |           
......                                                |         |           
}                                                         |         |           
|         |           
#ifdef CONFIG_LCD                                         |         |           
void lcd_enable(void)                            <--------+         |           
{                                                                   |           
......                                                          |           
setenv("ethaddr",buffer);                                       |           
......                                                          |           
}                                                                   |           
|           
int eth_initialize(bd_t *bis)                <----------------------+           
{                                                                              
......                                                                     
/* Try board-specific initialization first.  If it fails or isn't           
* present, try the cpu-specific initialization */                          
if (board_eth_init(bis) < 0)                                                
cpu_eth_init(bis);                   -------+                           
|                           
......                                          |                           
}                                                   |                           
|                           
|                           
int cpu_eth_init(bd_t *bis)                  <------+                           
{                                                                              
int rc = -ENODEV;                                                           
#if defined(CONFIG_MXC_FEC)                                                     
rc = mxc_fec_initialize(bis);            -------+                           
|                           
/* Board level init */                          |                           
enet_board_init();                              |                           
|                           
#endif                                              |                           
return rc;                                      |                           
}                                                   |                           
|                           
int mxc_fec_initialize(bd_t *bis)           <-------+                           
{                                                                              
struct eth_device *dev;                                                     
int i;                                                                     
unsigned char ethaddr[6];                                                   
for (i = 0; i < sizeof(fec_info) / sizeof(fec_info[0]); i++) {              
#ifdef CONFIG_ARCH_MMU                                                         
int j;                                                                  
#endif                                                                          
dev =                                                                  
(struct eth_device *)memalign(CONFIG_SYS_CACHELINE_SIZE,            
sizeof *dev);                                         
if (dev == NULL)                                                        
hang();                                                            
memset(dev, 0, sizeof(*dev));                                          
sprintf(dev->name, "FEC%d", fec_info.index);                        
dev->priv = &fec_info;                       ----------+            
dev->init = fec_init;                                     |            
dev->halt = fec_halt;                                     |            
dev->send = fec_send;                                     |            
dev->recv = fec_recv;                                     |            
......                                                    |            
|            
if (fec_get_hwaddr(dev, ethaddr) == 0) {            ------*-----+      
printf("got MAC address from IIM: %pM\n", ethaddr);   |     |      
memcpy(dev->enetaddr, ethaddr, 6);                    |     |      
fec_set_hwaddr(dev);                            ------*-----*-+     
}                                                         |     | |     
}                                                             |     | |     
|     | |     
return 1;                                                     |     | |     
}                                                                 |     | |     
|     | |     
struct fec_info_s fec_info[] = {                       <----------+     | |     
{                                                             |     | |     
0,            /* index */                                    |     | |     
CONFIG_FEC0_IOBASE,    /* io base */               --------+-*-----*-*-+   
CONFIG_FEC0_PHY_ADDR,    /* phy_addr */                    | |     | | |   
0,            /* duplex and speed */                       | |     | | |   
0,            /* phy name */                               | |     | | |   
0,            /* phyname init */                           | |     | | |   
0,            /* RX BD */                                  | |     | | |   
0,            /* TX BD */                                  | |     | | |   
0,            /* rx Index */                               | |     | | |   
0,            /* tx Index */                               | |     | | |   
0,            /* tx buffer */                              | |     | | |   
#ifdef CONFIG_ARCH_MMU                                          | |     | | |   
{ 0 },            /* rx buffer */                          | |     | | |   
#endif                                                          | |     | | |   
0,            /* initialized flag */                       | |     | | |   
},                                                         | |     | | |   
};                                                              | |     | | |   
| |     | | |   
/* FEC private information */                                   | |     | | |   
struct fec_info_s {                                  <----------*-+     | | |   
int index;                                                  |       | | |   
u32 iobase;                                                 |       | | |   
int phy_addr;                                               |       | | |   
int dup_spd;                                                |       | | |   
char *phy_name;                                             |       | | |   
int phyname_init;                                           |       | | |   
cbd_t *rxbd;        /* Rx BD */                             |       | | |   
cbd_t *txbd;        /* Tx BD */                             |       | | |   
uint rxIdx;                                                 |       | | |   
uint txIdx;                                                 |       | | |   
char *txbuf;                                                |       | | |   
#ifdef CONFIG_ARCH_MMU                                          |       | | |   
char *rxbuf[PKTBUFSRX];                                     |       | | |   
#endif                                                          |       | | |   
int initialized;                                            |       | | |   
struct fec_info_s *next;                                    |       | | |   
};                                                              |       | | |   
|       | | |   
#define CONFIG_FEC0_IOBASE    ENET_BASE_ADDR       <------------+       | | |   
#define ENET_BASE_ADDR              (AIPS2_OFF_BASE_ADDR + 0x8000)      | | |   
#define AIPS2_OFF_BASE_ADDR         (ATZ2_BASE_ADDR + 0x80000)          | | |   
#define ATZ2_BASE_ADDR              AIPS2_ARB_BASE_ADDR                 | | |   
#define AIPS2_ARB_BASE_ADDR             0x02100000                      | | |   
| | |   
extern int fec_get_mac_addr(unsigned char *mac);                        | | |   
static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac) <-+ | |   
{                                                                         | |   
#ifdef CONFIG_GET_FEC_MAC_ADDR_FROM_IIM                                   | |   
fec_get_mac_addr(mac);                          ----------+           | |   
|           | |   
return 0;                                                 |           | |   
#else                                                         |           | |   
return -1;                                                |           | |   
#endif                                                        |           | |   
}                                                             |           | |   
|           | |   
#ifdef CONFIG_GET_FEC_MAC_ADDR_FROM_IIM                       |           | |   
int fec_get_mac_addr(unsigned char *mac)           <----------+           | |   
{                                                                         | |   
#if 0                                                                     | |   
unsigned int value;                                                   | |   
| |   
value = readl(OCOTP_BASE_ADDR + HW_OCOTP_MACn(0));                    | |   
mac[5] = value & 0xff;                                                | |   
mac[4] = (value >> 8) & 0xff;                                         | |   
mac[3] = (value >> 16) & 0xff;                                        | |   
mac[2] = (value >> 24) & 0xff;                                        | |   
value = readl(OCOTP_BASE_ADDR + HW_OCOTP_MACn(1));                    | |   
mac[1] = value & 0xff;                                                | |   
mac[0] = (value >> 8) & 0xff;                                         | |   
#else                                                                     | |   
eth_getenv_enetaddr("ethaddr", mac);            ----------+           | |   
#endif                                                        |           | |   
return 0;                                                 |           | |   
}                                                             |           | |   
#endif                                                        |           | |   
|           | |   
static int fec_set_hwaddr(struct eth_device *dev)        <----|-----------+ |   
{                                                             |             |   
uchar *mac = dev->enetaddr;                               |             |   
struct fec_info_s *info = dev->priv;                      |             |   
volatile fec_t *fecp = (fec_t *)(info->iobase);           |             |   
|             |   
writel(0, &fecp->iaur);                                   |             |   
writel(0, &fecp->ialr);                                   |             |   
writel(0, &fecp->gaur);                                   |             |   
writel(0, &fecp->galr);                                   |             |   
|             |   
/*                                                        |             |   
* Set physical address                                   |             |   
*/                                                       V             |   
writel((mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3],  ------*-+
&fecp->palr);                                                   | |
writel((mac[4] << 24) + (mac[5] << 16) + 0x8808, &fecp->paur);          | |
| |
return 0;                                                               | |
}                                                                           | |
| |
| |
cat arch/arm/mach-mx6/board-mx6q_sabresd.c                                  | |
MACHINE_START(MX6Q_SABRESD, "Freescale i.MX 6Quad/DualLite/Solo Sabre-SD Boa|"|)
/* Maintainer: Freescale Semiconductor, Inc. */                         | |
.boot_params = MX6_PHYS_OFFSET + 0x100,                                 | |
.fixup = fixup_mxc_board,                                               | |
.map_io = mx6_map_io,                                                   | |
.init_irq = mx6_init_irq,                                               | |
.init_machine = mx6_sabresd_board_init,      ----------+                | |
.timer = &mx6_sabresd_timer,                           |                | |
.reserve = mx6q_sabresd_reserve,                       |                | |
MACHINE_END                                                |                | |
|                | |
/*!                                                        |                | |
* Board specific initialization.                          |                | |
*/                                                        |                | |
static void __init mx6_sabresd_board_init(void)  <---------+                | |
{                                                                           | |
......                                                                  | |
imx6_init_fec(fec_data);                                                | |
......   |                                                              | |
}            |                                                              | |
V                                                              | |
void __init imx6_init_fec(struct fec_platform_data fec_data)  ---------+    | |
{                                                                      |    | |
fec_get_mac_addr(fec_data.mac);                                    |    | |
/*                                                                 |    | |
if (!is_valid_ether_addr(fec_data.mac))                            |    | |
random_ether_addr(fec_data.mac);                               |    | |
*/                                                                 |    | |
|    | |
if (cpu_is_mx6sl())                                                |    | |
imx6sl_add_fec(&fec_data);                                     |    | |
else                                                               |    | |
imx6q_add_fec(&fec_data);                                      |    | |
}                                                                      |    | |
|    | |
extern const struct imx_fec_data imx6q_fec_data __initconst;           |    | |
#define imx6q_add_fec(pdata)    \                 <--------------------+    | |
imx_add_fec(&imx6q_fec_data, pdata)           ---------------------+    | |
|    | |
#ifdef CONFIG_SOC_IMX6Q                                                |    | |
const struct imx_fec_data imx6q_fec_data __initconst =                 |    | |
imx_fec_data_entry_single(MX6Q, "enet");                           |    | |
|    | |
const struct imx_fec_data imx6sl_fec_data __initconst =     <----------+    | |
imx_fec_data_entry_single(MX6DL, "fec");               ----------+ |    | |
#endif                                                               | |    | |
| |    | |
struct platform_device *__init imx_add_fec(       <------------------*-+    | |
const struct imx_fec_data *data,                             |      | |
const struct fec_platform_data *pdata)                       |      | |
{                                                                    |      | |
struct resource res[] = {                                        |      | |
{                                                            |      | |
.start = data->iobase,                                   |      | |
.end = data->iobase + SZ_4K - 1,                         |      | |
.flags = IORESOURCE_MEM,                                 |      | |
}, {                                                         |      | |
.start = data->irq,                                      |      | |
.end = data->irq,                                        |      | |
.flags = IORESOURCE_IRQ,                                 |      | |
},                                                           |      | |
};                                                               |      | |
|      | |
if (!fuse_dev_is_available(MXC_DEV_ENET))                        |      | |
return ERR_PTR(-ENODEV);                                     |      | |
|      | |
return imx_add_platform_device_dmamask(data->devid, 0,           |      | |
res, ARRAY_SIZE(res),                                    |      | |
pdata, sizeof(*pdata), DMA_BIT_MASK(32));                |      | |
}                                                                    |      | |
|      | |
#define imx_fec_data_entry_single(soc, _devid)                \ <----+      | |
{                                \                                      | |
.iobase = soc ## _FEC_BASE_ADDR,            \        --------+      | |
.irq = soc ## _INT_FEC,                    \                 |      | |
.devid = _devid,                    \                        |      | |
}                                                                |      | |
|      | |
#define MX6DL_FEC_BASE_ADDR        ENET_BASE_ADDR            <-------+------+ |
#define ENET_BASE_ADDR            (AIPS2_OFF_BASE_ADDR+0x8000)                |
#define AIPS2_OFF_BASE_ADDR        (ATZ2_BASE_ADDR + 0x80000)                 |
#define ATZ2_BASE_ADDR            AIPS2_ARB_BASE_ADDR                         |
#define AIPS2_ARB_BASE_ADDR        0x02100000                                 |
|
cat drivers/net/fec.c                                                         |
static int __init                                                             |
fec_enet_module_init(void)                                                    |
{                                                                             |
printk(KERN_INFO "FEC Ethernet Driver\n");                                |
|
return platform_driver_register(&fec_driver);  ------+                    |
}                                                        |                    |
|                    |
static void __exit                                       |                    |
fec_enet_cleanup(void)                                   |                    |
{                                                        |                    |
platform_driver_unregister(&fec_driver);             |                    |
}                                                        |                    |
|                    |
module_exit(fec_enet_cleanup);                           |                    |
module_init(fec_enet_module_init);                       |                    |
|                    |
MODULE_LICENSE("GPL");                                   |                    |
|                    |
static struct platform_driver fec_driver = {       <-----+                    |
.driver    = {                                                            |
.name    = DRIVER_NAME,                                               |
.owner    = THIS_MODULE,                                              |
#ifdef CONFIG_PM                                                              |
.pm    = &fec_pm_ops,                                                 |
#endif                                                                        |
},                                                                        |
.id_table = fec_devtype,                                                  |
.probe    = fec_probe,                         ------+                    |
.remove    = __devexit_p(fec_drv_remove),            |                    |
};                                                       |                    |
|                    |
static int __devinit                                     |                    |
fec_probe(struct platform_device *pdev)            <-----+                    |
{                                                                             |
......                                                                    |
fep->hwp = ioremap(r->start, resource_size(r));      ---------------+     |
......                                                              |     |
ret = fec_enet_init(ndev);                     ------+              |     |
if (ret)                                             |              |     |
goto failed_init;                                |              |     |
......                                               |              |     |
}                                                        |              |     |
|              |     |
static int fec_enet_init(struct net_device *ndev)  <-----+              |     |
{                                                                       |     |
......                                                              |     |
/* Get the Ethernet address */                                      |     |
fec_get_mac(ndev);                             ----------------+    |     |
......                                                         |    |     |
}                                                                  |    |     |
|    |     |
static void __inline__ fec_get_mac(struct net_device *ndev)  <-----+    |     |
{                                                                       |     |
struct fec_enet_private *fep = netdev_priv(ndev);                   |     |
struct fec_platform_data *pdata = fep->pdev->dev.platform_data;     |     |
unsigned char *iap, tmpaddr[ETH_ALEN];                              |     |
|     |
/*                                                                  |     |
* try to get mac address in following order:                       |     |
*                                                                  |     |
* 1) module parameter via kernel command line in form              |     |
*    fec.macaddr=0x00,0x04,0x9f,0x01,0x30,0xe0                     |     |
*/                                                                 |     |
iap = macaddr;                                                      |     |
|     |
/*                                                                  |     |
* 2) from flash or fuse (via platform data)                        |     |
*/                                                                 |     |
if (!is_valid_ether_addr(iap)) {                                    |     |
#ifdef CONFIG_M5272                                                     |     |
if (FEC_FLASHMAC)                                               |     |
iap = (unsigned char *)FEC_FLASHMAC;                        |     |
#else                                                                   |     |
if (pdata)                                                      |     |
memcpy(iap, pdata->mac, ETH_ALEN);                          |     |
#endif                                                                  |     |
}                                                                   |     |
|     |
/*                                                                  |     |
* 3) FEC mac registers set by bootloader                           |     |
*/                                                                 |     |
if (!is_valid_ether_addr(iap)) {                                    |     |
*((unsigned long *) &tmpaddr[0]) =                              |     |
be32_to_cpu(readl(fep->hwp + FEC_ADDR_LOW));     <----------+-----+
*((unsigned short *) &tmpaddr[4]) =                                    
be16_to_cpu(readl(fep->hwp + FEC_ADDR_HIGH) >> 16);                 
iap = &tmpaddr[0];                                                      
}                                                                           
memcpy(ndev->dev_addr, iap, ETH_ALEN);                                      
/* Adjust MAC if using macaddr */                                          
if (iap == macaddr)                                                         
ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id;      
}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-391025-1-1.html 上篇帖子: Mac的SVN使用 下篇帖子: mac 下安装caffe(二)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表