技术积累BCM-SDK架构分析及源码移植-nios2平台移植

技术积累BCM-SDK架构分析及源码阅读

                                                                           ---北京华环电子 任晓亮 2016/01/09

希望:已经进入黑夜,黎明还会远吗?

经过两周的坚持不懈,SDK终于在Linux-V3.0版本编译通过。今天开始慢慢分析阅读源码。

一.SDK初始化前,需要对SDK的架构有所了解,具体如下图;可以看出SDK的代码结构是一个层次化分明的架构,这里对各层的作用和详细工作机制不阐述了,具体可以参见SDK的介绍文档。

   SDK代码的结构图

 

SDK根据上述架构,BCM模式启动的时候进行的初始化包括以下几个步骤:

1.           根据操作系统(linux、vxworks或unix等)不同调用sal_core_init()和sal_appl_init()两个函数的对应版本,分别对Core SAL和Appl SAL两部分进行初始化;

2.           linux系统下的sal_core_init()函数的主要工作时调用了函数

(1).sal_dpc_init()创建DPC(Deferred Procedure Call)的信号量和线程;(2).sal_appl_init()函数的linux版本则直接返回,没有做任何工作;

这两个函数虽然意义很大,但是值得我们研究的内容不多。

3.      然后调用sal_thread_create创建一个运行BCM模式的线程,并调用diag_shell()函数完成对BCM模式的数据进行初始化、命令行进行注册、设备探测和挂载、芯片初始化、客户命令注册、重启动和BCM模式退出等操作,主要通过调用diag_init()函数、sysconf_init()函数、diag_rc_set()函数、sysconf_probe()函数、sysconf_attach()函数、bcm_init()函数、custom_cmd()和sal_reboot()等函数实现,下面详细介绍下该函数的执行流程;

a.      diag_init()调用cmdlist_init()函数、init_symtab()函数、sal_srand()函数、gvar_init()函数和sh_bg_init()函数等来完成命令行注册、芯片的寄存器和表项软件数据内存分配、随机数种子获取、全局变量初始化和所有设备可执行任务的内存分配(最多10条)和记录等工作;

b.      sysconf_init()函数除了初始化管理接口的调式函数外还调用soc_cm_init()函数来完成SOC的配置的管理接口的初始化;

c.      sysconf_probe()函数调用bde_create()函数和sysconf_chip_override()函数完成探测已经挂载的设备并建立对应的配置管理项,包括为每个设备的分配id等工作;

d.      然后对每个unit调用sysconf_attach()函数来对soc_cm_device_init ()初始的管理接口的设备挂载一些中断处理函数,注册PCI读写函数等,用管理接口的结构体的指针函数成员形式保存,以便可以删除和添加这些处理函数,并调用soc_cm_device_init()函数通过在里面再调用soc_attach()函数来对每一个unit建立并初始化芯片的soc_control_t structure信息及对其访问的互斥体;soc_attach()函数调用soc_feature_init函数、soc_intr_disable()函、soc_cmic_uc_msg_start函数、soc_info_config()函数(这个函数下面会继续调用)、soc_dcb_unit_init()函数和soc_counter_verify()函数分别进行支持特性赋值、关闭中断、开启对设备的CMIC的UC信息、soc信息初始化、CPU收发包缓存DCB初始化和各种counter寄存器软件记录特定初始化,并对SOC_CONTROL(unit)和SOC_PERSIST(unit)两个保存芯片设备信息的结构体一些成员进行赋值;

f.       然后对每个芯片调用bcm_init()函数开始芯片的初始化工作,其首先调用bcm_attach()函数对BCM_CONTROL(unit)信息的部分成员进行赋值,包括设备类型、设备名称和unit号等;然后调用_bcm_api_xlate_port_init()函数建立lport和bcm port的映射关系;并调用芯片各功能模块的初始化函数(trident是bcm_esw_init ()函数)来对各模块进行初始化;

g.      然后调用custom_cmd()函数加载BCM模式下用户配置的命令加载进去;

h.      这样整个SDK就初始化完毕,BCM模式就会提示BCM>等来等待用户输入命令;然后进入一个死循环一直调用sh_process()函数解析用户配置的命令,然后调用对应的SDK接口下发到驱动;

i.        如果用户输入退出命令,会调用sh_exit函数来处理,包括可选的是否回收已经分配的资源等任务;

j.        如果用户输入重启的命令则调用sal_reboot()函数linux版本是通过exit(0)实现。

 

a.      首先调用soc_reset_init()函数,ESW????????芯片里这个函数调用soc_do_init()函数来完事情;soc_do_init()函数会根据是否是重启动设备进行的配置不一样;

(1)    如果是热启动的设备则先调用soc_dma_abort()关闭所有DMA并调用soc_linkscan_config()函数设置CMIC(CPU Management InterfaceController)查询端口link状态,如果设置项为空则表示关闭端口link状态扫描;然后如果是初始化soc有失败标记的话调用soc_dma_abort()函数、soc_counter_stop()函数、soc_mem_scan_stop函数、soc_i2c_detach()函数和soc_l2x_stop()函数(有些其他芯片还调用soc_cmic_uc_msg_stop函数等)分别禁止所有的中断、禁止计数行为、禁止内存扫描动作、释放I2C 驱动内存、结束L2X(应该是用于mac地址学习和老化对CPU进行中断通知)相关线程和停止等;

然后调用soc_info_config()函数来初始化芯片端口的各种信息,包括芯片型号、各种类型端口的位图、芯片称号、mod数目、端口数目、hg口的位置、堆叠口位置、CPU口队列数目、用于时间同步端口数目、端口最大支持速率、meter pools、入端口QOS支持的队列数目等信息,另外对trident芯片支持QOS三级调度,所以还会调用soc_trident_num_cosq_init()对各个端口支持的队列数做特殊初始化,最后调用soc_esw_dport_init()函数对User to physical port map的映射及对user port的逆映射;

总之soc_reset_init()函数偏重于对芯片信息、端口属性和QOS队列属性等初始化;然后调用soc_feature_init()函数和soc_dcb_unit_init()函数完成芯片特性支持添加和CPU收发包缓存DCB的初始化工作;

然后调用soc_dma_attach()函数和soc_dma_init()函数对中断进行重新初始化,然后对通过PCI设置CMIC_CONFIG使能高级的DMA模式,包括Scatter/gather, reload, andunaligned transfers(这里具体含义不太明白),然后开启一些中断;

(2)    在不是热启动的情况下,会首先调用调用soc_info_config()函数、soc_feature_init()函数和soc_dcb_unit_init()函数来完成信么MMU、芯片特性支持和DCB初始化工作;

然后调用soc_endian_config() 函数和soc_pci_burst_enable()函数来完成硬件大小端和支持PCI读写突发情形的使能;

然后是调用soc_reset()函数来完成对芯片的一些配置,包括端口的phy配置和mac配置(比如寄存器有XLPORT_XMAC_CONTROL),及还会调用相应芯片的soc_reset_bcm56840_a0()函数完成对CPU口和出入方向属性的一些配置,如CMIC_XGXS1_PLL_CONTROL_*、CMIC_MISC_CONTROL、CMIC_SOFT_RESET_REG、ING_CONFIG_2、EGR_CONFIG_2、ING_Q_BEGIN和EGR_Q_BEGIN等寄存器;然后和热启动一样,通过PCI设置CMIC_CONFIG使能高级的DMA模式,对MAC_CTRL寄存器读写配置一些MAC层的收发使能就退出了soc_do_init()函数;

b.      然后调用soc_misc_init()函数对芯片的初始化信息进行核实判断,最终根据函数指针调用芯片相应的函数,trident调用的则是_soc_trident_misc_init()函数;_soc_trident_misc_init()函数首先_soc_trident_ser_init()函数对IFP、EFP、VFP和UDF等tcam表项的表项大小、起始地址等信息进行软件获取并记录,然后调用_soc_trident_clear_all_memory函数对CPU_COS_MAP_ONLY、FP_GLOBAL_MASK_TCAM、FP_GM_FIELDS、FP_TCAM、FP_UDF_TCAM、L2_USER_ENTRY_ONLY、L3_DEFIP_128_ONLY、L3_DEFIP_ONLY、L3_TUNNEL、MY_STATION_TCAM_ENTRY_ONLY、VFP_TCAM、VLAN_SUBNET_ONLY、EFP_TCAM、FP_GLOBAL_MASK_TCAM_Xm、FP_GLOBAL_MASK_TCAM_Ym、L3_ECMP_XM、L3_ECMP_YM、EGR_IPMC_CFG2、EGR_VLAN_CONTROL_1、_XLPORT_MIB_RESET等表项进行清空;然后_soc_trident_misc_init()函数继续对CPU_PBM、CPU_PBM_2m、ISBS_PORT_TO_PIPE_MAPPINGm、EGR_ING_PORTm、XLPORT_CONFIGr、XLPORT_MODE_REG、IARB_MAIN_TDMm、EGR_PERQ_XMT_COUNTERS_BASE_ADDR、MISCCONFIG、ING_BYPASS_CTRL、EGR_BYPASS_CTRL、EGR_ENABLE、EPC_LINK_BMAP、ING_CONFIG_64、EGR_CONFIG_1、EGR_VLAN_CONTROL_1、ING_EN_EFILTER_BITMAP、SW2_FP_DST_ACTION_CONTROL、RTAG7_FLOW_BASED_HASH、RTAG7_HASH_ECMP、CMIC_I2C_STAT、CMIC_RATE_ADJUST_I2C、CMIC_RATE_ADJUST_INT_MDIO等寄存器或表项进行初始化赋值操作,并调用_trident_ledup_init对端口进行点灯操作,还调用_soc_trident_fcoe_config_init对芯片的FCOE功能进行初始化;

c.      然后调用soc_mmu_init()函数对MMU进行初始化,和soc_misc_init()函数一样,也是根据不同的芯片挂载不同的函数指针,这里会调用_soc_trident_mmu_init()函数对trident芯片的MMU进行初始化;包括GH、PG、SSP、SP、Port Min、PORT_MAX_SHARED_CELL、Queue Min等的划分,MMU port到phy port的映,及MCQ_CONFIG、OP_THR_CONFIG、OP_VOQ_PORT_CONFIG、OVQ_DROP_THRESHOLD0、OVQ_DROP_THRESHOLD_RESET_LIMIT、OVQ_FLOWCONTROL_THRESHOLD、OVQ_MCQ_CREDITS、MCQ_FIFO_BASE_REG、PORT_PAUSE_ENABLE0_64、INPUT_PORT_RX_ENABLE0_64、S3_CONFIG、S2_CONFIG、S2_S3_ROUTING等voq和Qos相关功能的MMU相关寄存器初始化;

d.      然后调用soc_l2x_start函数开启对MAC地址学习和老化的信息通知功能,主要是创建一个线程;

e.      然后调用bcm_init()函数对芯片进一步初始化,实际对trident芯片调用的是bcm_esw_init()函数,该函数再调用_bcm_esw_init()函数,该函数主要的是分别调用bcm_esw_linkscan_enable_set()函数、_bcm_modules_init()函数和bcm_esw_rcpu_init()函数,来实现关闭端口状态扫描、初始化芯片各个模块、初始化RCPU机制的主控模块:然后_bcm_esw_init()函数调用_bcm_esw_switch_init()函数来实现对CPU队列的初始化和对芯片的一些特殊控制信息,主要是通过调用bcm_esw_switch_rcpu_encap_priority_map_set()函数和bcm_esw_switch_control_set()函数来设置的。其中的_bcm_modules_init()函数调用芯片转发流程的各个模块的初始化函数,具体如下图:

        

 

此处内容较多但是非常重要,希望感兴趣的同学能查看对应代码实际学习下相关内容,只提一点,bcm_esw_l2_init函数会调用_bcm_l2_bpdu_init函数对l2_user_etry表项设置BPDU报文上CPU的规则;

f.       然后对unit的每个端口调用bcm_port_stp_set()函数、bcm_port_autoneg_set()函数和bcm_stat_clear()函数分别设置端口的STP的状态为转发、是否自动协商和清楚端口统计;

g.      然后调用bcm_linkscan_enable_set函数来定期查询端口的link状态;

h.      部分芯片还会调用bcm_linkscan_register注册trunk口的link状态查询回调函数;

 

 

SDK各个模块之间的关系:

Broadcom提供的sdk软件包包括了broadcom公司的交换芯片、phy芯片、cpu等芯片的驱动程序、器件操作接口、应用层接口;如下图所示:

 


对于bcm的交换芯片sdk包,主要模块有:

用户应用程序:用户自由定制的应用系统,通过sdk提供的接口控制芯片。

BCMX API:为用户应用程序提供的通用接口,不区分芯片,以芯片提供的业务功能为粒度。

BCM API: 驱动级接口,提供芯片各种读写控制接口,可以由用户应用程序调用,设置特定、读取寄存器,或查询芯片信息;

   BCMX API是对BCM API进行了下封装,一般的应用直接使用BCM API就可以;

 

BCM SDK支持的芯片比较多,使用时需要确定自己用的芯片是哪个系列的,BCM API接口函数在dispath中使用下面方式对应到芯片的类型的操作入口,

#defineBCM_DLIST_ENTRY(_dtype)

bcm_##_dtype##_auth_mac_add,

static int(*_auth_mac_add_dispatch[])(

    int unit,

    int port,

    bcm_mac_t mac) =

{

#include<bcm_int/bcm_dlist.h>

0

};

##_dtype##:##_dtype##为芯片系列类型,如robo系列_dtype==robo;

 

芯片功能使用比较简单可靠的方式是参考srcappldiagcmdlist.c,在sdkincludesocdefs.h定义了对某些命令功能的支持。文件中对应芯片类型的命令处理列表,里面有芯片功能相关的命令行说明及处理。

 

   Sdk如果不进行裁剪进行编译时默认支持所有芯片,在sdk目录下的make子目录中的make文件进行设置,可以过滤掉不关心的器件。

   在系统启动初始化过程中通过调用sdk的初始化接口,完成交换芯片的初始化操作,系统初始化完成后,通过用户应用程序调用BCMX api或者BCM api接口进行业务的控制操作。

 

命令定义,添加在:Cmdlist.c

芯片支持宏定义:defs.h

Insmod 入口在,gmodule.c

 

内核学习调试宏:gmodule.h

/************add by renxl****************/

//#define __KDEBUG__  

#ifdef __KDEBUG__ 

#define REN_KDEBUG(level, format, ...)  printk("[%s|%5d|%s] "format,level,__LINE__, __func__,##__VA_ARGS__ )

#else 

#define REN_KDEBUG(format,...) 

#endif

用户态调试学习宏开关:

/************add by renxl****************/

#define __DEBUG__  

#ifdef __DEBUG__ 

#define REN_DEBUG(level, format, ...)  printf("[%s|%5d|%s] "format,level,__LINE__, __func__,##__VA_ARGS__ )

#else 

#define REN_DEBUG(format,...) 

#endif

函数执行流程:

用户接口:bcm.user.proxy  入口bcm-diag-proxy.c:main.o 726,

文件关联:bcm-diag-proxy.c çè/usr/share/linux-uk-proxy.c

默认无参数调用:

1.      _kernel_fd_attach(intinput_fd, int output_fd) 583 :打开内核设备接口,通知内核创建服务,函数指针赋值。

a.调用:linux_uk_proxy_open()589,->源文件usr/share/linux-uk-proxy.c:58行,打开内核模块linux-uk-proxy.ko(设备号125)的设备接口:linux-uk-proxy(主设备号125,次设备号0,用命令:mknod /dev/linux-uk-proxy c 125 0) 在在文件内部记录文件号:staticint _dev_fd = -1;

b. linux_uk_proxy_service_create():602 –>源文件Linux-uk-proxy.c:84通知通过ioctl()和内核交互,创建输入输出内核服务线程。

c.     reader.ctrl.input_cb= (proxy_data_cb_t)_kernel_proxy_input_cb;

   reader.ctrl.output_cb = (proxy_data_cb_t)_fd_output_cb;

reader.ctrl.exit_cb= (proxy_data_cb_t)_kernel_proxy_input_exit_cb;

这些函数都在linux-uk-proxy.c中定义。

d. proxy_service_start(&reader.ctrl,1);启动线程:调用proxy-service.c里面的proxy_service_start(proxy_ctrl_t* ctrl, int fork),参数决定了创建分离线程或者是前台线程。

                   proxy_service_start(&reader.ctrl,1);分离线程

                   proxy_service_start(&writer.ctrl,0);前台线程:命令行就是在这里等待输入命令------

到此内核接口初始化完成------

3.            之后的所有交互都是基于kernel/modules/linux-uk-proxy.c

文件关联:usr/share/linux-uk-proxy.cçè/kernel/modules/linux-uk-proxy.c

模块linux-uk-proxy.ko函数结构体:

static gmodule_t_gmodule = {

    name: LUK_MODULE_NAME,

    major: LUK_DEVICE_MAJOR,

    init: _init,

    cleanup: _cleanup,

    pprint: _pprint,

    ioctl: _ioctl,

    open: NULL,

    close: NULL,

};

主要接口:用户接口 ========ioctl(int fd,unsigned int cmd, unsigned long arg)

                内核接口========_ioctl(unsigned int cmd, unsigned long arg)

         接口命令:linux-uk-proxy.h:

#define LUK_VERSION                  _IO(LUK_MAGIC,0)==版本查询

#define LUK_SERVICE_CREATE   _IO(LUK_MAGIC,1)==创建内核服务

#define LUK_SERVICE_DESTROY         _IO(LUK_MAGIC,2)==注销内核服务

#define LUK_SERVICE_RECV       _IO(LUK_MAGIC,3)==内核接收数据

#define LUK_SERVICE_SEND       _IO(LUK_MAGIC,4)==内核发送数据

#define LUK_SERVICE_SUSPEND         _IO(LUK_MAGIC,5)==挂起服务

#define LUK_SERVICE_RESUME _IO(LUK_MAGIC,6)==注册服务

4.            linux-bcm-diag-full.ko模块

当这个模块被插入到内核的时候,linux-bcm-diag-full模块的_init函数会执行(linux-bcm-diag-full.c=====416行)

         _init()函数调用module/uk-proxy/linux-uk-proxy.c里面的linux_uk_proxy_service_create()函数,创建内核proxy service.

         在调用sal_thread_create("bcm-shell",0, 0, _bcm_shell, 0);创建bcm-shell内核线程,处理接收到的命令

         _bcm_shell()在bcm-diag-full.c的280行,调用sal_core_init()?????初始化核心模块,

         Diag-shell()àsh_process(0, "BCM", TRUE);

5.            linux-user-bde.c 里面定义了使用linux驱动/dev/spi-dev1.0

SDK根据上述架构,BCM模式启动的时候进行的初始化包括以下几个步骤:

 

1.     根据操作系统(linux、vxworks或unix等)不同调用sal_core_init()和sal_appl_init()两个函数的对应版本,分别对Core SAL和Appl SAL两部分进行初始化;linux系统下的sal_core_init()函数的主要工作时调用了函数sal_dpc_init()创建DPC(Deferred Procedure Call)的信号量和线程;sal_appl_init()函数的linux版本则直接返回,没有做任何工作;这两个函数虽然意义很大,但是值得我们研究的内容不多。

 

2.     然后调用sal_thread_create创建一个运行BCM模式的线程,并调用diag_shell()函数完成对BCM模式的数据进行初始化、命令行进行注册、设备探测和挂载、芯片初始化、客户命令注册、重启动和BCM模式退出等操作,主要通过调用diag_init()函数、sysconf_init()函数、diag_rc_set()函数、sysconf_probe()函数、sysconf_attach()函数、bcm_init()函数、custom_cmd()和sal_reboot()等函数实现,下面详细介绍下该函数的执行流程;

 

a.     diag_init()调用cmdlist_init()函数、init_symtab()函数、sal_srand()函数、gvar_init()函数和sh_bg_init()函数等来完成命令行注册、芯片的寄存器和表项软件数据内存分配、随机数种子获取、全局变量初始化和所有设备可执行任务的内存分配(最多10条)和记录等工作;

 

b.     sysconf_init()函数除了初始化管理接口的调式函数外还调用soc_cm_init()函数来完成SOC的配置的管理接口的初始化;

 

c.     sysconf_probe()函数调用bde_create()函数和sysconf_chip_override()函数完成探测已经挂载的设备并建立对应的配置管理项,包括为每个设备的分配id等工作;

 

d.     然后对每个unit调用sysconf_attach()函数来对soc_cm_device_init ()初始的管理接口的设备挂载一些中断处理函数,注册PCI读写函数等,用管理接口的结构体的指针函数成员形式保存,以便可以删除和添加这些处理函数,并调用soc_cm_device_init()函数通过在里面再调用soc_attach()函数来对每一个unit建立并初始化芯片的soc_control_t structure信息及对其访问的互斥体;soc_attach()函数调用soc_feature_init函数、soc_intr_disable()函、soc_cmic_uc_msg_start函数、soc_info_config()函数(这个函数下面会继续调用)、soc_dcb_unit_init()函数和soc_counter_verify()函数分别进行支持特性赋值、关闭中断、开启对设备的CMIC的UC信息、soc信息初始化、CPU收发包缓存DCB初始化和各种counter寄存器软件记录特定初始化,并对SOC_CONTROL(unit)和SOC_PERSIST(unit)两个保存芯片设备信息的结构体一些成员进行赋值;

 

 

f.      然后对每个芯片调用bcm_init()函数开始芯片的初始化工作,其首先调用bcm_attach()函数对BCM_CONTROL(unit)信息的部分成员进行赋值,包括设备类型、设备名称和unit号等;然后调用_bcm_api_xlate_port_init()函数建立lport和bcm port的映射关系;并调用芯片各功能模块的初始化函数(trident是bcm_esw_init ()函数)来对各模块进行初始化;

 

g.     然后调用custom_cmd()函数加载BCM模式下用户配置的命令加载进去;

 

h.     这样整个SDK就初始化完毕,BCM模式就会提示BCM>等来等待用户输入命令;然后进入一个死循环一直调用sh_process()函数解析用户配置的命令,然后调用对应的SDK接口下发到驱动;

 

i.       如果用户输入退出命令,会调用sh_exit函数来处理,包括可选的是否回收已经分配的资源等任务;

 

j.       如果用户输入重启的命令则调用sal_reboot()函数linux版本是通过exit(0)实现。

 

 

 

 

a.     首先调用soc_reset_init()函数,ESW芯片里这个函数调用soc_do_init()函数来完事情;soc_do_init()函数会根据是否是重启动设备进行的配置不一样;

 

 

(2)   在不是热启动的情况下,会首先调用调用soc_info_config()函数、soc_feature_init()函数和soc_dcb_unit_init()函数来完成信么MMU、芯片特性支持和DCB初始化工作;然后调用soc_endian_config() 函数和soc_pci_burst_enable()函数来完成硬件大小端和支持PCI读写突发情形的使能;然后是调用soc_reset()函数来完成对芯片的一些配置,包括端口的phy配置和mac配置(比如寄存器有XLPORT_XMAC_CONTROL),及还会调用相应芯片的soc_reset_bcm56840_a0()函数完成对CPU口和出入方向属性的一些配置,如CMIC_XGXS1_PLL_CONTROL_*、CMIC_MISC_CONTROL、CMIC_SOFT_RESET_REG、ING_CONFIG_2、EGR_CONFIG_2、ING_Q_BEGIN和EGR_Q_BEGIN等寄存器;然后和热启动一样,通过PCI设置CMIC_CONFIG使能高级的DMA模式,对MAC_CTRL寄存器读写配置一些MAC层的收发使能就退出了soc_do_init()函数;

 

b.     然后调用soc_misc_init()函数对芯片的初始化信息进行核实判断,最终根据函数指针调用芯片相应的函数,trident调用的则是_soc_trident_misc_init()函数;_soc_trident_misc_init()函数首先_soc_trident_ser_init()函数对IFP、EFP、VFP和UDF等tcam表项的表项大小、起始地址等信息进行软件获取并记录,然后调用_soc_trident_clear_all_memory函数对CPU_COS_MAP_ONLY、FP_GLOBAL_MASK_TCAM、FP_GM_FIELDS、FP_TCAM、FP_UDF_TCAM、L2_USER_ENTRY_ONLY、L3_DEFIP_128_ONLY、L3_DEFIP_ONLY、L3_TUNNEL、MY_STATION_TCAM_ENTRY_ONLY、VFP_TCAM、VLAN_SUBNET_ONLY、EFP_TCAM、FP_GLOBAL_MASK_TCAM_Xm、FP_GLOBAL_MASK_TCAM_Ym、L3_ECMP_XM、L3_ECMP_YM、EGR_IPMC_CFG2、EGR_VLAN_CONTROL_1、_XLPORT_MIB_RESET等表项进行清空;然后_soc_trident_misc_init()函数继续对CPU_PBM、CPU_PBM_2m、ISBS_PORT_TO_PIPE_MAPPINGm、EGR_ING_PORTm、XLPORT_CONFIGr、XLPORT_MODE_REG、IARB_MAIN_TDMm、EGR_PERQ_XMT_COUNTERS_BASE_ADDR、MISCCONFIG、ING_BYPASS_CTRL、EGR_BYPASS_CTRL、EGR_ENABLE、EPC_LINK_BMAP、ING_CONFIG_64、EGR_CONFIG_1、EGR_VLAN_CONTROL_1、ING_EN_EFILTER_BITMAP、SW2_FP_DST_ACTION_CONTROL、RTAG7_FLOW_BASED_HASH、RTAG7_HASH_ECMP、CMIC_I2C_STAT、CMIC_RATE_ADJUST_I2C、CMIC_RATE_ADJUST_INT_MDIO等寄存器或表项进行初始化赋值操作,并调用_trident_ledup_init对端口进行点灯操作,还调用_soc_trident_fcoe_config_init对芯片的FCOE功能进行初始化;

 

c.     然后调用soc_mmu_init()函数对MMU进行初始化,和soc_misc_init()函数一样,也是根据不同的芯片挂载不同的函数指针,这里会调用_soc_trident_mmu_init()函数对trident芯片的MMU进行初始化;包括GH、PG、SSP、SP、Port Min、PORT_MAX_SHARED_CELL、Queue Min等的划分,MMU port到phy port的映,及MCQ_CONFIG、OP_THR_CONFIG、OP_VOQ_PORT_CONFIG、OVQ_DROP_THRESHOLD0、OVQ_DROP_THRESHOLD_RESET_LIMIT、OVQ_FLOWCONTROL_THRESHOLD、OVQ_MCQ_CREDITS、MCQ_FIFO_BASE_REG、PORT_PAUSE_ENABLE0_64、INPUT_PORT_RX_ENABLE0_64、S3_CONFIG、S2_CONFIG、S2_S3_ROUTING等voq和Qos相关功能的MMU相关寄存器初始化;

 

d.     然后调用soc_l2x_start函数开启对MAC地址学习和老化的信息通知功能,主要是创建一个线程;

 

e.     然后调用bcm_init()函数对芯片进一步初始化,实际对trident芯片调用的是bcm_esw_init()函数,该函数再调用_bcm_esw_init()函数,该函数主要的是分别调用bcm_esw_linkscan_enable_set()函数、_bcm_modules_init()函数和bcm_esw_rcpu_init()函数,来实现关闭端口状态扫描、初始化芯片各个模块、初始化RCPU机制的主控模块:然后_bcm_esw_init()函数调用_bcm_esw_switch_init()函数来实现对CPU队列的初始化和对芯片的一些特殊控制信息,主要是通过调用bcm_esw_switch_rcpu_encap_priority_map_set()函数和bcm_esw_switch_control_set()函数来设置的。其中的_bcm_modules_init()函数调用芯片转发流程的各个模块的初始化函数,具体如下图:

相关内容推荐