锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

23.从0学ARM-网卡DM9000及uboot协议栈详解

时间:2023-04-16 15:37:00 直接电缆连接gp3000h12f629集成电路集成电路icmp1411dh

第二十三章

一、网卡

1. 概念

网卡是一块被设计用来允许计算机在计算机网络上进行通讯的计算机硬件。由于其拥有MAC所以属于地址OSI第二层模型。它允许用户通过电缆或无线连接。

每个网卡都有一个叫做MAC地址独特的48位串行号写在卡上ROM在网络上的每一台计算机都必须有一个独特的MAC地址。没有两张生产的网卡有相同的地址。这是因为电气电子工程师协会(IEEE)负责为网络接口控制器(网卡)卖家分配唯一的MAC地址。

处理器和存储器安装在网卡上RAM和ROM)。网卡与局域网之间的通信通过电缆或双绞线串行传输。网卡与计算机之间的通信通过计算机主板I/O并行传输总线。

因此,网卡的一个重要功能是串行/并行转换。由于网络上的数据率与计算机总线上的数据率不同,网卡中必须安装缓存数据的存储芯片

网卡曾经作为扩展卡插入计算机总线,但由于其价格低廉,以太网标准普遍存在,大多数新计算机在主板上集成了网络接口。

这些主板要么在主板芯片中集成以太网功能,要么通过使用一块PCI (或更新PCI-Express连接到主板的廉价网卡。

除非需要多接口或其他类型的网络,否则不再需要独立的网卡。即使是更新的主板也可能包含内置的双网络(以太网)接口。

2. 主要功能

1.数据的包装和解封
在发送过程中,将上一层传输的数据添加到第一层和尾部,成为以太网的帧。在接收过程中,将以太网的帧剥离到第一层和尾部,然后发送到上一层

2、链路管理
主要是通过CSMA/CD(Carrier Sense Multiple Access with Collision Detection ,通过协议实现带冲突检测的载波监问)协议

3.数据编码和译码
也就是说,曼彻斯特编码和译码。曼彻斯特码,又称数字双向码、分相码或相位码(PE),它是物理层用来编码同步位流的时钟和数据的常用二元码线路编码方法之一。在通信技术中,用来表示要发送
比特 流中的数据与定时信号相结合。 常用在以太网通信,列车总线控制,工业总线等领域。

3. 分类

  1. 按总线接口类型划分
    一般可以根据网卡的总线接口类型进行bai为ISA接口网卡、PCI在服务器上使用的接口网卡和PCI-X笔记本电脑使用的网卡是总线接口类型的网卡PCMCIA接口类型。
  • (1)ISA总线网卡
  • (2)PCI总线网卡
  • (3)PCI-X总线网卡
  • (4)PCMCIA总线网卡
  • (5)USB总线接口网卡
  1. 按网络接口划分
    除网卡的总线接口类型外,我们还可以根据网卡的网络接口类型进行划分。网卡最终必须与网络连接,因此必须有一个接口,使网线通过其与其他计算机网络设备连接。不同的网络接口适用于不同类型的网络。目前,以太网是常见的接口RJ-45接口,细同轴电缆
    BNC接口和粗同轴电AUI接口、FDDI接口、ATM接口等。此外,一些网卡提供两种或多种接口,以适用于更广泛的应用环境。例如,一些网卡将同时提供RJ-45、BNC接口或AUI接口。
  • (1)RJ-45接口网卡
  • (2)BNC接口网卡
  • (3)AUI接口网卡
  • (4)FDDI接口网卡
  • (5)ATM接口网卡
  1. 按带宽划分
    随着网络技术的发展,网络带宽也在不断改进,但不同带宽的网卡应用环境也不同。目前,主流网卡主要有10张Mbps网卡、100Mbps以太网卡、10Mbps/100Mbps自适应网卡,10000Mbps四种千兆以太网卡。
  • (1)10Mbps网卡
  • (2)100Mbps网卡
  • (3)10Mbps/100Mbps网卡
  • (4)1000Mbps以太网卡

二、DM9000A

DM9000芯片是DAVICOM公司生产,DM9000A 它是一种完全集成的单芯片快速以太网控制器,性价比高,引脚少,带有通用处理器接口。

一个 10/100M PHY 和 4K 双字的 SRAM 。它是为低功耗和高性能而设计的 IO 端口支持 3.3V 与 5V 容限值。

DM9000A 提供适应各种处理器的服务 8 位、16 访问内部存储器的位数据接口。

DM9000A物理协议层接口完全支持使用 10MBps 下 3 类、4 类、5 类非屏蔽双绞线和 100MBps 下 5类非屏蔽双绞线。这完全符合要求 IEEE 802.3u 标准。

其自动协商功能将自动完成 DM9000AE配置使其发挥最佳性能。

它还支持 IEEE 802.3x 全双工流量控制。

1. 模块图

图1 DM9000内部结构框架

EEPROM Interface存放接口mac地址,Internal SRAM存储收发数据,MII部分把MAC部分与PHY部分连接通信,AUTO-MDIX自适应10/1000M网络,在物理层,MAC在PHY之下。

2. 引脚分析


(#:表示低电平有效)

开发板FS4412的网卡DM9000A连接到了SROM以下是数据线、地址线和信号线连接的分析

1) SD0~15

SD0~15: 16位数据线连接到引脚BUF_B_Xm0DATA[0:15],由CMD引脚决定了访问类型。

可见数据和地址线连接到SOC的XM0上。

数据线和信号线对应的SROMC引脚如上图所示。

2) CMD

 dm9000       外围电路             转换电路         soc    CMD--------BUF_B_Xm0ADDR2--------Xm0ADDR2-----Xm0ADDR2 

如下图所示:
CMD: 命令线,当CMD为高,表示SD 传输数据,CMD低表示地址传输,连接exynos4412的BUF_B_Xm0ADDR2上,可见CMD复用地址线Xm0ADDR2引脚。

3) IOR#、IOW#

 dm9000       外围电路         转换电路    soc    IOR--------BUF_Xm0OEn--------Xm0OEn-----Xm0OEn   IOW--------BUF_Xm0WEn--------Xm0WEn-----Xm0WEn  

4) CS#

 dm9000       外围电路         转换电路    soc 
  CS--------BUF_Xm0cs1--------Xm0cs1-----Xm0CSn1


CS#:片选,放在exynos4412的Bank1的片选上面,内存基地址是0x05000000。

我们的DM9000A是放在exynos4412的Bank1(0X05000000)的片选上面。

而DM9000的CMD引脚接在Bank1的LADDR2上面

读写DM9000A的地址
CMD拉低, 此时向0X05000000地址上读写的数据便是DM9000A的内部寄存器地址

读写DM9000A的数据
CMD拉高,此时向0X05000000+4地址上读写的数据便是DM9000A的数据

设置exynos4412的bank1的硬件位宽,时序,因为不同的硬件,涉及的数据收发都不同。

5) INT#

中断线DM9000_IRQ通过U8转接到引脚XEINT6

由上图可知中断引脚INT,接在exynos4412的GPX0_6脚上。
uboot中的DM9000A的驱动没有用到中断。

3. 复用GPIO引脚

XM0引脚复用了GPIO引脚,所以需要初始化对应的GPIO引脚来使能SROMC。

1) GPY0CON

2) GPY1CON
3)GPY3CON

4) GPY5CON

5) GPY6CON

三、SROM 控制器

1. 概念

SROM是高速存储器,Cache技术就是通过在DROM和CPU之间插入一小块SROM来减小CPU和存储之间的速度差异的。

EXYNOS 4412包含了SROM控制器,特性如下:

  • 外部 8/16位 NOR Flash/PROM/ SRAM memory.
  • 4组内存,每块内存最多16 MB

首先我们要初始化 exynos4412的 SROM 控制器,设置总线宽度和相关时序。

针对 SROM 控制器的每一个 bank 只有2 个寄存器: SROM_BW 和 SROM_BC

2. SROM_BW

在 SROM_BW 寄存器中,我们只关心与 bank1 相关的域。

上面分析过,
DM9000A 的 16 根数据线全部接在 exynos 4412的数据线上,所以 DataWidth1 设置为 1;
DM9000A 的地址是按字节存取的,所以 AddrMode1 设置为 1;
通过查看原理图,没有使用 Xm0WAITn和 Xm0BEn 引脚;
所以 WaitEnable1 和 ByteEnable1 均设置为 0。

SROM_BW[7:4]=0x3

3. SROM_BC1

SROM 控制器读时序和 DM9000A 的读时序主要通过SROM_BCn控制寄存器设置。

设置这些时序之前,首先来看DM9000A芯片手册时序图和exynos4412的时序图


详尽时序分析:,内存控制器使用HCLK作为时钟,在HCLK为100MHz时,1个clock大约为10ns。
信号值的设定如下:

信号 含义 最低时间(ns)
Tacs 地址发出后等多长时间发片选, DM9000AE 中 CS 和 CMD(地址)同时发出,所以 Tacs最低为0ns 0
Tcos 发出片选信号后等多长时间发出读使能信号(nOW、 IOR),在 DM9000A 的时序图上对应 T1,最小为 0 0
Tacc 读使能信号持续时间,access cycle ,读写使能后,多久才能访问数据,在 DM9000A 的时序图上对应 T2 10
Tcoh 当DM9000A的写信号取消后,数据线上的数据还需要至少3ns才消失(nOE读写取消后,片选需要维持多长时间)在 DM9000A 的时序图中对应 T4 3
Tcah 片选结束后,地址保存时间, DM9000A 中CS和cmd同时结束,所以 Tcah=0 0
Tacp 页模式,不管 0
PMC 页模式,不管 0

从DM9000A的读写时序图中可以看出,T2+T6实际上构成了DM9000A的一个访问周期,因此还需要满足:Tacs + Tcos + Tacc + Tcoh + Tcah>= T2+T6,最终使用下面的表达式来表达:
(Tacs >= 0 && Tacs <= 4) && (Tcos >= 0 && Tcos <= 4) && (Tacc >= 1 && Tacc <= 14 ) && (Tcoh >=1 && Tcoh <= 4 )

寄存器SROM_BCn (n = 0 to 3)定义如下:

故设置参考值为:

#define DM9000_Tacs (0x1) // address set-up
#define DM9000_Tcos (0x1) // chip selection set-up
#define DM9000_Tacc (0x5) // access cycle
#define DM9000_Tcoh (0x1) // chip selection hold
#define DM9000_Tah (0xC) // address holding time
#define DM9000_Tacp (0x9) // page mode access cycle
#define DM9000_PMC (0x1) // normal(1data)page mode configuration

4. SROM初始化

u-boot 已经自带了 DM9000系列网卡的驱动,在 u-boot 源码中的 driver/net/dm9000x.c 的有一段说明:

       06/03/2008	Remy Bohmer <linux@bohmer.net>
			- Fixed the driver to work with DM9000A.
			  (check on ISR receive status bit before reading the
			  FIFO as described in DM9000 programming guide and
			  application notes)
			- Added autodetect of databus width.
			- Made debug code compile again.
			- Adapt eth_send such that it matches the DM9000*
			  application notes. Needed to make it work properly
			  for DM9000A.
			- Adapted reset procedure to match DM9000 application
			  notes (i.e. double reset)
			- some minor code cleanups
			These changes are tested with DM9000{ 
        A,EP,E} together
			with a 200MHz Atmel AT91SAM9261 core

可见,2008年Remy Bohmer已经为 DM9000A 添加了驱动,但是我们仍然需要针对板子做一些修改。

前一章我们针对参考的fs4412开发板移植了DM9000A的驱动,下面我们来详细分析DM9000A驱动程序。

分析驱动涉及到以下几个文件:

arch/arm/lib/board.c
board/samsung/origen/origen.c
drivers/net/Dm9000x.c
drivers/net/Dm9000x.h
include/config_cmd_default.h
include/configs/origen.h
include/net.h
net/eth.c

5. 宏定义

在include/configs/origen.h中需要定义DM9000A基地址和编译的宏。
其中最重要的几个宏如下:

名称 说明
CONFIG_DM9000_BASE DM9000A 的基地址 0x05000000
DM9000_IO DM9000A 的 INDEX 端口地址 CONFIG_DM9000_BASE
DM9000_DATA DM9000A 的 DATA 端口地址 (CONFIG_DM9000_BASE + 4)
CONFIG_DRIVER_DM9000 Makefile中用于控制dm9000驱动是否编译 1
CONFIG_DM9000_USE_16BIT DM9000A数据宽度
CONFIG_DM9000_NO_SROM 表示没有使用SROM 1

其中DM9000_DATA 定义为基地址+0x4,刚好把 Xm0ADDR2 拉高,即把 CMD 拉高。

查看文件drivers/net/Makefile:
从 Makefile 得知,要把 DM9000A 的驱动编译进 u-boot中,需要定义 CONFIG_DRIVER_DM9000 这个宏。

宏定义如下:

#ifdef CONFIG_CMD_NET
#define CONFIG_NET_MULTI
#define CONFIG_DRIVER_DM9000 1
#define CONFIG_DM9000_BASE 0x05000000 
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE + 4)
#define CONFIG_DM9000_USE_16BIT
#define CONFIG_DM9000_NO_SROM 1
#define CONFIG_ETHADDR 11:22:33:44:55:66
#define CONFIG_IPADDR 192.168.6.187
#define CONFIG_SERVERIP 192.168.6.186
#define CONFIG_GATEWAYIP 192.168.6.1
#define CONFIG_NETMASK 255.255.255.0
#endif

除此以外我们还需要添加一些 u-boot 的命令,比如 ping 命令用来检查网络是否通畅,tftp用来下载文件。

uboot通过宏来控制是否编译这些命令,include/configs/origen.h定义了一些宏,但是有的是undefine,我们要打开它们。

/* Command definition*/
#include 

#define CONFIG_CMD_PING
#define CONFIG_CMD_ELF
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_MMC
#define CONFIG_CMD_FAT
#define CONFIG_CMD_NET
#undef CONFIG_CMD_NFS
#define CONFIG_CMD_HELLO
#define CONFIG_CMD_LEDA

除此之外头文件: u-boot-2013.01/include/config_cmd_all.h 也列出了一些可用的命令。

#define CONFIG_CMD_BDI /* bdinfo */
#define CONFIG_CMD_BOOTD /* bootd */
#define CONFIG_CMD_CONSOLE /* coninfo */
#define CONFIG_CMD_ECHO /* echo arguments */
#define CONFIG_CMD_EDITENV /* editenv */
#define CONFIG_CMD_FPGA /* FPGA configuration Support */
#define CONFIG_CMD_IMI /* iminfo */
#define CONFIG_CMD_ITEST /* Integer (and string) test */
#ifndef CONFIG_SYS_NO_FLASH
#define CONFIG_CMD_FLASH /* flinfo, erase, protect */
#define CONFIG_CMD_IMLS /* List all found images */
#endif
#define CONFIG_CMD_LOADB /* loadb */
#define CONFIG_CMD_LOADS /* loads */
#define CONFIG_CMD_MEMORY /* md mm nm mw cp cmp crc base loop mtest */
#define CONFIG_CMD_MISC /* Misc functions like sleep etc*/
#define CONFIG_CMD_NET /* bootp, tftpboot, rarpboot */
#define CONFIG_CMD_NFS /* NFS support */
#define CONFIG_CMD_RUN /* run command in env variable */
#define CONFIG_CMD_SAVEENV /* saveenv */
#define CONFIG_CMD_SETGETDCR /* DCR support on 4xx */
#define CONFIG_CMD_SOURCE /* "source" command support */
#define CONFIG_CMD_XIMG /* Load part of Multi Image */

6. 初始化srom

在arch/arm/lib/board.c的函数board_init_r中有如下代码:

void board_init_r(gd_t *id, ulong dest_addr)
{ 
        
	……
	board_init();	/* Setup chipselects */
	……
}

函数board_init()定义在board/samsung/origen/origen.c中,我们在该函数中添加了初始化srom代码:

int board_init(void)
{ 
        
	gpio1 = (struct exynos4_gpio_part1 *) EXYNOS4_GPIO_PART1_BASE;
	gpio2 = (struct exynos4_gpio_part2 *) EXYNOS4_GPIO_PART2_BASE;

	gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);

#ifdef CONFIG_DRIVER_DM9000
	dm9000aep_pre_init();
#endif
	return 0;
}

函数dm9000aep_pre_init用来设置 SROM 控制器。

static void dm9000aep_pre_init(void)
{ 
        
	unsigned int tmp;
	unsigned char smc_bank_num = 1;
	unsigned int     smc_bw_conf=0;
	unsigned int     smc_bc_conf=0;

	/* gpio configuration */
	writel(0x00220020, 0x11000000 + 0x120);//GPY0CON
	writel(0x00002222, 0x11000000 + 0x140);//GPY1CON
	/* 16 Bit bus width */
	writel(0x22222222, 0x11000000 + 0x180);//GPY3CON
	writel(0x0000FFFF, 0x11000000 + 0x188);//GPY3PUD
	writel(0x22222222, 0x11000000 + 0x1C0);//GPY5CON
	writel(0x0000FFFF, 0x11000000 + 0x1C8);//GPY5PUD
	writel(0x22222222, 0x11000000 + 0x1E0);//GPY6CON
	writel(0x0000FFFF, 0x11000000 + 0x1E8);//GPY6PUD
	              
	smc_bw_conf &= ~(0xf<<4);
	smc_bw_conf |= (1<<7) | (1<<6) | (1<<5) | (1<<4);
	smc_bc_conf = ((DM9000_Tacs << 28)
			| (DM9000_Tcos << 24)
			| (DM9000_Tacc << 16)
			| (DM9000_Tcoh << 12)
			| (DM9000_Tah << 8)
			| (DM9000_Tacp << 4)
			| (DM9000_PMC));
	exynos_config_sromc(smc_bank_num,smc_bw_conf,smc_bc_conf);
}
/* * exynos_config_sromc() - select the proper SROMC Bank and configure the * band width control and bank control registers * srom_bank - SROM * srom_bw_conf - SMC Band witdh reg configuration value * srom_bc_conf - SMC Bank Control reg configuration value */

void exynos_config_sromc(u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf)
{ 
        
	unsigned int tmp;
	struct exynos_sromc *srom = (struct exynos_sromc *)(EXYNOS4412_SROMC_BASE);

	/* Configure SMC_BW register to handle proper SROMC * bank */
	tmp = srom->bw;
	tmp &= ~(0xF << (srom_bank * 4));
	tmp |= srom_bw_conf;
	srom->bw = tmp;

	/* Configure SMC_BC * register */
	srom->bc[srom_bank] = srom_bc_conf;
}

四、DM9000A驱动分析

DM9000A所能支持的功能非常的多,驱动的实现相对比较复杂,搞清楚裸机的网卡驱动,我们再去学习Linux内核的DM9000驱动就相对容易一些。
本节将详细讲解DM9000A网卡的数据的收发操作的流程。

1. 相关结构体

struct board_info

/* Structure/enum declaration ------------------------------- */
typedef struct board_info { 
        
	u32 runt_length_counter;	/* counter: RX length < 64byte */
	u32 long_length_counter;	/* counter: RX length > 1514byte */
	u32 reset_counter;	/* counter: RESET */
	u32 reset_tx_timeout;	/* RESET caused by TX Timeout */
	u32 reset_rx_status;	/* RESET caused by RX Statsus wrong */
	u16 tx_pkt_cnt;
	u16 queue_start_addr;
	u16 dbug_cnt;
	u8 phy_addr;
	u8 device_wait_reset;	/* device state */
	unsigned char srom[128];
	void (*outblk)(volatile void *data_ptr, int count);
	void (*inblk)(void *data_ptr, int count);
	void (*rx_status)(u16 *RxStatus, u16 *RxLen);
	struct eth_device netdev;
} board_info_t;

static board_info_t dm9000_info;

该结构体是用来维护DM9000系列网卡的结构体,所有和网卡DM9000A信息都保存到该结构体中。
struct eth_device
struct board_info中有一个重要的成员 netdev,该成员是uboot提供的标准的统一的网卡设备接口。

struct eth_device { 
        
	char name[16];
	unsigned char enetaddr[6];
	int iobase;
	int state;

	int  (*init) (struct eth_device *, bd_t *);
	int  (*send) (struct eth_device *, void *packet, int length);
	int  (*recv) (struct eth_device *);
	void (*halt) (struct eth_device *);
#ifdef CONFIG_MCAST_TFTP
	int (*mcast) (struct eth_device *, u32 ip, u8 set);
#endif
	int  (*write_hwaddr) (struct eth_device *);
	struct eth_device *next;
	int index;
	void *priv;
};

该结构体维护了操作网卡的回调函数等信息,我们只需要把网口的收发数据操作封装到对应的回调函数中,然后注册到系统即可。

2. 网卡注册/注销

进入到arch/arm/lib/board.c 中的 board_init_r 函数:

665 #if defined(CONFIG_CMD_NET)
666     puts("Net: ");
667     eth_initialize(gd->bd);
668 #if defined(CONFIG_RESET_PHY_R)
669     debug("Reset Ethernet PHY\n");
670     reset_phy();
671 #endif

如果定义了 CONFIG_CMD_NET,就调用 eth_initialize(gd->bd)进行网卡初始化。

这个宏在include/config_cmd_default.h 中定义,这个头文件又被单板配置文件 include/configs/origen.h 所包含。

eth_initialize 函数在 net/eth.c 中定义,下面是该函数部分代码:

308     /* 309 * If board-specific initialization exists, call it. 310 * If not, call a CPU-specific one 311 */
312     if (board_eth_init != __def_eth_init) { 
        
313         if (board_eth_init(bis) < 0)
314             printf("Board Net Initialization Failed\n");
315     } else if (cpu_eth_init != __def_eth_init) { 
        
316         if (cpu_eth_init(bis) < 0)
317             printf("CPU Net Initialization Failed\n");
318     } else
319         printf("Net Initialization Skipped\n");

这段代码功能是:如果定义了单板相关的初始化函数就调用它,否则调用 CPU 相关的初始化函数。

其中__def_eth_init 函数,同样在net/eth.c 中定义

105  * CPU and board-specific Ethernet initializations.  Aliased function
106  * signals caller to move on
107  */
108 static int __def_eth_init(bd_t *bis)
109 { 
        
110     return -1;
111 }
112 int cpu_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));
113 int board_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));

这里用到了 gcc 的弱符号和别名属性。
如果我们没有定义自己的 board_eth_init 函数,则 board_eth_init 就和__def_eth_init 相同,调用 board_eth_init 就相当于调用__def_eth_init,现在就能明白上面的 if 判断语句了。

board_eth_init 在board/samsung/origen/origen.c 中定义

264 #ifdef CONFIG_CMD_NET
265 int board_eth_init(bd_t *bis)                                                  
266 { 
              
267 
268     int rc = 0;
269 #ifdef CONFIG_DRIVER_DM9000
270     rc = dm9000_initialize(bis);                                            
271 #endif                                                                         
272     return rc;                                                              
273 }  
274 #endif

这里通过配置宏来决定调用哪个网卡初始化函数。

我们使用的是 DM9000A,我们先查看下 DM9000A 的驱动源文件drivers/net/DM9000x.c,初始化函数如下:

626 int dm9000_initialize(bd_t *bis)
627 { 
        
628     struct eth_device *dev = &(dm9000_info.netdev);
629 
630     /* Load MAC address from EEPROM */
631     dm9000_get_enetaddr(dev);
632 
633     dev->init = dm9000_init;
634     dev->halt = dm9000_halt;
635     dev->send = dm9000_send;
636     dev->recv = dm9000_rx;
637     sprintf(dev->name, "dm9000");
638 
639     eth_register(dev);
640 
641     return 0;
642 } 

该函数就是 DM9000A 的初始化函数。
631行dm9000_get_enetaddr 从 EEPROM 加载MAC地址,

static void dm9000_get_enetaddr(struct eth_device *dev)
{ 
        
#if !defined(CONFIG_DM9000_NO_SROM)
	int i;
	for (i = 0; i < 3; i++)
		dm9000_read_srom_word(i, dev->enetaddr + (2 * i));
#endif
}

该函数根据宏CONFIG_DM9000_NO_SROM 来决定是否从EEPROM 加载MAC地址, 参考的板子上的 DM9000A 没有接 EEPROM,我们在 origen.h 中定义了这个宏,表示不从 EEPROM 加载 MAC地址。

633~636行是将网卡的初始化和收发数据的函数填充到dev中,用于注册到系统中:

639行,函数eth_register()的参数是dev,该变量地址其实是dm9000_info.netdev的地址。
dm9000_info定义在同一文件下:

108  static board_info_t dm9000_info;

函数eth_register()位于net/eth.c中;

  • 功能:用于注册网卡到系统中,如果之前网卡设备链表为空,则直接复制给全局指针变量eth_devices和eth_current ,如果不为空,则把当前网卡插入到链表eth_devices中。
int eth_register(struct eth_device *dev元器件数据手册IC替代型号,打造电子元器件IC百科大全!
          

相关文章