MTK eCos系统的有线驱动收包流程

驱动设备注册

如下,注册了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线程

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放入队列。

Network support线程处理

线程入口函数为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函数。

你可能感兴趣的:(协议)