Chinaunix

标题: PCI网卡的MAC地址 [打印本页]

作者: sherf    时间: 2009-11-02 15:42
标题: PCI网卡的MAC地址
各位,请教一下,MAC的获取是怎样的?我的代码如下(但老是得不到MAC地址)

//遍历PCI配置空间
while(i<32)
    {
        out_word(0xCF8,j);
       
        pcidata = in_word(0xCFC);

        //找到网卡后
        if (pcidata == 0x831910EC )
        {
           out_word(0xCF8,j+0x10 );
          
           *iobase  =in_word(0xCFC );
           *iobase &= 0xFFFFFFF0;
          
           // for mac
            printf("mac addr is : " );

           mac_base         = *iobase + 0x50;
           for(k=0; k<6; k++)
           {
                   mac         = in_word(mac_base + k*0x8 );
                printf ("%x:",mac&0x000000FF );
           }
           printf("\n" );


           return 1;
        }

        i++;
        j += 0x800;
    }

[ 本帖最后由 sherf 于 2009-11-2 15:45 编辑 ]
作者: sherf    时间: 2009-11-02 15:45
标题: 回复 #1 sherf 的帖子
先顶一下
作者: sherf    时间: 2009-11-02 17:07
标题: 回复 #2 sherf 的帖子
有人知道吗?
作者: wzypunk    时间: 2009-11-02 20:43
为什么不用ioctl操作socket呢?
作者: accessory    时间: 2009-11-03 00:57
LZ的代码是想读EEPROM里面的MAC么?如果是,你读EEPROM的方法不对。
下面这段是从LINUX, 8139TOO.C里面抄过来的:
另外,IO ADDR的前6个字节也含有MAC地址。可以直接读。具体方法可以参考8139TOO.C

static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len)
{
        int i;
        unsigned retval = 0;
        int read_cmd = location | (EE_READ_CMD << addr_len);

        RTL_W8 (Cfg9346, EE_ENB & ~EE_CS);
        RTL_W8 (Cfg9346, EE_ENB);
        eeprom_delay ();

        /* Shift the read command bits out. */
        for (i = 4 + addr_len; i >= 0; i--) {
                int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
                RTL_W8 (Cfg9346, EE_ENB | dataval);
                eeprom_delay ();
                RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK);
                eeprom_delay ();
        }
        RTL_W8 (Cfg9346, EE_ENB);
        eeprom_delay ();

        for (i = 16; i > 0; i--) {
                RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK);
                eeprom_delay ();
                retval =
                    (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 :
                                     0);
                RTL_W8 (Cfg9346, EE_ENB);
                eeprom_delay ();
        }

        /* Terminate the EEPROM access. */
        RTL_W8 (Cfg9346, ~EE_CS);
        eeprom_delay ();

        return retval;
}
作者: sherf    时间: 2009-11-03 09:24
标题: 回复 #5 accessory 的帖子
accessory,

拿到的MAC地址仍为:FFFFFF.....

另外,你说的“IO ADDR的前6个字节也含有MAC地址”,IO ADDR是我上面的iobase吗?
作者: accessory    时间: 2009-11-03 09:40
"另外,你说的“IO ADDR的前6个字节也含有MAC地址”,IO ADDR是我上面的iobase吗?"

Yes
作者: godbach    时间: 2009-11-03 10:08
内核中有8139的网卡驱动代码啊
作者: sherf    时间: 2009-11-03 10:19
标题: 回复 #7 accessory 的帖子
accessory,

拿到的仍然不对,不知道是不是我拿的有问题,具体代码如下:

//遍历PCI配置空间
while(i<32)
    {
        out_word(0xCF8,j);
      
        pcidata = in_word(0xCFC);

        //找到网卡后
        if (pcidata == 0x831910EC )
        {
           out_word(0xCF8,j+0x10 );
         
           *iobase  =in_word(0xCFC );
           *iobase &= 0xFFFFFFF0;
         
           // for mac
            printf("mac addr is : " );

          for(k=0;k<6;k++)
           {
                mac        = in_byte(*iobase + k );
                printl("%x:",mac&0x000000FF );
           }

           printf("\n" );

           return 1;
        }

        i++;
        j += 0x800;
    }

[ 本帖最后由 sherf 于 2009-11-3 10:20 编辑 ]
作者: sherf    时间: 2009-11-03 12:55
标题: 回复 #9 sherf 的帖子
改成以下方式,也是拿的不对。


//遍历PCI配置空间
while(i<32)
    {
        out_word(0xCF8,j);
      
        pcidata = in_word(0xCFC);

        //找到网卡后
        if (pcidata == 0x831910EC )
        {
           out_word(0xCF8,j+0x10 );
         
           *iobase  =in_word(0xCFC );
           *iobase &= 0xFFFFFFF0;
         
           // for mac
            printf("mac addr is : " );

              // u8** macaddr;
                 *macaddr = (u8*)(*iobase );

                   for(k=0;k<6;k++ )
                   {
                        printf("%x:",(*(*macaddr+k ) ) & 0x000000FF );
                   }

                   printf("\n");

           return 1;
        }

        i++;
        j += 0x800;
    }

[ 本帖最后由 sherf 于 2009-11-3 12:57 编辑 ]
作者: accessory    时间: 2009-11-03 13:07
要用io来读。10楼的方法不对。
另外,你确定拿到的iobase是对的么?可以打印出来看看具体数值。
作者: accessory    时间: 2009-11-03 13:21
又想了下。怎么读要看你的设备是配制成 io map or memory map. 如果是io map,那用9楼的方法,反之用10楼的。
我看 qemu rtl8139的实现文件里,2种都支持。bochs就不清楚了。
作者: sherf    时间: 2009-11-03 13:22
原帖由 accessory 于 2009-11-3 13:07 发表
要用io来读。10楼的方法不对。
另外,你确定拿到的iobase是对的么?可以打印出来看看具体数值。


accessory,

用哪个IO端口读? 如果是用io的方法之前我也试过(9楼的代码),但出不来结果(数据不对)。顺便问一句,我之前的代码(9楼)对吗 ?由于是用bochs调试,很多东西我都不是很确定.......

另,iobase我打印过出来,是有数值的,但对不对我也不知道怎样验证。
作者: sherf    时间: 2009-11-03 15:07
标题: 回复 #13 sherf 的帖子
有人知道吗?mac这东西真难弄...........
作者: accessory    时间: 2009-11-04 00:07
lz,你到底是在什么环境下编程的?什么OS?自己写的OS?PCI 初始化这部分一般是OS去做的。你程序运行的时候OS还没跑起来?
如果没有OS初始化过PCI的话,那你要自己读PCI 设备的 BASE ADDR REGISTER。找出来它是IO MAP OR MEMORY MAP。需要多大,然后自己分配个空间给它。我以前给你的连接里写的还算清楚的。不知道你看了没有。下面我把相关的直接贴出来。


http://tldp.org/LDP/tlk/dd/pci.html
Finding Out How Much PCI I/O and PCI Memory Space a Device Needs
Each PCI device found is queried to find out how much PCI I/O and PCI Memory address space it requires. To do this, each Base Address Register has all 1's written to it and then read. The device will return 0's in the don't-care address bits, effectively specifying the address space required.

There are two basic types of Base Address Register, the first indicates within which address space the devices registers must reside; either PCI I/O or PCI Memory space. This is indicated by Bit 0 of the register. Figure  6.10 shows the two forms of the Base Address Register for PCI Memory and for PCI I/O.

To find out just how much of each address space a given Base Address Register is requesting, you write all 1s into the register and then read it back. The device will specify zeros in the don't care address bits, effectively specifying the address space required. This design implies that all address spaces used are a power of two and are naturally aligned.

For example when you initialize the DECChip 21142 PCI Fast Ethernet device, it tells you that it needs 0x100 bytes of space of either PCI I/O or PCI Memory. The initialization code allocates it space. The moment that it allocates space, the 21142's control and status registers can be seen at those addresses.

Allocating PCI I/O and PCI Memory to PCI-PCI Bridges and Devices
Like all memory the PCI I/O and PCI memory spaces are finite, and to some extent scarce. The PCI Fixup code for non-Intel systems (and the BIOS code for Intel systems) has to allocate each device the amount of memory that it is requesting in an efficient manner. Both PCI I/O and PCI Memory must be allocated to a device in a naturally aligned way. For example, if a device asks for 0xB0 of PCI I/O space then it must be aligned on an address that is a multiple of 0xB0. In addition to this, the PCI I/O and PCI Memory bases for any given bridge must be aligned on 4K and on 1Mbyte boundaries respectively. Given that the address spaces for downstream devices must lie within all of the upstream PCI-PCI Bridge's memory ranges for any given device, it is a somewhat difficult problem to allocate space efficiently.
作者: yidou    时间: 2009-11-04 09:13
找到该卡的编程手册吧
作者: sherf    时间: 2009-11-04 09:55
原帖由 accessory 于 2009-11-4 00:07 发表
lz,你到底是在什么环境下编程的?什么OS?自己写的OS?PCI 初始化这部分一般是OS去做的。你程序运行的时候OS还没跑起来?
如果没有OS初始化过PCI的话,那你要自己读PCI 设备的 BASE ADDR REGISTER。找出来它是 ...


accessory,

你的意思是:如果不使用操作系统资源(像目前我是通过其他的启动程序而没进入任何操作系统)的话,要读取MAC地址就只能从EPPROM入手,而将MAC地址映射入IO地址空间(IOADDR头6个字节)的任务是操作系统去完成的(即我目前是要自己编程实现的)。是这样吗?
作者: sherf    时间: 2009-11-04 17:14
标题: 回复 #15 accessory 的帖子
accessory,

谢谢你之前的回复,我已拿到MAC地址了
作者: FedoraAdmin    时间: 2009-11-04 19:15
关注下
作者: accessory    时间: 2009-11-05 01:29
怎么拿到的?换了QEMU就好了?又是BOCHS的问题?
作者: sherf    时间: 2009-11-05 02:05
原帖由 accessory 于 2009-11-5 01:29 发表
怎么拿到的?换了QEMU就好了?又是BOCHS的问题?


确实,但不能说是bochs的问题,是我原先没留意到bochs的虚拟网卡用的是ne2000,而不是rtl8139,只是潜意识的认为bochs能模拟出所有真实的硬件。更换成QEMU并装上rtl8139后,2种方式都能取到MAC(EEPROM和IOADDR方式)

另外补充一下,第一次之所以是bochs的原因是因为我用的版本太旧,不支持PCI的,最新版的bochs已能支持PCI模拟了。

[ 本帖最后由 sherf 于 2009-11-5 02:09 编辑 ]
作者: accessory    时间: 2009-11-05 02:22
看来大部分时间都是浪费在了低级错误上。
作者: xuxd32    时间: 2009-11-06 18:10
提示: 作者被禁止或删除 内容自动屏蔽




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2