作者

QQ群:852283276
微信:arm80x86
微信公众号:青儿创客基地
B站:主页 https://space.bilibili.com/208826118

方法

u-boot下访问sata或者sata ahci有两种方式,一种是pcie上的pcie转sata芯片,比如marvell的88se9230,需要先开启对pcie的支持,一种是cpu内部总线上的,linux上称为platform设备,以xilinx zynqmp为例,u-boot下开启的宏为:

/*u-boot-xlnx-v2018.2\include\configs\xilinx_zynqmp.h*/
#define CONFIG_SYS_SCSI_MAX_SCSI_ID 2
#define CONFIG_SYS_SCSI_MAX_LUN     1
#define CONFIG_SYS_SCSI_MAX_DEVICE  (CONFIG_SYS_SCSI_MAX_SCSI_ID * \CONFIG_SYS_SCSI_MAX_LUN)
/*menuconfig*/
#define CONFIG_SCSI 1
#define CONFIG_AHCI 1/*scsi 对应scsi系列命令 2015.2.1*/
#ifdef CONFIG_AHCI
#define CONFIG_LIBATA
#define CONFIG_SCSI_AHCI
#define CONFIG_SCSI_AHCI_PLAT
#define CONFIG_SUNXI_AHCI
#define CONFIG_SYS_SCSI_MAX_SCSI_ID 1
#define CONFIG_SYS_SCSI_MAX_LUN     1
#define CONFIG_SYS_SCSI_MAX_DEVICE  (CONFIG_SYS_SCSI_MAX_SCSI_ID * \CONFIG_SYS_SCSI_MAX_LUN)
#define CONFIG_CMD_SCSI
#endif/*sata 对应sata系列命令 2015.2.1*/
#define CONFIG_CMD_SATA
#ifdef CONFIG_CMD_SATA
#define CONFIG_DWC_AHSATA
#define CONFIG_SYS_SATA_MAX_DEVICE  1
#define CONFIG_DWC_AHSATA_PORT_ID   0
#define CONFIG_DWC_AHSATA_BASE_ADDR SATA_ARB_BASE_ADDR
#define CONFIG_LBA48
#define CONFIG_LIBATA
#endif

如果我们的sata是通过pcie转sata实现,首先我们需要打开pcie相关的宏,u-boot-xlnx-v2015.2.1\common\board_r.c中会先初始化pcie,initr_pci

/*pcie*/
#define CONFIG_PCI
#define CONFIG_DM_PCI
#define CONFIG_PCI_XILINX
#define CONFIG_CMD_PCI#ifdef CONFIG_PCI
static int initr_pci(void)
{pci_init();return 0;
}
#endif

然后调用后调用scsi_init

/*cmd_scsi.c*/
#ifdef CONFIG_PCI
void scsi_init(void)
{int busdevfunc;int i;/** Find a device from the list, this driver will support a single* controller.*/for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {/* get PCI Device ID */busdevfunc = pci_find_device(scsi_device_list[i].vendor,scsi_device_list[i].device,0);if (busdevfunc != -1)break;}if (busdevfunc == -1) {printf("Error: SCSI Controller(s) ");for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) {printf("%04X:%04X ",scsi_device_list[i].vendor,scsi_device_list[i].device);}printf("not found\n");return;}
#ifdef DEBUGelse {printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n",scsi_device_list[i].vendor,scsi_device_list[i].device,(busdevfunc >> 16) & 0xFF,(busdevfunc >> 11) & 0x1F,(busdevfunc >> 8) & 0x7);}
#endifbootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci");scsi_low_level_init(busdevfunc);scsi_scan(1);bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI);
}
#endif

这里需要定义你的scsi_device_list,对应宏CONFIG_SCSI_DEV_LIST

/******************************* console command******************************/
#define CONFIG_CMD_EXT4
#define CONFIG_CMD_EXT4_WRITE
#define CONFIG_CMD_SCSI
#define CONFIG_CMD_SATA
#define CONFIG_CMD_USB/* ****************************** SATA AHCI driver configure******************************/
#if defined(CONFIG_CMD_SCSI)
#define CONFIG_SCSI_AHCI
#define CONFIG_AHCI_SETFEATURES_XFER
#define CONFIG_LIBATA
#ifdef CONFIG_SCSI_AHCI
#define CONFIG_SATA_MAX_DEVICE_AHCI    32
#define CONFIG_SYS_SCSI_MAX_SCSI_ID    4
#define CONFIG_SYS_SCSI_MAX_LUN        1
#define CONFIG_SYS_SCSI_MAX_DEVICE     (CONFIG_SYS_SCSI_MAX_SCSI_ID * \CONFIG_SYS_SCSI_MAX_LUN * CONFIG_SATA_MAX_DEVICE_AHCI)
#endif
#define CONFIG_ATAPI
#endif
#define CONFIG_SCSI_DEV_LIST           {0x1b21, 0x0612}, \{0x1cc4, 0x1401}, \{0x1b4b, 0x9215}, \{0x1b4b, 0x9235}, \{0x1b4b, 0x9125}, \{0x1b4b, 0x9230}, \{0x21b4, 0x0835}

scsi的底层支持函数在u-boot-xlnx-v2015.2.1\drivers\block\ahci.c中实现,

void scsi_low_level_init(int busdevfunc)
-->static int ahci_init_one(int pdev)-->static int ahci_host_init(struct ahci_probe_ent *probe_ent)-->static void ahci_print_info(struct ahci_probe_ent *probe_ent)
void scsi_scan(int mode)/*cmd_scsi.c*/
-->int scsi_exec(ccb *pccb)int scsi_exec(ccb *pccb)
{int ret;switch (pccb->cmd[0]) {case SCSI_READ10:ret = ata_scsiop_read_write(pccb, 0);break;case SCSI_WRITE10:ret = ata_scsiop_read_write(pccb, 1);break;case SCSI_RD_CAPAC10:ret = ata_scsiop_read_capacity10(pccb);break;case SCSI_RD_CAPAC16:ret = ata_scsiop_read_capacity16(pccb);break;case SCSI_TST_U_RDY:ret = ata_scsiop_test_unit_ready(pccb);break;case SCSI_INQUIRY:ret = ata_scsiop_inquiry(pccb);break;default:printf("Unsupport SCSI command 0x%02x\n", pccb->cmd[0]);return false;}if (ret) {debug("SCSI command 0x%02x ret errno %d\n", pccb->cmd[0], ret);return false;}return true;}

scsi系列命令,如果定义了CONFIG_SCSI_AHCI_PLAT则需要开发者自己实现scsi_init,或者你就是想用自己的sata ip,那你就实现自己的scsi_init函数,参考sunxi_ahci_phy_init,如果你需要初始化Xilinx FPGA的GTX,那就在这个地方,

/*board\xilinx\zynqmp\zynqmp.c*/
#ifdef CONFIG_SCSI_AHCI_PLAT
void scsi_init(void)
{ahci_init(ZYNQMP_SATA_BASEADDR);scsi_scan(1);
}
#endif
/*u-boot-xlnx-v2015.2.1\board\sunxi\ahci.c*/
void scsi_init(void)
{printf("SUNXI SCSI INIT\n");
#ifdef CONFIG_SATAPWRgpio_request(CONFIG_SATAPWR, "satapwr");gpio_direction_output(CONFIG_SATAPWR, 1);/* Give attached sata device time to power-up to avoid link timeouts */mdelay(500);
#endifif (sunxi_ahci_phy_init(SUNXI_SATA_BASE) < 0)return;ahci_init(SUNXI_SATA_BASE);
}

函数ahci_init位于u-boot-xlnx-v2015.2.1\drivers\block\ahci.c,注意其中的CONFIG_SYS_SCSI_MAX_SCSI_ID,表示支持多少个port,每个port对应一个盘,CONFIG_SYS_SCSI_MAX_LUN表示每个盘有多少分区,

#ifdef CONFIG_SCSI_AHCI_PLAT
int ahci_init(u32 base)
{int i, rc = 0;u32 linkmap;probe_ent = malloc(sizeof(struct ahci_probe_ent));if (!probe_ent) {printf("%s: No memory for probe_ent\n", __func__);return -ENOMEM;}memset(probe_ent, 0, sizeof(struct ahci_probe_ent));probe_ent->host_flags = ATA_FLAG_SATA| ATA_FLAG_NO_LEGACY| ATA_FLAG_MMIO| ATA_FLAG_PIO_DMA| ATA_FLAG_NO_ATAPI;probe_ent->pio_mask = 0x1f;probe_ent->udma_mask = 0x7f;   /*Fixme,assume to support UDMA6 */probe_ent->mmio_base = base;/* initialize adapter */rc = ahci_host_init(probe_ent);if (rc)goto err_out;ahci_print_info(probe_ent);linkmap = probe_ent->link_port_map;for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) {if (((linkmap >> i) & 0x01)) {if (ahci_port_start((u8) i)) {printf("Can not start port %d\n", i);continue;}
#ifdef CONFIG_AHCI_SETFEATURES_XFERahci_set_feature((u8) i);
#endif}}
err_out:return rc;
}

如果走sata系列命令,比如i.mx上使用的dwc的sata ahci ip,驱动实现在了u-boot-xlnx-v2015.2.1\drivers\block\dwc_ahsata.c驱动初始化入口init_sata在sata命令中调用,

#define CONFIG_CMD_SATA
#ifdef CONFIG_CMD_SATA#define CONFIG_DWC_AHSATA#define CONFIG_SYS_SATA_MAX_DEVICE      1#define CONFIG_DWC_AHSATA_PORT_ID       0#define CONFIG_DWC_AHSATA_BASE_ADDR     SATA_BASE_ADDR#define CONFIG_LBA48#define CONFIG_LIBATA
#endifint __sata_initialize(void)
{int rc;int i;for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) {memset(&sata_dev_desc[i], 0, sizeof(struct block_dev_desc));sata_dev_desc[i].if_type = IF_TYPE_SATA;sata_dev_desc[i].dev = i;sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN;sata_dev_desc[i].type = DEV_TYPE_HARDDISK;sata_dev_desc[i].lba = 0;sata_dev_desc[i].blksz = 512;sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz);sata_dev_desc[i].block_read = sata_read;sata_dev_desc[i].block_write = sata_write;rc = init_sata(i);if (!rc) {rc = scan_sata(i);if (!rc && (sata_dev_desc[i].lba > 0) &&(sata_dev_desc[i].blksz > 0))init_part(&sata_dev_desc[i]);}}sata_curr_device = 0;return rc;
}
int sata_initialize(void) __attribute__((weak,alias("__sata_initialize")));

验证

这里没有实现scsi_init函数,因为FPGA配置文件没有加载,初始化就死机了,所以做了一个命令,

zynq-uboot> run fpga_boot && fdk_ahci && scsi scan
SF: Detected N25Q128 with page size 512 Bytes, erase size 128 KiB, total 32 MiB
SF: 15728640 bytes @ 0x100000 Read: OKdesign filename = "MWM195_V2_U40_V1;UserID=0XFFFFFFFF;Version=2017.4"part number = "7z030ffg676"date = "2019/04/08"time = "18:52:22"bytes in bitstream = 5979916
zynq_align_dma_buffer: Align buffer at 10000070 to 10000000(swap 1)
FDK SCSI INIT...after fpga load
Target spinup took 0 ms.
AHCI 0001.0300 32 slots 1 ports 6 Gbps 0x1 impl SATA mode
flags: ncq stag pm led clo only pmp pio slum part apst
scanning bus for devices...Device 0: (0:0) Vendor: ATA Prod.: MWM198-1TB Rev: V1.0Type: Hard DiskCapacity: 915715.3 MB = 894.2 GB (1875385008 x 512)
Found 1 device(s).
zynq-uboot> ext4ls scsi 0 /
<DIR>       4096 .
<DIR>       4096 ..
<DIR>       4096 NET
<DIR>       4096 CAN
<DIR>       4096 RS422
<DIR>       4096 RS485
zynq-uboot> ext4ls scsi 0 /NET
<DIR>       4096 .
<DIR>       4096 ..
<DIR>       4096 20191015
<DIR>       4096 20191016
<DIR>       4096 20191017
zynq-uboot>

u-boot scsi sata源码解析相关推荐

  1. 【Spring Boot实战】源码解析Spring Boot自动配置原理

    一.简介 Spring致力于让Java开发更简单,SpringBoot致力于让使用Spring进行Java开发更简单,SpringCloud致力于基于SpringBoot构建微服务生态圈,让微服务开发 ...

  2. Spring Boot Profile使用详解及配置源码解析

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 二师兄 来源 | 程序新视界 在实践的过程中我 ...

  3. Spring Boot 核心原理与源码解析 - 目录

    准备重新写 SpringBoot 配置文件解析原理 , 先在这里把要写的内容记下来 Spring Boot 核心原理与源码解析 - 目录 1\何时解析\如何解析 application.propert ...

  4. spring boot 源码解析23-actuate使用及EndPoint解析

    前言 spring boot 中有个很诱人的组件–actuator,可以对spring boot应用做监控,只需在pom文件中加入如下配置即可: <dependency><group ...

  5. 2 Keil自带的8051汇编boot源码解析注释

    本仓库相关网址: CSDN文章地址(待添加) Gitee工程和源码地址 - https://gitee.com/langcai1943/8051-from-boot-to-application 相关 ...

  6. 【SpringBoot】最新版2019Spring Boot配置解析,源码解析(速成SpringBoot)——学习笔记版【2】

    SpringBoot配置文件 文章目录 SpringBoot配置文件 四.配置文件 1.简介 2.YAML用法 2.1 简介 2.2语法 3.为属性注入值 3.1使用.yml配置文件 3.1编写.ym ...

  7. 注册中心 Eureka 源码解析 —— 应用实例注册发现(五)之过期

    2019独角兽企业重金招聘Python工程师标准>>> 摘要: 原创出处 http://www.iocoder.cn/Eureka/instance-registry-evict/ ...

  8. Guava RateLimiter限流源码解析和实例应用

    2019独角兽企业重金招聘Python工程师标准>>> 在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流 缓存 缓存的目的是提升系统访问速度和增大系统处理容量 降级 降级是 ...

  9. Laravel源码解析之从入口开始

    前言 提升能力的方法并非使用更多工具,而是解刨自己所使用的工具.今天我们从Laravel启动的第一步开始讲起. 入口文件 laravel是单入口框架,所有请求必将经过index.php define( ...

最新文章

  1. RDKit | 比较分子之间的相似性
  2. 华为发布《自动驾驶网络解决方案白皮书》
  3. 产品经理提升修炼的方法
  4. linux查看登录服务器的ip历史记录,通过登陆IP记录Linux所有用户登录所操作日志的方法...
  5. 编辑器eslint格式_ESlint 代码格式大坑vscode vetur,eslint 冲突
  6. Failedto load class org.slf4j.impl.StaticLogger...
  7. Chrome 浏览器 NET::ERR_SSL_OBSOLETE_VERSION 问题及解决方式
  8. 2021.01.04 第 1 个工作日反思
  9. Lighttpd、Nginx 、Apache 隐藏响应头信息的Server信息和版本信息
  10. pycharm 调试模式下命令行参数的传递
  11. 苹果Mac可视化磁盘清理工具:Disk Expert
  12. (一)查询出排序中的最大值和最小值
  13. 明解c语言答案第八章,明解C语言 入门篇 第八章答案
  14. 01web前端笔试试题
  15. SEODONG Medical推出创新干眼症治疗仪器,深受海外消费者好评
  16. 苹果企业签名掉签问题以及稳定性解析
  17. Android 常用正则表达式
  18. 适配iOS 11和iPhone X——导航栏、UITableView
  19. (Sentinel-2A、Sentinel-2B)2017年全年中国地区数据
  20. swift中代码生成纯色图片

热门文章

  1. 系统设计 架构设计 画图工具 架构图 设计图
  2. JNI系列(一)JNI简介
  3. 吕文哲:为什么我说EOS完爆以太坊,理由全在这里了
  4. Python——爬虫+词云+数据库
  5. 通过外网访问局域网中的IPCamera
  6. Java程序员常用开发工具
  7. Keil MDK5生成bin文件时生成了*.bin文件夹
  8. 【深解读】什么是数据科学?如何把数据变成产品?
  9. 森林防火三维电子沙盘指挥系统
  10. lambda表达式无法抛出异常_Lambda 异常处理