Chinaunix首页 | 论坛 | 博客
  • 博客访问: 394917
  • 博文数量: 138
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1620
  • 用 户 组: 普通用户
  • 注册时间: 2013-03-10 16:55
个人简介

当你比别人优秀一点点,别人会嫉妒你。当你比别人优秀很多,别人会羡慕你。

文章分类

全部博文(138)

文章存档

2016年(2)

2015年(2)

2014年(15)

2013年(119)

我的朋友

分类: LINUX

2013-07-08 23:40:52

首先第一部分,看网卡如何被probe出来的。

分析如下,所有分析这个网卡架构的都是基于 ISA总线接口的情况下的分析,不管是书还是blog。

ISA情况下,内核启动的时候,会调用结构体中的成员(函数指针),static struct devprobe2 [] = {










#ifdef  
 {, 0},
#endif


进而调用probe函数, 完成网卡的probe。 
struct net_device *  (int )

 但是开发板上压根就不是用的这个路子,开发板网卡控制器本身就在cpu上,我们的网卡直接连到了CPU引脚。
其实想想,我们本质上就是想在内核启动的时候,调用网卡的probe函数,至于什么方式,放在总线的对应数组还是别的什么方式,都是可以的。
下面从网卡移植入口,看看我们移植的时候是如何做,使得内核启动的时候,去probe了我们的网卡。


综合比较了下网上关于移植的blog,又加上韦东山的书。发现上面的想法是错误的。


虽说我的开发板上是网卡和CPU直连的,没有经过ISA总线。我原来的设想是就不会使用上面的数组 [] ,也就调用不到我们的cs89x0_probe()函数了。但事实是:
static int  net_olddevs_init(void)

---->
static void  (int )

点击(此处)折叠或打开

  1.  282static void __init ethif_probe2(int unit)
  2.  283{
  3.  284 unsigned long base_addr = netdev_boot_base("eth", unit);
  4.  285
  5.  286 if (base_addr == 1)
  6.  287 return;
  7.  288
  8.  289 (void)( probe_list2(unit, m68k_probes, base_addr == 0) &&
  9.  290 probe_list2(unit, eisa_probes, base_addr == 0) &&
  10.  291 probe_list2(unit, mca_probes, base_addr == 0) &&
  11.  292 probe_list2(unit, isa_probes, base_addr == 0) &&
  12.  293 probe_list2(unit, parport_probes, base_addr == 0));
  13.  294}

可以看到这个地方是遍历所有的总线的对应数组,不管有没有这种总线存在。我们这的情况,虽然没有ISA总线,虽然我们的网卡没有直接连到ISA总线上,按照上面的说法,只要让我们的probe函数被调用了就行,
哪怕放在PCI总线, eisa总线,的对应数组中,都是可以的,甚至可以创建一个数组,里面放上我们的cs89x0_probe()这个函数,就可以了。


好了,现在知道了,我们的开发板的probe函数就是使用ISA对应的数组来调用到的。下面就看probe函数的本身实现了。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

前面提到过,probe函数中要把系统的资源告诉内核,(就是吧net_device丰满一下,然后提交到内核去),其实际的函数函数是cs89x0_probe1,这里处理的函数cs89x0_probe只是准备下参数而已。



probe函数的主要功能是:http://blog.chinaunix.net/uid-28708203-id-3785215.html
0,检测网卡是否存在
1,映射网卡I/O资源。 0和1其实算作一步
2,申请中断(如果需要,一般都是在open中申请)
3,申请DMA,(如果需要,一般都是在open中申请)
4,提交体积





******************************************************************************************************************************************************

下面我们需要详细讲一讲上面提到的网卡I/O资源映射这件事:
http://blog.chinaunix.net/uid-28708203-id-3793252.html
使用网卡的I/O资源有两种方式,把他映射到I/O地址空间或者映射到内存地址空间。
这边是ARM,所以我们只能映射到内存地址空间。其有两种方式:动态映射,和静态映射,
动态映射往往是在cs89x0_probe函数中调用函数ioremap()函数来把物理内存映射为内核地址空间的虚拟地址。
而静态映射是在内核启动的时候,统一映射所有的外设的I/O外存空间。不知道内核启动时候的映射,后期系统运行过程中还能不能更改???


http://blog.chinaunix.net/uid-28708203-id-3791175.html
http://blog.chinaunix.net/uid-28708203-id-3791177.html
这两篇blog讲的相当透彻,不再罗嗦了。

韦东山的书上使用的是动态映射这种方式。
网上搜到的大量的移植文档,是采用的静态映射这种方式。


******************************************************************************************************************************************************




arch/arm/mach-s3c2440/mach-smdk2440.c
static struct  []  = {

在这个数组中添加内容:
,{ 
        // support cs8900
         
             .virtual     = vSMDK2410_ETH_IO,        // virtural addr that will be remapped 
          
            .pfn          = __phys_to_pfn(S3C2410_CS3 + (1<<24)), 
          
            .length      = SZ_1M, 
          
            .type          = MT_DEVICE, 
 
}

或者是这么个格式
{vSMDK2410_ETH_IO, 
0x19000000, 
SZ_1M, 
MT_DEVICE}

 

这个数组是下面函数调用的:  
 (, ());

  
这个功能是把 物理地址 0x19000000映射到虚拟地址 vSMDK2410_ETH_IO 这个虚拟地址上去。 


****************************************************************************************************************************************************** 
物理地址是这个的原因: 网卡已经焊接到板子上了,线路已经了连好了,就好比是RAM是分配了0x30000000 ~ 0x34000000这段物理地址空间。
网卡被分配给了19000000,这个地址是从电路图得出来的:
我们要判断某一个功能芯片是连接到了CPU哪个区域(物理地址空间),应该从CPU芯片的一看起。
首先我们的cpu物理地址空间是 128MB×8=1024MB
分为8个区域nGCS0-7。我们通过cpu出来的引脚 哪个连到 功能芯片上,来判断我们的功能芯片连到了CPU的哪个区域。
看电路图上 CPU的引脚 
 
nGCS0--------------nGCS0
 
 



































nGCS1--------------nGCS1
 
nGCS2--------------nGCS2
 
nGCS3--------------nLAN_CS
 
nGCS4--------------nGCS4
 
nGCS5--------------nGCS5
 

然后看CS8900A的引脚,有一个
nCLIPSLE------------nLAN_CS
 
那么证明网卡是连到第四个区域了,nGCS3的起始地址是18000000。
 
我们再看下地址线,由于只有128MB的地址空间,所有有效的地址线就是 27条。网卡的起始地址如何确定出是 19000000???
 
看下虚拟地址vSMDK2410_ETH_IO
******************************************************************************************************************************************************



------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ok,现在分析下probe的具体实现:


static int  net_olddevs_init(void)
        ---->static void  (int )
                  ---> (, ,  == 0)
 --->struct net_device *  (int )
 
 
 
  
struct net_device *  (int )
这个函数真的仅仅的是一个参数准备函数,重头戏在
static int  (struct net_device *dev, int , int )

这里有个好奇,既然我们的ARM中是只能使用“把网卡I/O资源映射到内存地址空间”,probe1中针对某一个端口地址,进行检测。
检测哪几个端口,是由数组netcard_portlist决定的。数组有几个成员,就调用几次 probe1。 原因是:
这个代码是针对X86来写的,X86使用的是I/O地址空间的方式,外设的I/O资源需要映射到I/O地址空间中去,但是他不是说地址空间的任意
值都可以,只能映射到有限的几个地址(开始)处。

这有限个,就是数组的成员。

这里,我既然是ARM的,明显的就不用检测了,我们不使用这些端口,这个机制只适用于X86。我们通过上面两种方式,把网卡的I/O资源映射到
内存地址空间。
但是probe1函数还是要执行,因为他不仅仅是探测,确定 I/O地址空间。也进行了其他一些操作。

韦东山那边,他是在probe函数中,控制了对netcard_portlist数组的使用,因为我们开发板什么布局我们已经知道了,不需要探测,直接映射就好。


那第二种方式,静态映射网卡I/O资源到内存地址空间的方式。移植的教程中都没有修改cs89x0.c,那么也就是说,内核还是会探测那么多个端口地址。
估计探测不出来也就作罢。我们下一步,还是去看看怎么使用的这些个地址。往下走吧。
 
 
 
 
 
 
 
 
 






阅读(550) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~