如下,注册了ra305x_eth_netdev1,关联ra305x_eth_sc1方法,ra305x_eth_sc1定义时关联了eth_drv_funs。if_ra305x_init将在cyg_net_init_devs中被调用。if_ra305x_init初始化时调用ra305x_init,其中调用cyg_drv_interrupt_create注册了中断处理函数ra305x_isr和ra305x_dsr。至此,中断处理,物理设备处理,逻辑设备处理关联已经完成。
/* 设备定义,定义一个全局变量 */
#define ETH_DRV_SC(sc,priv,name,start,stop,control,can_send,send,recv,deliver,poll,int_vector) \
static void start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags); \
static void stop(struct eth_drv_sc *sc); \
static int control(struct eth_drv_sc *sc, unsigned long key, void *data, int data_length); \
static int can_send(struct eth_drv_sc *sc); \
static void send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total, unsigned long key); \
static void recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len); \
static void deliver(struct eth_drv_sc *sc); \
static void poll(struct eth_drv_sc *sc); \
static int int_vector(struct eth_drv_sc *sc); \
static struct eth_hwr_funs sc##_funs = { \
start, \
stop, \
control, \
can_send, \
send, \
recv, \
deliver, \
poll, \
int_vector, \
ð_drv_funs, \ //关联了通用逻辑设备方法
(struct eth_drv_funs *)0 }; \
struct eth_drv_sc sc = {&sc##_funs, priv, name};
// 通用逻辑设备方法注册
struct eth_drv_funs eth_drv_funs = {eth_drv_init, eth_drv_recv, eth_drv_tx_done};
// 物理设备方法注册
ETH_DRV_SC(ra305x_eth_sc1,
&ra305x_eth1_priv_data, /* Driver specific data */
CYGDAT_DEVS_ETH_MIPS_RA305X_ETH1_NAME, /* Name of device */
if_ra305x_start,
if_ra305x_stop,
if_ra305x_ioctl,
if_ra305x_cansend,
if_ra305x_send,
if_ra305x_recv,
if_ra305x_deliver,
if_ra305x_poll,
if_ra305x_intvector);
// 初始化
NETDEVTAB_ENTRY(ra305x_eth_netdev1,
"ra305x_" CYGDAT_DEVS_ETH_MIPS_RA305X_ETH1_NAME,
if_ra305x_init,
&ra305x_eth_sc1);
// 物理设备中断处理方法注册
cyg_drv_interrupt_create(pra305x->vector,
0, /* Priority */
(CYG_ADDRWORD) pra305x, /* interupt context */
ra305x_isr, /* ISR function */
ra305x_dsr, /* DSR function */
&pra305x->int_hdl, /* interrupt handle */
&pra305x->int_obj); /* interrupt object */
ra305x_dsr
eth_drv_funs
ecos_synch_eth_drv_dsr
调cyg_flag_setbits( &alarm_flag, 2 );
唤醒Network alarm support线程
线程入口函数为alarm_thread
,发现alarm_flag标志为2,执行
eth_drv_run_deliveries
(*sc->funs->deliver)(sc)
,即执行if_ra305x_deliver
函数
ra305x_rxint
eth_drv_recv
通过(pifra305x->sc->funs->eth_drv->recv)()
调用
分配mbuf结构体
if_ra305x_recv
通过(sc->funs->recv)(sc, sg_list, sg_len)
调用物理设备的recv函数
拷贝数据
ether_input
ether_demux
这里会进行fastpath,数据包过滤。
然后调用schednetisr(NETISR_SNIFFER)
唤醒Network support线程进行协议栈处理。然后将数据包通过IF_ENQUEUE放入队列。
线程入口函数为cyg_netint
这里主要是协议栈处理,我们以ip协议为例,说下,如何调到ip_input的。
在in_proto.c里面的全局变量里注册了很多协议,这里截取部分
struct protosw inetsw[] = {
{ 0, &inetdomain, 0, 0,
0, 0, 0, 0,
0,
ip_init, 0, ip_slowtimo, ip_drain,
&nousrreqs
},
{ SOCK_DGRAM, &inetdomain, IPPROTO_UDP, PR_ATOMIC|PR_ADDR,
udp_input, 0, udp_ctlinput, ip_ctloutput,
0,
udp_init, 0, 0, 0,
&udp_usrreqs
},
{ SOCK_STREAM, &inetdomain, IPPROTO_TCP,
PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD,
tcp_input, 0, tcp_ctlinput, tcp_ctloutput,
0,
tcp_init, 0, tcp_slowtimo, tcp_drain,
&tcp_usrreqs
},
{ SOCK_RAW, &inetdomain, IPPROTO_RAW, PR_ATOMIC|PR_ADDR,
rip_input, 0, rip_ctlinput, rip_ctloutput,
0,
0, 0, 0, 0,
&rip_usrreqs
},
}
其中就注册了IP协议,初始化函数为ip_init,其中通过register_netisr(NETISR_IP, ipintr);
注册了网络的isr,ipintr中调用IF_DEQUEUE取出数据包,然后调用ip_input函数。