? ? ? ? 目的:最近在搞DW 网卡驱动,索性自己重新编写驱动,这样加深下在SylixOS 系统下网络驱动的过程;
? ? ? ?1, 开始先了解下SylixOS 下的网络驱动编程流程,建议看下《SylixOS 驱动程序开发》手册,SylixOS 下网络整体框图如下:
? ? ? ? ?2,通过手册可以得知,如果想在SylixOS 下添加新的网络设备,需要使用到 netdev_add() 这个函数;
/* netdev driver call the following functions add / delete a network interface,
* if this device not in '/etc/if_param.ini' ip, netmask, gw is default configuration.
* 'if_flags' defined in net/if.h such as IFF_UP, IFF_BROADCAST, IFF_RUNNING, IFF_NOARP, IFF_MULTICAST, IFF_PROMISC ... */
int netdev_add(netdev_t *netdev, const char *ip, const char *netmask, const char *gw, int if_flags);
在该函数下有个重要的结构体netdev_t 网络设备结构体:
/*
* network device struct.
*/
typedef struct netdev {
#define NETDEV_VERSION (0x00020003)
#define NETDEV_MAGIC (0xf7e34a81 + NETDEV_VERSION)
UINT32 magic_no; /* MUST be NETDEV_MAGIC */
char dev_name[IF_NAMESIZE]; /* user network device name (such as igb* rtl* also call initialize with '\0') */
char if_name[IF_NAMESIZE]; /* add to system netif name (such as 'en'), after netdev_add() if_name saved full ifname by system */
char *if_hostname;
#define NETDEV_INIT_LOAD_PARAM 0x01 /* load netif parameter when add to system */
#define NETDEV_INIT_LOAD_DNS 0x02 /* load dns parameter when add to system */
#define NETDEV_INIT_IPV6_AUTOCFG 0x04 /* use IPv6 auto config */
#define NETDEV_INIT_AS_DEFAULT 0x08
#define NETDEV_INIT_USE_DHCP 0x10 /* force use DHCP get address */
#define NETDEV_INIT_USE_DHCP6 0x40 /* force use IPv6 DHCP get address */
#define NETDEV_INIT_USE_AODV 0x80 /* use AODV(Ad-hoc) Only for LOWPAN (ipv4 only) */
#define NETDEV_INIT_DO_NOT 0x20 /* do not call init() function (Only used for net bridge) */
#define NETDEV_INIT_NO_TXQ 0x100 /* do not support txqueue */
#define NETDEV_INIT_TIGHT 0x200 /* add to bridge or bonding do not delete from system */
UINT32 init_flags;
#define NETDEV_CHKSUM_GEN_IP 0x0001 /* tcp/ip stack will generate checksum IP, UDP, TCP, ICMP, ICMP6 */
#define NETDEV_CHKSUM_GEN_UDP 0x0002
#define NETDEV_CHKSUM_GEN_TCP 0x0004
#define NETDEV_CHKSUM_GEN_ICMP 0x0008
#define NETDEV_CHKSUM_GEN_ICMP6 0x0010
#define NETDEV_CHKSUM_CHECK_IP 0x0100 /* tcp/ip stack will check checksum IP, UDP, TCP, ICMP, ICMP6 */
#define NETDEV_CHKSUM_CHECK_UDP 0x0200
#define NETDEV_CHKSUM_CHECK_TCP 0x0400
#define NETDEV_CHKSUM_CHECK_ICMP 0x0800
#define NETDEV_CHKSUM_CHECK_ICMP6 0x1000
#define NETDEV_CHKSUM_ENABLE_ALL 0xffff /* tcp/ip stack will gen/check all chksum */
#define NETDEV_CHKSUM_DISABLE_ALL 0x0000 /* tcp/ip stack will not gen/check all chksum */
UINT32 chksum_flags;
#define NETDEV_TYPE_RAW 0
#define NETDEV_TYPE_ETHERNET 1
#define NETDEV_TYPE_LOWPAN 2
#define NETDEV_TYPE_LOWPAN_BLE 3
UINT32 net_type;
UINT64 speed; /* link layer speed bps */
UINT32 mtu; /* link layer max packet length (6LowPAN must be 1280) */
UINT8 hwaddr_len; /* link layer address length MUST 6 or 8 */
UINT8 hwaddr[NETIF_MAX_HWADDR_LEN]; /* link layer address */
struct netdev_funcs *drv; /* netdev driver */
void *priv; /* user network device private data */
/* the following member is used by system, driver MUST set zero and do not used! */
int if_flags;
/* wireless externed */
void *wireless_handlers; /* iw_handler_def ptr */
void *wireless_data; /* iw_public_data ptr */
/* hwaddr filter list */
struct netdev_mac *mac_filter;
/* SylixOS Real-Time externd(poll mode) */
struct netdev_poll poll;
/* SylixOS Tx-Queue */
void *kern_txq;
/* SylixOS Reserve */
void *kern_priv; /* kernel priv */
void *kern_res[15];
ULONG sys[254]; /* reserve for netif */
} netdev_t;
3,好了,废话不多说直接上搭建好的网络驱动代码模板:
#define __SYLIXOS_KERNEL
#include <SylixOS.h>
#include <netdev.h>
char *ip = "10.9.0.99";
char *netmask = "255.255.0.0";
char *gw = "10.9.0.1";
char *netDevName = "dw";
netdev_t dwDev;
int dwTransmit(struct netdev *netdev, struct pbuf *p);
void dwReceive(struct netdev *netdev, int (*input)(struct netdev *, struct pbuf *));
struct netdev_funcs netFuns = {
.init = NULL,
.up = NULL,
.down = NULL,
.remove = NULL,
.transmit = dwTransmit,
.receive = dwReceive,
.pollrecv = NULL,
.intctl = NULL,
.rxmode = NULL,
.ioctl = NULL,
};
int dwTransmit(struct netdev *netdev, struct pbuf *p)
{
return (0);
}
void dwReceive(struct netdev *netdev, int (*input)(struct netdev *, struct pbuf *))
{
return;
}
void dwCreate(void)
{
int ret = 0;
lib_memcpy(dwDev.dev_name,netDevName,sizeof(netDevName));
lib_strcpy(dwDev.if_name, "en");
dwDev.hwaddr_len = 6;
dwDev.hwaddr[0] = 0x00;
dwDev.hwaddr[1] = 0x11;
dwDev.hwaddr[2] = 0x44;
dwDev.hwaddr[3] = 0x55;
dwDev.hwaddr[4] = 0x77;
dwDev.hwaddr[5] = 0x88;
dwDev.magic_no = NETDEV_MAGIC;
dwDev.if_hostname = "SylixOS_Dw";
dwDev.init_flags = NETDEV_INIT_LOAD_PARAM | /* net_dev 初始化时选项 */
NETDEV_INIT_LOAD_DNS |
NETDEV_INIT_IPV6_AUTOCFG;
dwDev.chksum_flags = NETDEV_CHKSUM_ENABLE_ALL;
dwDev.net_type = NETDEV_TYPE_ETHERNET;
dwDev.speed = 0;
dwDev.mtu = 1500;
dwDev.drv = &netFuns;
ret = netdev_add(&dwDev,ip,netmask,gw,IFF_UP | IFF_BROADCAST | IFF_RUNNING);
if(ret < 0)
{
printk("dev add error \n\r");
}
}
/*
* SylixOS call module_init() and module_exit() automatically.
*/
int module_init (void)
{
dwCreate();
printk("hello_module init!\n");
return 0;
}
void module_exit (void)
{
printk("hello_module exit!\n");
}
/*
* module export symbols
*/
LW_SYMBOL_EXPORT void hello_module_func (void)
{
printk("hello_module_func() run!\n");
}
编译,上传并加载ko文件,使用ifconfig 命令可以发现多出一个网络设备:
?
|