Linux SATA驱动

驱动层次关系

0-> sata_xxx.c  //sata的平台驱动
        1-> drivers/of/xxx.c  //设备树相关操作,of_xxx()
        1-> sata_xxx.c //不同芯片自己的init、irq handler、ata_port ops接口、scsi_host_template sht接口
        1-> drivers/ata/libata_core.c //ata驱动核心,ata_host_xxx()
        1-> drivers/ata/libata_scsi.c //scsi适配层
        1-> drivers/ata/libata_pmp.c //端口扩展
        1-> drivers/ata/libata_eh.c    //异常处理

以Freescale(飞思卡尔) 主控芯片自带的SATA控制器为例,sata_fsl.c

初始化流程

0-> sata_fsl_probe (drivers/ata/sata_fsl.c)
    1-> of_iomap //从设备树种获取hcr_base、ssr_base、csr_base
    1-> irq_of_parse_and_map //从设备树获取中断信息
    1-> ata_host_alloc_pinfo (drivers/ata/libata_core.c)
        //通过ata_host_alloc分配host
        //host.ops及host.port.ops = sata_fsl_ops
    1-> sata_fsl_init_controller //使用fsl自己的寄存器初始化SATA控制器及中断
    1-> ata_host_activate //irq_handler: sata_fsl_interrupt, sht: sata_fsl_sht

 ATA核心接口 ata_host_alloc_pinfo (drivers/ata/libata-core.c)

0-> ata_host_alloc_pinfo //分配host及初始化port
    1-> ata_host_alloc //分配ATA host及port
    1-> 初始化每个host.ports

ATA核心接口 ata_host_activate (drivers/ata/libata-core.c)

0-> ata_host_activate //启动ATA host,请求并注册IRQ
    1-> ata_host_start //启动ATA host
        2-> ap->ops->port_start //sata_fsl_port_start 启动端口,通过fsl内部HCONTROL寄存器复位在线phy
        2-> ap->ops->freeze //sata_fsl_freeze 冻结端口,通过fsl内部HCONTROL寄存器关闭中断实现
    1-> devm_request_irq //请求并注册中断处理函数
    1-> ata_host_register //注册ATA 已启动的host,开启ATA端口,注册host到ATA即SCSI层,并probe注册的设备
        2-> ata_tport_add //每个端口 初始化sysfs的ATA端口结构。
        2-> ata_scsi_add_hosts //注册SCSI主机适配器实例 sht: sata_fsl_sht
            3-> scsi_host_alloc //分配SCSI主机内存并初始化
            3-> scsi_add_host_with_dma //添加带有dma设备的SCSI主机
        2-> sata_link_init_spd //通过SControl(SCR2)寄存器初始化并限制速率
        2-> 打印ATA端口信息
        2-> async_port_probe //每个端口 异步probe
            3-> ata_port_probe
                4-> __ata_port_probe
                    5-> ata_port_schedule_eh
                        6-> ata_std_sched_eh //ap->ops->sched_eh
                4-> ata_port_wait_eh //等待当前挂起的eh完成
            3-> ata_scsi_scan_host

sysfs下的信息 

cxh@cxhserver:~$ ls /sys/class/ata_port/
ata1  ata2  ata3
cxh@cxhserver:~$ ls /sys/class/ata_port/ata1
device  idle_irq  nr_pmp_links  port_no  power  subsystem  uevent
cxh@cxhserver:~$ ls /sys/class/ata_link/
link1  link2  link3
cxh@cxhserver:~$ ls /sys/class/ata_link/link1
device  hw_sata_spd_limit  power  sata_spd  sata_spd_limit  subsystem  uevent

接口 ops

ata_port_operations 

//libata-core.c
const struct ata_port_operations ata_base_port_ops = {
	.prereset		= ata_std_prereset,
	.postreset		= ata_std_postreset,
	.error_handler		= ata_std_error_handler,
	.sched_eh		= ata_std_sched_eh,
	.end_eh			= ata_std_end_eh,
};
const struct ata_port_operations sata_port_ops = {
	.inherits		= &ata_base_port_ops,

	.qc_defer		= ata_std_qc_defer,
	.hardreset		= sata_std_hardreset,
};

//libata-pmp.c
const struct ata_port_operations sata_pmp_port_ops = {
	.inherits		= &sata_port_ops,
	.pmp_prereset		= ata_std_prereset,
	.pmp_hardreset		= sata_std_hardreset,
	.pmp_postreset		= ata_std_postreset,
	.error_handler		= sata_pmp_error_handler,
};

//sata_fsl.c
static struct ata_port_operations sata_fsl_ops = {
    .inherits       = &sata_pmp_port_ops,

    .qc_defer = ata_std_qc_defer,
    .qc_prep = sata_fsl_qc_prep,
    .qc_issue = sata_fsl_qc_issue,
    .qc_fill_rtf = sata_fsl_qc_fill_rtf,

    .scr_read = sata_fsl_scr_read,
    .scr_write = sata_fsl_scr_write,

    .freeze = sata_fsl_freeze,
    .thaw = sata_fsl_thaw,
    .softreset = sata_fsl_softreset,
    .hardreset = sata_fsl_hardreset,
    .pmp_softreset = sata_fsl_softreset,
    .error_handler = sata_fsl_error_handler,
    .post_internal_cmd = sata_fsl_post_internal_cmd,

    .port_start = sata_fsl_port_start,
    .port_stop = sata_fsl_port_stop,

    .pmp_attach = sata_fsl_pmp_attach,
    .pmp_detach = sata_fsl_pmp_detach,
};

scsi_host_temp

//libata.h
#define ATA_BASE_SHT(drv_name)					\
	.module			= THIS_MODULE,			\
	.name			= drv_name,			\
	.ioctl			= ata_scsi_ioctl,		\
	.queuecommand		= ata_scsi_queuecmd,		\
	.can_queue		= ATA_DEF_QUEUE,		\
	.tag_alloc_policy	= BLK_TAG_ALLOC_RR,		\
	.this_id		= ATA_SHT_THIS_ID,		\
	.emulated		= ATA_SHT_EMULATED,		\
	.use_clustering		= ATA_SHT_USE_CLUSTERING,	\
	.proc_name		= drv_name,			\
	.slave_configure	= ata_scsi_slave_config,	\
	.slave_destroy		= ata_scsi_slave_destroy,	\
	.bios_param		= ata_std_bios_param,		\
	.unlock_native_capacity	= ata_scsi_unlock_native_capacity, \
	.sdev_attrs		= ata_common_sdev_attrs

#define ATA_NCQ_SHT(drv_name)					\
	ATA_BASE_SHT(drv_name),					\
	.change_queue_depth	= ata_scsi_change_queue_depth

//sata_fsl.c
static struct scsi_host_template ahci_sht = {
	ATA_NCQ_SHT("sata_fsl"),
	.can_queue = SATA_FSL_QUEUE_DEPTH,
	.sg_tablesize = SATA_FSL_MAX_PRD_USABLE,
	.dma_boundary = ATA_DMA_BOUNDARY,
};

核心ATA发送命令

libata内部ata命令即scsi的ata命令流程与AHCI驱动相同。

ata_qc_issue

所有发送ata的命令都会调用到此接口。

//libata-core.c
0-> ata_qc_issue //分发taskfile到device,taskfile存放于qc中
    1-> link->sactive |= 1 << qc->hw_tag; //NCQ模式下使用sactive的bit表示待处理的多个命令, 命令完成后清除sactive对应bit。
    1-> link->active_tag = qc->tag; //非NCQ模式使用link->active_tag表示待处理的单个命令, 命令完成后active_tag=ATA_TAG_POISON表示空闲。
    1-> ata_sg_setup //如果为DMA模式,则设置sgl
        2-> dma_map_sg //配置sgl,此函数调用后dma_address才会被赋值,且新的sgl更连续,sg数量更少
        2-> ap->ops->qc_prep(qc); //ahci_qc_prep 将qc命令拷贝到正确的位置,准备发送
        2-> ap->ops->qc_issue(qc); //ahci_qc_issue 发送qc命令

sata_fsl_qc_prep

sata_fsl_qc_issue

流程与AHCI类似,具体操作不同cpu可能不同

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SATA (Serial ATA) 是一种高速传输数据的接口标准,它已经成为现代计算机中硬盘驱动器的主要接口标准之一。Linux 内核中的 SATA 驱动程序主要用于支持 SATA 硬盘控制器。 SATA 驱动程序的源代码主要包括以下几个部分: 1. 驱动程序注册和初始化 在 Linux 内核启动时,SATA 驱动程序会自动注册到内核中,以便能够识别并支持 SATA 硬盘控制器。驱动程序的初始化主要包括以下几个步骤: - 检查硬件设备是否存在并可用 - 分配内存空间和初始化数据结构 - 注册中断处理函数 - 设置硬件设备的工作模式和参数 2. 块设备驱动 SATA 硬盘控制器对应的块设备驱动程序主要实现以下几个功能: - 探测硬盘的容量和参数 - 支持读写操作 - 支持块设备的缓存和缓存管理 块设备驱动程序的核心代码包括请求队列管理、命令和数据传输、块设备缓存管理等模块。 3. 中断处理程序 当 SATA 硬盘控制器发生中断时,SATA 驱动程序会调用相应的中断处理程序来处理中断事件。中断处理程序主要实现以下几个功能: - 读取和处理硬件设备的状态信息 - 处理传输命令和数据的完成情况 - 唤醒等待中的进程 4. 控制器驱动程序 SATA 控制器驱动程序主要用于管理和控制 SATA 控制器的工作,包括以下几个功能: - 初始化和配置控制器 - 管理控制器的中断和 DMA 控制 - 处理控制器的错误和异常情况 控制器驱动程序的核心代码主要包括控制器的初始化、中断处理、DMA 控制等模块。 总的来说,SATA 驱动程序的源代码主要涉及硬件设备的初始化和配置、块设备驱动、中断处理程序和控制器驱动程序等几个方面。在理解和分析 SATA 驱动程序的源代码时,需要掌握相关的硬件知识和 Linux 内核编程技巧。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值