Uboot DM_USB与DM_ETH模型

技术背景

详细有学习过Linux驱动的小伙伴,都知道相应的总线驱动模型吧。学习驱动都是先从硬编码,到设备驱动模型的历程,这样能让代码尽可能少的改动,即可支持一系列的设备。在较新的Uboot中,已经有成熟的DM模型了,可以像开发Linux驱动一样,很容易的就能完成设备驱动的编写。

本专题也是基于DM_USB和DM_ETH模型,对iTop4412开发板的DM9621 USB to Ethernet芯片进行驱动程序的移植,借鉴了Linux内核里面的driver/net/usb/dm9601.c和Uboot里面的类似网卡驱动driver/usb/eth/asix.c,帮助很大!

前言

推荐大家阅读一下这篇比较优秀的博文,比较详细的介绍Uboot的DM模型,了解清楚DM模型,就知道为何我们这样写,就可以进行相应的操作,下面给出链接。

uboot (番外篇)uboot 驱动模型: https://blog.csdn.net/ooonebook/article/details/53234020

DM_USB模型简介

概览

根据Uboot的DM模型,需要有udevice_idUBOOT_DEVICE描述设备信息,U_BOOT_DRIVER驱动对应设备的实际硬件操作;UCLASS_USB描述抽象的类信息,和与其对应的UCLASS_DRIVER来描述对应的通用操作。如果一脸懵逼,请先阅读下前言中的博客链接,才能更好的理解Uboot中的驱动模型。

Host驱动简要分析

UCLASS驱动

源自文件drivers/usb/host/usb-uclass.c

  792 UCLASS_DRIVER(usb) = {
  793     .id     = UCLASS_USB,
  794     .name       = "usb",
  795     .flags      = DM_UC_FLAG_SEQ_ALIAS,
  796     .post_bind  = dm_scan_fdt_dev,
  797     .priv_auto_alloc_size = sizeof(struct usb_uclass_priv),
  798     .per_child_auto_alloc_size = sizeof(struct usb_device),
  799     .per_device_auto_alloc_size = sizeof(struct usb_bus_priv),
  800     .child_post_bind = usb_child_post_bind,
  801     .child_pre_probe = usb_child_pre_probe,
  802     .per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata),
  803 };
  804 

设备驱动

源自文件drivers/usb/host/ehci-exynos.c

  247 static const struct udevice_id ehci_usb_ids[] = {
  248     { .compatible = "samsung,exynos-ehci" },
  249     { }
  250 };  
  251 
  252 U_BOOT_DRIVER(usb_ehci) = {
  253     .name   = "ehci_exynos",
  254     .id = UCLASS_USB,
  255     .of_match = ehci_usb_ids,
  256     .ofdata_to_platdata = ehci_usb_ofdata_to_platdata,
  257     .probe = ehci_usb_probe,
  258     .remove = ehci_usb_remove,
  259     .ops    = &ehci_usb_ops,
  260     .priv_auto_alloc_size = sizeof(struct exynos_ehci),
  261     .platdata_auto_alloc_size = sizeof(struct exynos_ehci_platdata),
  262     .flags  = DM_FLAG_ALLOC_PRIV_DMA,
  263 };  

设备驱动操作集

源自文件drivers/usb/host/ehci-exynos.c

  1665 struct dm_usb_ops ehci_usb_ops = {
  1666     .control = ehci_submit_control_msg,
  1667     .bulk = ehci_submit_bulk_msg,
  1668     .interrupt = ehci_submit_int_msg,
  1669     .create_int_queue = ehci_create_int_queue,
  1670     .poll_int_queue = ehci_poll_int_queue,
  1671     .destroy_int_queue = ehci_destroy_int_queue,
  1672     .get_max_xfer_size  = ehci_get_max_xfer_size,
  1673 }; 

工作流程

  • udevice和对应uclass的创建(初始化DM时自动创建)
  • udevice和对应uclass的绑定(初始化DM时自动绑定)
  • 对应udevice的probe调用 (需要自己实现)
  • uclass的接口调用(最终对应udevice driver中ops结构体保存的各种回调)

DM_ETH模型模型简要分析

概览

与DM_USB模型类似,会有UCLASS_ETH抽象类和对应的UCLASS_DRIVER,还有U_BOOT_USB_DEVICE和对应的U_BOOT_DRIVER。注意DM9621是USB转以太网芯片,所以这里有专门的宏U_BOOT_USB_DEVICE来描述USB设备。这里暂时以其他USB以太网网卡驱动用来分析模型,此处为ASIX AX8817X。

分析

UCLASS驱动

源自文件net/eth-uclass.c

  544 UCLASS_DRIVER(eth) = {
  545     .name       = "eth",
  546     .id     = UCLASS_ETH,
  547     .post_bind  = eth_post_bind,
  548     .pre_unbind = eth_pre_unbind,
  549     .post_probe = eth_post_probe,
  550     .pre_remove = eth_pre_remove,
  551     .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
  552     .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
  553     .flags      = DM_UC_FLAG_SEQ_ALIAS,
  554 };

设备驱动

源自文件drivers/usb/eth/asix.c

  872 U_BOOT_DRIVER(asix_eth) = {
  873     .name   = "asix_eth",
  874     .id = UCLASS_ETH,
  875     .probe = asix_eth_probe,
  876     .ops    = &asix_eth_ops,
  877     .priv_auto_alloc_size = sizeof(struct asix_private),
  878     .platdata_auto_alloc_size = sizeof(struct eth_pdata),
  879 };
  880
  881 static const struct usb_device_id asix_eth_id_table[] = {
  882     /* Apple USB Ethernet Adapter */
  883     { USB_DEVICE(0x05ac, 0x1402), .driver_info = FLAG_TYPE_AX88772 },
  884     /* D-Link DUB-E100 H/W Ver B1 */
  885     { USB_DEVICE(0x07d1, 0x3c05), .driver_info = FLAG_TYPE_AX88772 },
  886     /* D-Link DUB-E100 H/W Ver C1 */
  887     { USB_DEVICE(0x2001, 0x1a02), .driver_info = FLAG_TYPE_AX88772 },
  888     /* Cables-to-Go USB Ethernet Adapter */
  889     { USB_DEVICE(0x0b95, 0x772a), .driver_info = FLAG_TYPE_AX88772 },
  890     /* Trendnet TU2-ET100 V3.0R */
  891     { USB_DEVICE(0x0b95, 0x7720), .driver_info = FLAG_TYPE_AX88772 },
  892     /* SMC */
  893     { USB_DEVICE(0x0b95, 0x1720), .driver_info = FLAG_TYPE_AX88172 },
  894     /* MSI - ASIX 88772a */
  895     { USB_DEVICE(0x0db0, 0xa877), .driver_info = FLAG_TYPE_AX88772 },
  896     /* Linksys 200M v2.1 */
  897     { USB_DEVICE(0x13b1, 0x0018), .driver_info = FLAG_TYPE_AX88172 },
  898     /* 0Q0 cable ethernet */
  899     { USB_DEVICE(0x1557, 0x7720), .driver_info = FLAG_TYPE_AX88772 },
  900     /* DLink DUB-E100 H/W Ver B1 Alternate */
  901     { USB_DEVICE(0x2001, 0x3c05), .driver_info = FLAG_TYPE_AX88772 },
  902     /* ASIX 88772B */
  903     { USB_DEVICE(0x0b95, 0x772b),
  904         .driver_info = FLAG_TYPE_AX88772B | FLAG_EEPROM_MAC },
  905     { USB_DEVICE(0x0b95, 0x7e2b), .driver_info = FLAG_TYPE_AX88772B },
  906     { }     /* Terminating entry */
  907 };

设备驱动操作集

源自文件drivers/usb/eth/asix.c

  863 static const struct eth_ops asix_eth_ops = {
  864     .start  = asix_eth_start,
  865     .send   = asix_eth_send,
  866     .recv   = asix_eth_recv,
  867     .free_pkt = asix_free_pkt,
  868     .stop   = asix_eth_stop,
  869     .write_hwaddr = asix_write_hwaddr,
  870 };

设备

源自文件drivers/usb/eth/asix.c

909 U_BOOT_USB_DEVICE(asix_eth, asix_eth_id_table);

工作流程

  • udevice和对应uclass的创建(初始化DM时自动创建)
  • udevice和对应uclass的绑定(初始化DM时自动绑定)
  • 对应udevice的probe调用 (需要自己实现)
  • uclass的接口调用(最终对应udevice driver中ops结构体保存的各种回调)

网络命令工作流程

这里只写个简单的,就不分析了,太难写了。。直接给出简易版本,如下:

cmd/net.c:
shell中input合法的ping <IP>
	---> do_ping(...)
		---> net_loop(PING)
			---> net_init()
			---> eth_halt()	--> eth_ops.stop  -> asix_stop()
			---> eth_init() --> eth_ops.start -> asix_start()
			---> net_set_state(NETLOOP_CONTINUE)
			---> ping_start()
				---> net_set_timeout_handler(10000UL, ping_timeout_handler)
				---> ping_send()
					---> net_send_packet(ptr, len)
						---> eth_send(ptr, len) --> eth_ops.send -> asix_send()
			---> for(;;) --> eth_rx()
			             	--> eth_ops.recv -> asix_recv()
			             	--> net_process_received_packet()
			             	--> eth_ops.free_pkt() --> asix_free_pkt()
			             	--> jump to do recv, max 32 loops
			             --> if get crtl_c
			             	--> eth_halt()
			             	--> break for(;;)
			             --> if timeout or recv error
			             	--> retry N times
			             	--> break for(;;)
			             --> if OK
			             	--> eth_halt()
			             	--> break for(;;)
		---> ret < 0, failed, else OK
	---> ret CMD_RET_SUCCESS or CMD_RET_FAILURE
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值