linux协议栈pkt流程:http://blog.chinaunix.net/uid-22397896-id-3348984.html
1. 这是OS级别的,drv封装的时候注意如何满足这一层的需要。另外交给上层的时候注意选择哪种mode比较好。
2. tx与rx流程一样都是isr机制。
开头先插播《》中网卡:
1. 《》中使用CS8900A,TX2440A使用DM900芯片。《》中介绍了CS8900A功能: http://blog.csdn.net/npy_lp/article/details/6996479 这个链接解释了第二点等多个疑点
· 单芯片以太网解决方案:指单芯片支持PHY-MAC,最后能组装成封包。
· ??高效PacketPage??,支持DMA从模式在IO/存储空间运行。DMA(http://baike.baidu.com/subview/32471/5048463.htm)与CPU一样挂在内部高速bus上面,NIC如果使用DMA从模式会同共引脚挂到这个DMA控制器上,DMA得到CPU命令和bus控制权之后负责把设备的RAM中资料搬运到内存(DRAM)中。注意图中HOLD/HLDA是CPU通过bus给DMAC的(如何使用总线发DMA请求还要再看???)。之所以选择DMA模式主要是解放CPU,不然NIC来包之后中断CPU,CPU需要自己亲自把data搬到ram中(见下面IO/存储空间方式),如果用这种方式CPU只需要给DMA一个命令,DMA自己负责搬运。
· 可以运行在IO或者存储空间(这个据上面连接的说法是用于设置CS8900A上面4KB RAM,而这个RAM又是用于设置CS8900A的reg)(A0~15是地址,D0~15是DATA)(这个主要看CPU如何管理空间的,有前面mem controller知道这个外设的空间管理是mem controller做的,详见前述)。
CPU & 网卡 通信三个方式(http://os.51cto.com/art/200912/170454.htm):编进统一地址空间或者IO(使用A0~15,D0~15,CPU发送读命令+地址,网卡将data给RAM,这种方式需要CPU发送指令从网卡的IO空间拷贝到总线的RAM上面);网卡DMA pkt到(这种方式见上述),完成后DMA interrupt CPU,CPU去RAM中取;共享内存,这个不太懂,估计是CPU把网卡的RAM当成一块RAM直接访问吧。
· 全双工:这个应该是指一边Tx pkt一边Rx pkt。这个是指网卡自己的能力,不是指网卡与CPU之间全双工,是指网卡与网络之间。
· 支持MAC层CSMA/CD能力,自动填充CRC。所以linux这边填充好报文就可以,这个要看下drv做法了。
· 可编程接收功能???
· 流传输降低CPU负荷:估计是CPU按照drv写好pkt之后交给NIC就不用管了。
· DMA/片上RAM自动切换:片上RAM???
· 可早期中断结构先置处理???
· 自动抑制错误包:就是pkt error(如crc error)自动drop
· EEPROM支持无跳线配置:首先说有跳线的配置是指通过跳线(实际就是strappin方式)使用EEPROM auto download。无跳线配置估计是CPU上电时候自动拉高???
· Boot PROM支持无盘系统:首先说无盘系统是指没有硬盘,CPU启动时候进入的BIOS是自带ROM上面的,其中应该可以选择network boot。基本network boot过程是:CPU给NIC发送network boot命令,同时告知DMA过来的RAM地址;NIC中通过tftp方式(指定了IP)向网络上发送请求;通过tftp将image DMA到系统RAM中(还是在NIC的RAM中?估计这个不太可能呀,NIC RAM应该不会很大,而且NIC RAM CPU如何access到?);NIC给CPU发送完成信号,CPU从相应地址启动。所以在这里要注意:tftp方式传递过来的image大小有限制;Boot PROM这边的功能应该就是tftp download image的过程吧。
· 边界扫描 + 循环测试 ???
· LED:同我们的LED
· 省电模式
· 。。。
2. 软件驱动
· 驱动层次:
App Layer (类比user mode rtk API)
system call layer (类比kernel mode rtk API)
protocol agnostic layer (类比POSIX)
network protocl (比如app layer调用ping命令,这边就要按照片ping的过程调用 icmp protocl等,最后返回结果。实际包括TCP、UDP、IP)
device agnostic interface(类比DAL)
device driver (类比HAL)
hardware
linux中本来就有driver:driver/net/cs89x0.c
· demo board 连线图:
看出:
这里将CS8900A当作IO外设
CS8900A访问基地址:cGCS3=1,ADDR24=1,ADDR25/26没有使用。注意nGCS3低电平有效,看样子ADDR24是高电平有效(所以bit=1),注意nGCS3已经经过mem controller变换了,不要简单想成地址。所以这里CPU发出的BASE ADDR是:bank3地址(0x1800_0000)+不careADDR25/26(0x01FF_FFFF)+ADDR24=1(0x01xx_xxxx) = 0x1900_0000
字节使能信号nWAIT + nBE1。其中IOCHRDY是标志IO channel ready,参考datasheet,高表示IO ready了。链接nWAIT是CPU用于外设IO的引脚使能吧???
《》中nSBHE = 0时候表示SD8~15有效,=1时候表示0~7有效。为什么这么设计?貌似是因为网络数据是1B这样发送与接收的,这样发来1B就传走,中间不需要buffer了。注意与DMA方式对比。但是后面关于“nBE1”叙述不懂了???
中断pin脚:CPU上中断pin脚使用如图,这个还要再看???CS8900A使用int引脚是INTRQ3,参考datasheet。
· 驱动程序:driver/net/cs89x0.c
probe函数cs89x0_probe:
这个文件既可以编译进kernel(cs89x0_probe),也可以被编译进LKM(init_module),类比SDK既可以编译进kernel,也可以被编译进user mode。
有时候感觉中文书真是,乱自定义名词,例如《》中“枚举CS8900A”、“枚举函数”。其实就是通过读取外设的chip type和chip version来判断是不是CS8900A。
code流程见《》,注意:定义部分包括 物理BASE ADDR,虚拟地址,中断号。
ioremap 需要将0x19000000这个物理地址转换为虚拟地址,貌似调用一下这个func就好》???ioremap & iounremap
设置bank3:data总线宽度16,使能nWAIT(看来这个是mem controller自己的信号),使能UB/LB???调整时间参数,这个是给外设(网卡)使用的。这其中访问reg的方式与看到的一样,只不过这里写的裸体code
注册中断处理函数:
这个文件的net_open L1293
内核配置文件修改:
make menuconfig:
· 最后还有:
make kernel,这时kernel具有网络功能
其他的使用这个功能添加uboot命令,NFS,网络启动就是其他code了。
注意《》里面教的都是网卡工作在IO模式
好,下面说我们的NIC:从硬件上面看我们的NIC与网卡差很多,但是从软件上面看是一样的:都是NIC(DMA从模式)把pkt DMA到内存,linux driver都一样的。这里就用到网卡的DMA mode。
1. 先说swcore的NIC:其实NIC只是这个名字,只是搬运pkt而已
·4KEc通过DRAM特定pin脚线连接外挂DRAM,这个只是4KEc访问DRAM。外挂DRAM中跑code,这里面的linux自有自己的内存保存trap过来的pkt。
·4KEc与swcore并没有接口访问,clock差很多。看来果然话不投机半句多。
·swcore有多个MAC,其中连接CPU的MAC需要NIC(注意这时已经加CPUTAG了)。
·这边NIC所要做的只是简单的把pkt从swcore的SRAM放到DRAM,方式是DMA,看一下外挂的DRAM chip有助于了解。
2. 参看相关spec,可以了解:
· Normal port收pkt trap CPU:NP收到pkt放到SRAM,swcore决定pkt发包给CPU port时候,首先在CPU MAC+tag,然后经过CPU mac,片上NIC负责将pkt从SRAM发给DRAM,DMA方式,发送成功之后(讲座的时候听着是通过interrupt方式通知4KEc,但是难道是DRAM发送interrupt??看spec讲的是NIC TX的过程:4KEc写好pkt;NIC这边有空位子;4KEc写reg通知NIC取pkt;NIC通过DMA取走pkt交给swcore。)。然后linux就通过NIC drv把pkt收上来,这个过程网上应该有,一定要搞清楚。
· 系统初始化的时候:
CPU在DRAM中初始化好几个ring,每个ring采用wrap方式管理,每个entry指向一个header,header指向pkt(对于小于1532的非jambo pkt),header中有S/C own。
cpu将ring的首地址填写给reg,供NIC使用。
· NIC Tx pkt(过程不一定准确):NIC会检查是否有空闲ring(什么算空闲???),如果有就Tx给这个ring n个pkt,并设置wrap,设置S own。Tx时候会:填写header(包括cpu tag与S own???)+ 填写原始pkt。这里可以使用中断??
· CPU get pkt:CPU可以使用轮训或者中断。CPU取走pkt之后,会将ring中的entry清空,而且CPU一次就取走整个ring中的entry???
3. 所以总结一下:
上来的pkt会带cpu tag
NIC把pkt DMA到指定的ring中,CPU拿走,这个地址CPU事先设置好并填写给swcore。
################# 以上是IO/存储空间模式的NIC ##########################
################# 以下是swcore DMA模式的NIC #########################
1. 硬件连接:
internal CPU mode: swcore.CPU_MAC <--tx/rx--> NIC <--DMA--> DRAM
external CPU mode:
2. 内存中ring组织:
· 首先要注意申请连续mem空间(供DMA使用);cache flush。注意这里由于kmalloc限制,只申请了entry+header,后面cluster由swcore填在header,并sw通过ioremap方式获得virtual addr。
· 分配好的内存的首地址传递进来,根据这个地址,填充好:pNic_rxCDPIdx[i](ring当前指向entry idx)、pNic_rxRDPIdx[i](??)、填充每个entry指向header、填充wrap形成ring。最后sw使用的是pNic_rxCDPIdx、pNic_rxRDPIdx,就这两个。
3. 中断设置:
· 软件上需要:NIC DMA pkt之后中断通知CPU,包含三类中断:NIC tx 一条entry ok中断;NIC rx 接收一条entry ok中断;NIC tx时候发现获得invlad entry,就是ring 满了。每类中断需要告知那个ring。所以总共是21个bit,正好ISR机制可以传递32bit的参数(具体机制???),使用其中21bit,坐在ISR中断函数中dispatch。
· NIC tx ok interrupt --》 _nic_isr_rxRoutine(见spec流程图):???
修改s/c own;将entry组织起来形成结构;调用rx callback函数,这个callback函数还不是用户的,而是drv的,任务就是把entry拷贝出来,(还没到 组织成linux中的skb)。
4. 线程组织:
· 一般都会开辟一个rx thread,;tx由用户自己来。
· 线程函数_nic_rx_pkt_process:while(1)循环:加锁;拿pkt(不拷贝);调用callback???这里还没搞懂是那个callback;free pkt(由这里free动作感觉这里涉及的pkt不是原始entry中的pkt了,cpy过一次了。entry拷贝到kernel空间,kernel 拷贝到user空间)。
5. init流程:
· 借助linux module init来初始化:1.设置相应reg。2.申请DMA空间,并按照步骤(2)整理。4.按照步骤(3)设置中断。
· 执行80_rx_register:probe。注册用户的callback函数。
· 执行80_rx_start:执行步骤(4)。让NIC开始真正的发包。
6. 收包流程:
7. 发包流程:
8. stop流程:
9. 销毁流程: