如何修改wince(s3c2410)的MAC地址 转+撰

wince中的MAC地址是在驱动中写死的。如果不修改会造成一些网络方面的功能故障。比如不能互ping,同在一个局域网内会出现冲突等。

 下面是我解决的方法:

1.添加如下注册表
[HKEY_LOCAL_MACHINE\Comm\CS8900\Parms]
"MAC12"=dword:3322
"MAC34"=dword:5544
"MAC56"=dword:0F66

2.修改CS8900驱动
在CS8900.c文件中,作如下修改:

  1. WORD iMAC3={0x3322,0x5544,0x0F66};  //添加MAC地址的原始数据
  2. //添加函数,读取注册表中的MAC地址的值
  3. void ReadRegsister()
  4. {
  5.     HKEY hkMAC = NULL;
  6.     DWORD MAC;
  7.     DWORD dwStatus, dwType, dwSize;
  8.         TCHAR gszBaseInstance[256] = _T("\\Comm\\CS8900\\Parms");
  9.     // open the registry key and read our configuration
  10.     dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, gszBaseInstance, 0, KEY_ALL_ACCESS, &hkMAC);
  11.     dwType = REG_DWORD;
  12.     if(dwStatus == ERROR_SUCCESS && dwType == REG_DWORD) 
  13.         {
  14.         dwSize = sizeof(DWORD);
  15.         //下面读取失败的话那么就用初始值作为MAC地址
  16.         dwStatus = RegQueryValueEx(hkMAC, _T("MAC12"), NULL, &dwType, (LPBYTE) &MAC, &dwSize);
  17.         if (dwStatus == ERROR_SUCCESS)
  18.         {
  19.             iMAC[0]=MAC;
  20.         }
  21.         dwStatus = RegQueryValueEx(hkMAC, _T("MAC34"), NULL, &dwType, (LPBYTE) &MAC, &dwSize);  
  22.         if (dwStatus == ERROR_SUCCESS)
  23.         {
  24.             iMAC[1]=MAC;
  25.         }
  26.         dwStatus = RegQueryValueEx(hkMAC, _T("MAC56"), NULL, &dwType, (LPBYTE) &MAC, &dwSize);  
  27.         if (dwStatus == ERROR_SUCCESS)
  28.         {
  29.             iMAC[2]=MAC;
  30.         }
  31.     }
  32. }
  33. int initCS()
  34. {   
  35.     CS8900WriteRegister(PKTPG_LINE_CTL, LINE_CTL_10_BASE_T);
  36.     CS8900WriteRegister(PKTPG_RX_CFG, RX_CFG_RX_OK_I_E);
  37.     CS8900WriteRegister(PKTPG_RX_CTL,RX_CTL_RX_OK_A | RX_CTL_IND_ADDR_A |RX_CTL_BROADCAST_A);
  38.     CS8900WriteRegister(PKTPG_TX_CFG, 0); 
  39.     CS8900WriteRegister(PKTPG_BUF_CFG, 0); 
  40.     
  41.     //modify by constantine 
  42.     ReadRegsister();
  43.     CS8900WriteRegister(PKTPG_INDIVISUAL_ADDR + 0, iMAC[0]);
  44.     CS8900WriteRegister(PKTPG_INDIVISUAL_ADDR + 2, iMAC[1]);
  45.     CS8900WriteRegister(PKTPG_INDIVISUAL_ADDR + 4, iMAC[2]);
  46.     initIrq();
  47.     return TRUE;
  48. }
  49. BOOLEAN CS8900ReadEthernetAddress(
  50.     IN PCS8900_ADAPTER Adapter
  51. )
  52. {
  53. //modify by constantine
  54.     //Adapter->PermanentAddress[0] = 0x22;
  55.     //Adapter->PermanentAddress[1] = 0x33;
  56.     //Adapter->PermanentAddress[2] = 0x44;
  57.     //Adapter->PermanentAddress[3] = 0x55;
  58.     //Adapter->PermanentAddress[4] = 0x66;
  59.     //Adapter->PermanentAddress[5] = 0x0F;
  60.     
  61.     Adapter->PermanentAddress[0] = iMAC[0]& 0x00FF;
  62.     Adapter->PermanentAddress[1] = iMAC[0]>>8;
  63.     Adapter->PermanentAddress[2] = iMAC[1]& 0x00FF;
  64.     Adapter->PermanentAddress[3] = iMAC[1]>>8;
  65.     Adapter->PermanentAddress[4] = iMAC[2]& 0x00FF;
  66.     Adapter->PermanentAddress[5] = iMAC[2]>>8; 
  67. //end    
  68.     RETAILMSG(1,
  69.         (TEXT("CS8900: PermanentAddress [ %02x-%02x-%02x-%02x-%02x-%02x ]\r\n"),
  70.             Adapter->PermanentAddress[0],
  71.             Adapter->PermanentAddress[1],
  72.             Adapter->PermanentAddress[2],
  73.             Adapter->PermanentAddress[3],
  74.             Adapter->PermanentAddress[4],
  75.             Adapter->PermanentAddress[5]));
  76.     //
  77.     // Use the burned in address as the station address, unless the
  78.     // registry specified an override value.
  79.     //
  80.     if ((Adapter->StationAddress[0] == 0x00) &
  81.         (Adapter->StationAddress[1] == 0x00) &
  82.         (Adapter->StationAddress[2] == 0x00) &
  83.         (Adapter->StationAddress[3] == 0x00) &
  84.         (Adapter->StationAddress[4] == 0x00) &
  85.         (Adapter->StationAddress[5] == 0x00)
  86.         )
  87.     {
  88.         RETAILMSG(1, (TEXT("CS8900: StationAddress Modified!...\r\n")));
  89.         Adapter->StationAddress[0] = Adapter->PermanentAddress[0];
  90.         Adapter->StationAddress[1] = Adapter->PermanentAddress[1];
  91.         Adapter->StationAddress[2] = Adapter->PermanentAddress[2];
  92.         Adapter->StationAddress[3] = Adapter->PermanentAddress[3];
  93.         Adapter->StationAddress[4] = Adapter->PermanentAddress[4];
  94.         Adapter->StationAddress[5] = Adapter->PermanentAddress[5];
  95.     }
  96.     return(TRUE);
  97. }

编译后就可以了,这样就让驱动是从注册表中读取MAC地址了。那么接下来我们就有办法修改这个MAC地址了。

 3.写代码修改注册表

下面是关键代码:

 void CWINCEMACDlg::ReadRegsister()

  1. {
  2.     HKEY hkMAC = NULL;
  3.     DWORD MAC=0;
  4.     DWORD dwStatus, dwType, dwSize;
  5.     TCHAR gszBaseInstance[256] = _T("\\Comm\\CS8900\\Parms");
  6.     // open the registry key and read our configuration
  7.     dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, gszBaseInstance, 0, KEY_ALL_ACCESS, &hkMAC);
  8.     dwType = REG_DWORD;
  9.     if(dwStatus == ERROR_SUCCESS && dwType == REG_DWORD) 
  10.     {
  11.         dwSize = sizeof(DWORD);
  12.         dwStatus = RegQueryValueEx(hkMAC, _T("MAC12"), NULL, &dwType, (LPBYTE) &MAC, &dwSize);
  13.         if (dwStatus == ERROR_SUCCESS)
  14.         {
  15.             m_EDT0.Format(_T("%02x"),(MAC & 0x00ff));
  16.             m_EDT1.Format(_T("%02x"),(MAC >> 8));
  17.         }
  18.         dwStatus = RegQueryValueEx(hkMAC, _T("MAC34"), NULL, &dwType, (LPBYTE) &MAC, &dwSize);
  19.         if (dwStatus == ERROR_SUCCESS)
  20.         {
  21.             m_EDT2.Format(_T("%02x"),(MAC & 0x00ff));
  22.             m_EDT3.Format(_T("%02x"),(MAC >> 8));
  23.         }
  24.         dwStatus = RegQueryValueEx(hkMAC, _T("MAC56"), NULL, &dwType, (LPBYTE) &MAC, &dwSize);
  25.         if (dwStatus == ERROR_SUCCESS)
  26.         {
  27.             m_EDT4.Format(_T("%02x"),(MAC & 0x00ff));
  28.             m_EDT5.Format(_T("%02x"),(MAC >> 8));
  29.         }
  30.     }
  31.     RegCloseKey( hkMAC );
  32.     UpdateData(FALSE);
  33. }
  34. void CWINCEMACDlg::WriteRegsister()
  35. {
  36.     HKEY hkMAC = NULL;
  37.     DWORD dwStatus, dwSize;
  38.     TCHAR gszBaseInstance[256] = _T("\\Comm\\CS8900\\Parms");
  39.     dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, gszBaseInstance, 0, KEY_ALL_ACCESS, &hkMAC);
  40.     if(dwStatus == ERROR_SUCCESS ) 
  41.     {
  42.         dwSize = sizeof(DWORD);
  43.         int value;
  44.         TCHAR num[4]={0};
  45.         BYTE * lpBuffer;
  46.         UpdateData(TRUE);
  47.                 value=0;
  48.         wsprintf(num,L"0x%s", m_EDT1.GetBuffer(0));
  49.         value += _ttoi(num)<<8;
  50.         wsprintf(num,L"0x%s", m_EDT0.GetBuffer(0));
  51.         value += _ttoi(num);
  52.         lpBuffer = (BYTE *)&value;
  53.         RegSetValueEx(hkMAC, _T("MAC12"), 0, REG_DWORD, lpBuffer,dwSize);
  54.         value=0;
  55.         wsprintf(num,L"0x%s", m_EDT3.GetBuffer(0));
  56.         value += _ttoi(num)<<8;
  57.         wsprintf(num,L"0x%s", m_EDT2.GetBuffer(0));
  58.         value += _ttoi(num);
  59.         lpBuffer = (BYTE *)&value;
  60.         RegSetValueEx(hkMAC, _T("MAC34"), 0, REG_DWORD, lpBuffer,dwSize);
  61.         value=0;
  62.         wsprintf(num,L"0x%s", m_EDT5.GetBuffer(0));
  63.         value += _ttoi(num)<<8;
  64.         wsprintf(num,L"0x%s", m_EDT4.GetBuffer(0));
  65.         value += _ttoi(num);
  66.         lpBuffer = (BYTE *)&value;
  67.         RegSetValueEx(hkMAC, _T("MAC56"), 0, REG_DWORD, lpBuffer,dwSize);
  68.     }
  69.     RegCloseKey( hkMAC );
  70. }

 4.如果有外接EEPROM之类的话,那么一般是写在EEPROM里面的,而不是写注册表。如果这种实现方式必须采用Hive方式的注册表。不然也是保存不了的。

5.特别说明
MAC地址一般由12个16进制数字组成,每2个为一组,前面3组代表网络硬件制造商的编号,这个一般是由IEEE来分配。
后面3组代表该制造商所制造的某个网络产品的序列号。这样也就为什么我们说MAC地址是唯一的了(当然前提是你没有自己修改过)。
wince驱动由于比较特殊,6组值要写入3个IO里面一个IO只能写入16个字节,为了方便我就不按照正常定义为两个部分,
而是简单定义成3个部分,这样容易写代码。
必须说明的是MAC地址前3组值不是能随便更改的,我们一般就改动后3组就行了。非要改就要找一个制造商的编号才行。
另外如果不修改MAC地址不组网是没有问题的,但是如果组网就会有一些小问题,比如ping,wince之间无法相互ping。当然还有别的。

    这里我要说明的是通过应用程序修改注册表当中存放的MAC地址能够实现掉电保存功能,但是注意使用RegFlushKey()函数,我在debug版本时能够将修改的mac写入注册表,但是使用release版本时写入不成功,后来使用了RegFlushKey()才好使了。   

MAC地址要求第一个字节的bit0必须为0,表明此地址是个物理地址,否则mac地址无效。我在做就餐机时解决多mac地址的方法是系统第一次启动时先检查注册表当中是否有MAC34的数值,如果没有,那么使用随机数的方法生成一个2个字节的数据,将默认的MAC12,MAC56,连同新生成的MAC34写入到注册表当中,这样下次启动时就会有数据了,这里面不在platform.reg当中设置那3个值是因为如果设置了则每台机器刚开始时都有相同的mac,带来不便。我设置第一个字节始终为0x10,即便是在后来的修改mac应用程序当中也不能修改。

   设置mac还可以通过读取配置文件的方法,在定制内核时添加一个mac.ini文件,里面放置有效mac数据,在网卡驱动程序当中通过读取文件的方式实现读取mac地址,这里的文件需要在定制内核时放置,我试验了将mac.ini放置到residengFlash和SD Card里的方法,但都不能找到文件,怀疑可能是网卡驱动的加载先于residengFlash和SD Card。

你可能感兴趣的:(Boot)