Chinaunix

标题: SkyEye硬件模拟平台,第三部分: 硬件仿真实现之四 [打印本页]

作者: 北在北方    时间: 2008-03-25 15:30
标题: SkyEye硬件模拟平台,第三部分: 硬件仿真实现之四
本系列文章的第三部分主要介绍了SkyEye硬件模拟平台的实现细节。主要内容包括SkyEye的总体设计、SkyEye的可扩
展框架、SkyEye的关键数据结构、SkyEye对各种CPU的模拟实现、SkyEye对各种外设的模拟实现、如何安装使用SkyEye以及如何扩展
SkyEye的仿真模块等。对SkyEye的深入了解,有助于对嵌入式硬件系统有更深入的认识,特别是对操作系统、驱动程序如何与嵌入式硬件系统进行交互
有更深刻的了解。
                       
      
1.1.6        SkyEye的网络模拟实现
                       
      
1.        RTL8019AS网络芯片模拟的构思和设计概述
                       
      

前网络在嵌入式系统中应用越来越广泛,通过为SkyEye增加虚拟以太网芯片设备,使SkyEye支持ethernet网络接口模拟。这样在SkyEye
硬件模拟平台上运行的操作系统能够与本地Linux主机进行网络通信,当然通过ipchains/iptables等包转发机制可以进一步支持直接跟
Internet通信。
                       
      
鉴于目前嵌入式设备中广泛使用了NE2K
10Base-T兼容网络芯片,其中RTL8019AS又是比较有代表性的一种,购买也比较方便,我们就决定模拟它。设计方案完全基于真实的
RTL8019AS(NE2000兼容,简称8019AS),但做了部份简化。简化掉的部分主要包括:
                       
      
                       
      
目前设计虚拟以太网芯片设备对简化的原则是:把虚拟网络芯片的驱动放到真实8019AS网络芯片上去,直接能用就可以了,目前还不能保证其它系统上的NE2K驱动能直接在SkyEye上用。
                       
      
2.        虚拟8019AS网络芯片原理
                       
      
SkyEye
本身是一个硬件开发板的模拟器。虚拟8019AS网络芯片是虚拟开发板上一个相对独立的外部设备,这个设备有自己的内部数据结构和操作函数,完成相应的功
能。但虚拟8019AS网络芯片对外的接口只是几个提供给SkyEye的API函数和它所占用的系统资源,如Memory map
Io和IRQ等。网络芯片驱动程序看到的只是8019AS的寄存器和它占用的系统中断号,这些寄存器地址位于SkyEye模拟的开发板中某一段IO地址空
间内,而SkyEye看到的是寄存器地址和虚拟8019AS网络芯片提供给SkyEye的API函数。如果运行在虚拟开发板上的网络芯片驱动程序读写这些
寄存器地址,那么SkyEye会截获这些读写操作,并把它们转换成对虚拟8019AS网络芯片API接口nic_read和nic_write函数的调
用,从而操作虚拟8019AS网络芯片,并收发数据。这个过程跟真实的硬件系统的逻辑操作是一致的。
                       
      
那么
SkyEye跟虚拟8019AS网络芯片交换数据包的同时,8019AS是如何跟主机进行通讯的呢?这是通过Host主机的Linux上安装的
tun/tap或vnet虚拟网络接口来实现的。tun/tap和vnet是Linux内核中的一个内核模块,它们模拟了一个简单的点对点网络环境,后文
会有进一步的说明。虚拟8019AS网络芯片的整体结构如图 0-1所示:
                       
      
                               
        
图 0-1 8019AS模拟结构图
                               
        

                       
      
                       
      
3.        虚拟8019AS网络芯片的内存结构
                       
      
SkyEye
模拟的虚拟8019AS网络芯片工作在8位模式下,网络芯片含有8K字节的RAM,地址为0x4000-0x5fff(指的是网络芯片上的存储地址,而不
是ISA总线的地址,是网络芯片工作用的存储器),每256个字节称为一页,共有64页。页的地址就是地址的高8位,页地址为0x00--0xff 。
                       
      

先看一下0x40-0x5f页,这8k的ram的一部分用来存放接收的数据包,一部分用来存储待发送的数据包,具体由驱动编写者自己决定。(一般发包只要
能容纳一个最大的以太网包就可以了,所以定义为0x40-0x45页,即0x4000-0x45ff,约1.5k。剩下的都用来收包)。按照8019AS
硬件规范手册上的规定,8位工作模式下只能使用4000-5fff,16位模式才能用到6000-7fff的RAM,所以我们还是以手册为准。
                       
      
                               
        
图 0-2 NE2K兼容网络芯片的RAM空间结构
                               
        

                       
      
                       
      

看一下第0页,也就是图 0
6中的PROM,PROM的内容是网络芯片在上电复位的时候从93C46里读出来的,其中0x00-0x0B(工作于8位DMA模式)用于存放本节点
MAC地址,奇偶地址内容是重复放置的。如:MAC地址00 00 12 34 56 78存放在0x00-0x0B中为00 00 00 00 12
12 34 34 56 56 78
78,单地址和双地址的内容是重复的,一般使用偶数地址的内容,这主要是为了同时适应8位和16位的DMA。8019芯片外接一块93c46
eeprom,上电时自动从93c46里把MAC地址读入到PROM中,所以为虚拟网络芯片写驱动,只要在init函数中读PROM中的MAC地址,并写
入工作寄存器PAR0-PAR5就可以了。网络芯片工作时的地址判断依据就是这几个寄存器,与PROM及93c46无关。PROM的其它地址不能使用。值
得一提的是,虽然一般来说mac地址随便取一个就可以了,但要注意其最高字节不能是奇数,否则就是一个multicast
mac地址,以后的应用中会有问题。
                       
      
根据以上的分析,虚拟8019AS网络芯片要模拟的网络芯片内部RAM共两块:
                       
      
0x0000-0x000B,12字节,页号为0x00。存放MAC地址
                       
      
0x4000-0x5FFF,8192字节,页号为0x40-0x60(只用到0x5f,0x60为结束边界),用于存放收发的数据包缓冲,具体收发多少由驱动程序初始化决定。
                       
      
以上两块内存都是网络芯片的内部数据,不在系统的地址空间内,实际上SkyEye模拟的CPU是看不到这两块内存的,只能通过读写寄存器间接访问。
                       
      
4.        虚拟8019AS网络芯片的寄存器结构
                       
      
在RTL8019AS
或其它NE2k兼容的网络芯片中,软件对网络芯片内存的读写是通过一个数据寄存器(地址偏移0x10)进行的,方式是DMA,DMA的长度、起始地址等由
控制寄存器决定。而DMA又分为Remote DMA和Local DMA,首先解释一下这两种DMA:
                       
      Local DMA
            
以太网
            

网络芯片 RAM
          Remote DMA
            
网络芯片 RAM
            

host主机
         
                       
      
Local DMA是网络芯片自动收发数据到/从网络芯片的RAM,而Remote DMA是CPU主动从网络芯片的RAM读写数据到/从CPU的RAM。具体的读写其实可以分为三种:
                       
      
                       
      
这四个寄存器在init函数里初始化,以后有数据包到来时,网络芯片自动判断是否发给本机,是则用Local DMA存入数据,并自动修改读写指针。
                       
      
                               
        
图 0-3 与DMA有关的寄存器
                               
        

                       
      
                       
      
8019AS
的寄存器地址为0x00-0x1f,有page 0-3共4页,每页都以0x00-0x0f访问,但实际访问的是不同的寄存器。page
3里的寄存器属于8019专用,不是NE2K标准,并且不常用,所以不模拟了。我们的寄存器共3页,页号为0-2。此外还有两个寄存器,不属于任何页:
                       
      
                       
      
                               
        
表 0 1 8019AS寄存器
                               
        

                       
      
                       
      

面分别叙述虚拟8019AS网络芯片所模拟的各页中寄存器,如表 0
1所示。每个寄存器的各个bit位的具体含义可参考8019AS硬件规范手册,下面写出各寄存器的页内偏移地址,以及编写驱动时读写的常用值表示什么意
思,有助于理解。每个寄存器的各种写入值可以以"或"的关系运算后写入,R表示只读,W表示只写,R/W表示可以读也可以写:
                       
      
                               
        PAGE 0
                       
      
                       
      
                       
      
                               
        PAGE 1:
                       
      
                       
      
                       
      
                               
        PAGE 2:
                       
      
                       
      
                       
      
这页的寄存器大部分是只读的,可读出相关的配置信息等。
                       
      
5.        虚拟网络芯片接收数据包的方法
                       
      
在前面CR寄存器的说明中可以看到,普通的RTL8019从网络芯片RAM读数据到CPU有两种方式:
                       
      
1. 目前SkyEye虚拟网络芯片还不支持Remote DMA READ方式:
        
  硬件初始化时,BNRY读指针 = CURR写指针-1 =PSTART。
        
  有数据包要读时,操作步骤如下:
      
                       
      
a.查看bnry是否=CURR-1,不等则说明有数据包要读
        
  b.用bnry初始化DMA起址控制器RSAR0,1
        
  c 用18初始化DMA长度控制器RBCR0,1
        
  d.执行Remote DMA READ命令
        
  e.读出以太网包头(18字节),从包头中读出包长度
        
  f.同b-e读出所有数据
        
  g.调整bnry指针=CURR-1
        
  这期间如果bnry指到了缓冲环的尾部还要手工调整它回到环的开头。
      
                       
      
2.虚拟8019网络芯片支持更快更简单的SEND COMMAND方式,读数据包的步骤如下:
        
  硬件初始化时,BNRY = CURR = PSTART
        
  有数据包要读时,操作步骤如下:
        
  a.向RBCR1寄存器写入0FH(硬性规定)
        
   
    IOWRITE(R_RBCR1, 0x0f);
        
  b.执行SEND COMMAND命令
        
    IOWRITE(R_CR, CMD_PAGE0 | CMD_SEND | CMD_RUN)
        
     然后网络芯片自动做了如下工作:
        
        I. 用当前的BNRY读指针指向的地址写入DMA控制器(RSAR0,1)
        
        II.用以太网包头中的包长度初始化DMA控制器(RBCR0,1)
        
  c.先读18个字节的包头看看是否是合法的数据包
        
  d.从0x10端口读数据……。(读多少当然要你自己去看以太网包头了)
      
                       
      
6.        skyeye_ne2k.c函数说明
                       
      
                       
      
7.        tapif和vnet虚拟网络接口说明
                       
      
tun/tap设备和vnet设备为网络接口设备(struct net_device),被链接到网络接口链表中。一般在函数tun_set_iff()里创建和注册。
                       
      
8.        网络芯片驱动程序分析
                       
      
编写驱动程序时对DMA结束的判断的说明
cpu--->NIC's ram 的DMA结束标志是ISR_RDC中断:
while((char) (IOREAD(R_ISR) & ISR_RDC) == 0 );
这里是循环等待了,如果做得更好可以先返回,等待结束中断,一般没必要了。
                       
      
NIC'ram ---> network的DMA结束标志是ISR_PTX中断
如果上层软件还有包要连续发送,可以打开这个中断,然后在ISR中继续发下一个包。否则没必要处理这个中断,可以屏蔽它。(这就类似于串口UART的发送成功中断,如果要发一个字符串,就使用这个中断,只发送一个字符就没必要了。)
                       
      
在Linux系统的ne2k driver中也是死等一段时间,见ne2k.c中的代码:
                       
      
                       
              while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
                if (jiffies - dma_start > 2*HZ/100) {                /* 20ms */
                        printk("%s: timeout waiting for Tx RDC.\n", dev->name);
                        ne_reset_8390(dev);
                        NS8390_init(dev,1);
                        break;
                }
               
   
参考资料
                       
      
               
   
关于作者


                               
        
陈渝, 清华大学,通过
         
[email=yuchen@tsinghua.edu.cn?cc=d]yuchen@tsinghua.edu.cn[/email]
可以和他联系。
        
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/54500/showart_507678.html




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