作者

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

接上一篇博客Linux AHCI驱动分析之设备初始化

参考

ATA Disk在Linux中的驱动架构对比分析
ata驱动框架及scsi请求处理流程
ATA接口寄存器描述
从ATA层向设备发送TRIM命令
使用硬盘ATA命令读取磁盘
scsi底层设备注册——如何一步步注册到block层
Scsi命令队列转换为ata命令过程
scsi设备的请求处理函数(request_fn)
libATA Developer’s Guide
块设备读写流程
块设备读写流程
Linux Block Layer块设备层基于MultiQueue的部分源码分析
为request的每一个bio创建DMA映射
Linux kernel scatterlist API介绍

打开内核调试信息

定义ATA_DEBUGATA_VERBOSE_DEBUG

//include\linux\libata.h
/** compile-time options: to be removed as soon as all the drivers are* converted to the new debugging mechanism*/
#undef ATA_DEBUG        /* debugging output */
#undef ATA_VERBOSE_DEBUG    /* yet more debugging output */
#undef ATA_IRQ_TRAP     /* define to ack screaming irqs */
#undef ATA_NDEBUG       /* define to disable quick runtime checks *//* note: prints function name for you */
#ifdef ATA_DEBUG
#define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
#ifdef ATA_VERBOSE_DEBUG
#define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
#else
#define VPRINTK(fmt, args...)
#endif  /* ATA_VERBOSE_DEBUG */
#else
#define DPRINTK(fmt, args...)
#define VPRINTK(fmt, args...)
#endif  /* ATA_DEBUG */
//drivers\ata\libata-core.c
struct ata_port *ata_port_alloc(struct ata_host *host)
{...
#if defined(ATA_VERBOSE_DEBUG)/* turn on all debugging levels */ap->msg_enable = 0x00FF;
#elif defined(ATA_DEBUG)ap->msg_enable = ATA_MSG_DRV | ATA_MSG_INFO | ATA_MSG_CTL | ATA_MSG_WARN | ATA_MSG_ERR;
#elseap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN;
#endif
...
}

驱动模型

驱动模型如下图,通过LibATA驱动作为SCSI Middle Level与ATA Host之间的转换层,从而可以很好的将ATA Host直接融入到SCSI的驱动体系中来,可以直接将ATA设备驱成SCSI Device。

注册块设备

下面进入ata_host_register函数,

ata_host_register //drivers\ata\libata-core.chost->n_tags = clamp(sht->can_queue, 1, ATA_MAX_QUEUE - 1); //can_queue = AHCI_MAX_CMDS - 1, n_tags=31, tag ATA_MAX_QUEUE - 1 is reserved for internal commandsata_tport_addata_scsi_add_hosts //drivers\ata\libata-scsi.cscsi_host_allocshost->hostt = sht; // struct scsi_host_template *shtshost->can_queue = sht->can_queue; //struct scsi_host_templateshost->sg_tablesize = sht->sg_tablesize; //struct scsi_host_templateshost->use_blk_mq = scsi_use_blk_mq && !shost->hostt->disable_blk_mq; //scsi_use_blk_mq is from Kconfigshost->max_cmd_len = 16;scsi_add_host_with_dma //drivers\scsi\hosts.cscsi_use_blk_mq: scsi_mq_setup_tags //mq tagsetscsi_setup_command_freelistscsi_get_host_cmd_poolscsi_host_alloc_commandscsi_host_set_state(shost, SHOST_RUNNING)scsi_sysfs_add_hostscsi_proc_host_addsata_link_init_spdata_pack_xfermaskasync_schedule(async_port_probe, ap)ata_port_probe__ata_port_probeata_port_wait_ehata_scsi_scan_host //drivers\ata\libata-scsi.c__scsi_add_device //drivers\scsi\scsi_scan.cscsi_alloc_targetscsi_probe_and_add_lunscsi_device_lookup_by_targetscsi_alloc_sdevscsi_mq_alloc_queue/scsi_alloc_queuescsi_change_queue_depthscsi_sysfs_device_initializescsi_probe_lun //探测lunscsi_execute_req: INQUIRYscsi_execute_req_flags //drivers\scsi\scsi_lib.cscsi_executeblk_get_requestblk_rq_set_block_pcblk_rq_map_kernblk_execute_rqscsi_add_lun //drivers\scsi\scsi_scan.cscsi_sysfs_add_sdev //drivers\scsi\scsi_sysfs.cdevice_add //触发上层probe,bsg_register_queue //block\bsg.c  scsi_target_reap

块设备队列

队列创建,支持多队列和传统的单队列,Linux内核默认是单队列(3.19,4.14),请求分发函数为scsi_queue_rq/scsi_request_fn

__scsi_init_queue //drivers\scsi\scsi_lib.cblk_queue_max_segmentsblk_queue_max_hw_sectorsblk_queue_bounce_limitblk_queue_segment_boundarydma_set_seg_boundaryblk_queue_max_segment_sizeblk_queue_dma_alignmentscsi_alloc_queue //传统单队列__scsi_alloc_queueblk_init_queue__scsi_init_queueblk_queue_prep_rq(q, scsi_prep_fn); //设置prep_rq函数blk_queue_unprep_rq(q, scsi_unprep_fn);blk_queue_softirq_done(q, scsi_softirq_done);blk_queue_rq_timed_out(q, scsi_times_out);blk_queue_lld_busy(q, scsi_lld_busy);static struct blk_mq_ops scsi_mq_ops = {.map_queue   = blk_mq_map_queue,.queue_rq   = scsi_queue_rq,.complete  = scsi_softirq_done,.timeout   = scsi_timeout,.init_request   = scsi_init_request,.exit_request  = scsi_exit_request,
};scsi_mq_alloc_queue //多队列mqblk_mq_init_queue__scsi_init_queue

以传统单队列为例,

scsi_request_fn //drivers\scsi\scsi_lib.cblk_peek_requestret = q->prep_rq_fn(q, rq); //scsi_prep_fnscsi_prep_state_checkscsi_get_cmd_from_req //构造struct scsi_cmndscsi_setup_cmndscsi_setup_fs_cmnd/scsi_setup_blk_pc_cmndscsi_prep_returnscsi_dev_queue_readyblk_start_requeststruct scsi_cmnd *cmd = req->special;scsi_target_queue_readyscsi_host_queue_readyscsi_init_cmd_errhcmd->scsi_done = scsi_done; //中断函数中会用到scsi_dispatch_cmdscsi_log_sendhost->hostt->queuecommand;scsi_queue_insert

其中host->hostt->queuecommand来自struct scsi_host_template,对应ata_scsi_queuecmd函数,函数ata_sg_setup中调用dma_map_sg,对于我们的异构系统,需要修改的就是这个函数,

ata_scsi_queuecmd //drivers\ata\libata-scsi.cata_shost_to_portata_scsi_dump_cdbata_scsi_find_dev__ata_scsi_queuecmdata_get_xlat_func/atapi_xlat //check if SCSI to ATA translation is possibleata_scsi_translate/ata_scsi_simulateata_scsi_translateata_scsi_qc_newqc->scsicmd = cmd;qc->scsidone = cmd->scsi_done;qc->sg = scsi_sglist(cmd);qc->n_elem = scsi_sg_count(cmd);ata_sg_initqc->complete_fn = ata_scsi_qc_complete;ata_get_xlat_func[ata_scsi_rw_xlat/ata_scsi_pass_thru]/atapi_xlat //translatestruct ata_taskfile *tf //构建tfap->ops->qc_defer //ahci_pmp_qc_defer, deferred:推迟; 延缓; 展期 drivers\ata\libahci.cata_std_qc_defer/sata_pmp_qc_defer_cmd_switchata_qc_issueata_sg_setupdma_map_sgap->ops->qc_prep //ahci_qc_prep drivers\ata\libahci.cata_tf_to_fis //tf转fis,协议Command Table的CFISmemcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len) //协议Command Table的ACMDahci_fill_sgahci_fill_cmd_slotap->ops->qc_issue //ahci_qc_issue drivers\ata\libahci.cwritel(1 << qc->tag, port_mmio + PORT_SCR_ACT);writel(fbs, port_mmio + PORT_FBS);writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);

scsi驱动

scsi驱动位于drivers\scsi\sd.c

init_sd //drivers\scsi\sd.cregister_blkdevblk_register_regionclass_registerscsi_register_driver

其中scsi_register_driver(&sd_template.gendrv),上面说的probe函数即sd_probe

static struct scsi_driver sd_template = {.gendrv = {.name      = "sd",.owner        = THIS_MODULE,.probe       = sd_probe,.remove     = sd_remove,.shutdown  = sd_shutdown,.pm      = &sd_pm_ops,},.rescan         = sd_rescan,.init_command      = sd_init_command,.uninit_command      = sd_uninit_command,.done          = sd_done,.eh_action       = sd_eh_action,
};

sd_probe函数,磁盘的队列就是用的scsi_device里的队列,不需要新创建了,

sd_probe //drivers\scsi\sd.calloc_disksd_format_disk_namesd_probe_asyncgd->fops = &sd_fops;gd->queue = sdkp->device->request_queue; //scsi_disk->scsi_device->request_queuesd_revalidate_diskadd_disksd_dif_config_hostsd_revalidate_disk

其中sd_fops如下,

static const struct block_device_operations sd_fops = {.owner           = THIS_MODULE,.open            = sd_open,.release     = sd_release,.ioctl            = sd_ioctl,.getgeo         = sd_getgeo,
#ifdef CONFIG_COMPAT.compat_ioctl       = sd_compat_ioctl,
#endif.check_events     = sd_check_events,.revalidate_disk = sd_revalidate_disk,.unlock_native_capacity   = sd_unlock_native_capacity,
};sd_ioctlscsi_verify_blk_ioctlscsi_ioctl/scsi_cmd_blk_ioctl

其中,

scsi_ioctl //block\scsi_ioctl.csg_scsi_ioctl/sdev->host->hostt->ioctl //ata_scsi_ioctlscsi_cmd_blk_ioctlscsi_verify_blk_ioctlscsi_cmd_ioctlsg_ioata_scsi_ioctl //drivers\ata\libata-scsi.cata_sas_scsi_ioctlATA_IOC_GET_IO32ATA_IOC_SET_IO32HDIO_GET_IDENTITY ata_get_identityHDIO_DRIVE_CMD ata_cmd_ioctlHDIO_DRIVE_TASK ata_task_ioctl

中断

以传统单队列为例,

ahci_single_irq_intr //drivers\ata\libahci.cahci_port_intrahci_handle_port_interruptata_qc_complete_multiple //drivers\ata\libata-core.cata_qc_from_tagata_qc_complete__ata_qc_completeata_sg_cleandma_unmap_sgqc->complete_fn //ata_scsi_qc_complete drivers\ata\libata-scsi.cata_gen_passthru_sense/ata_gen_ata_senseata_dump_statusqc->scsidone //scsi_done drivers\scsi\scsi_lib.cata_qc_free

Linux AHCI驱动分析之块设备层相关推荐

  1. Linux nvme驱动分析之块设备层

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

  2. nvme命令中prp_Linux nvme驱动分析之块设备层

    参考 Product Documentation Red Hat Enterprise Linux7 7.2 发行注记 第 14 章 存储 blk_mq 数据缓冲区转换成prp或者sg列表 用户态分配 ...

  3. Linux文件系统概述:硬盘驱动>通用块设备层>文件系统>虚拟文件系统(VFS)

    目录 一.概述 1. 硬盘驱动 2. 通用块设备层 General Block Device Layer 3. 文件系统 4. 虚拟文件系统(VFS) 二.存储介质 闪存(Flash Memory) ...

  4. Linux AHCI驱动

    目录 概念 port link device tag scsi host scsi device sgl Port.Link.Device之间的关系 Port Link host link pmp l ...

  5. linux串口驱动分析

    linux串口驱动分析 硬件资源及描写叙述 s3c2440A 通用异步接收器和发送器(UART)提供了三个独立的异步串行 I/O(SIO)port,每一个port都能够在中断模式或 DMA 模式下操作 ...

  6. Linux spi驱动分析(四)----SPI设备驱动(W25Q32BV)

    一.W25Q32BV芯片简介 W25X是一系列SPI接口Flash芯片的简称,它采用SPI接口和CPU通信,本文使用的W25Q32BV容量为32M,具体特性如下: 1.1.基本特性 该芯片最大支持10 ...

  7. Linux spi驱动分析----SPI设备驱动(W25Q32BV)

    转载地址:http://blog.chinaunix.net/uid-25445243-id-4026974.html 一.W25Q32BV芯片简介 W25X是一系列SPI接口Flash芯片的简称,它 ...

  8. Linux网卡驱动分析之RTL8139(五)

    Linux网卡驱动分析之RTL8139(五) deliver_skb(dev.c) // 该函数就是调用个协议的接收函数处理该skb 包,进入第三层网络层处理 static __inline__ in ...

  9. linux pinctrl驱动分析

    linux pinctrl驱动分析 altas200模块 准备 设备树节点 pinctrl驱动分析 pcs_probe函数 pcs_allocate_pin_table函数 pcs_add_pin函数 ...

  10. Linux下驱动开发_块设备驱动开发(硬件上采用SD卡+SPI协议)

    一.前言 块设备主要为存储设备设计的框架. 在前面章节Linux下驱动开发_块设备驱动开发(内存模拟存储) 里介绍了块设备驱动编写思路,并且利用内存模拟了硬件存储,完成了块设备驱动开发测试.这一篇文章 ...

最新文章

  1. iOS 标签自动布局
  2. 人脸识别开源网络笔记
  3. 卷积神经网络原理及实现
  4. oracle导入与导出,oracle导入与导出
  5. 多线程-NSOperation
  6. 文件包含漏洞不能包含php,ThinkPHP5漏洞分析之文件包含
  7. go 数据类型和操作符
  8. Java中的ThreadLocal的使用--学习笔记
  9. [转载] python 元组tuple - python基础入门(14)
  10. The content of elements must consist of well-formed character data or markup
  11. 斜视术后融合训练方法_做斜视手术两年后又复发了怎么办?
  12. 2010计算机网络考研真题及答案,2010年计算机考研统考真题参考答案
  13. 抽象类和接口到底是什么“垃圾“——教你分类
  14. 熊猫分发_熊猫下降列和行
  15. vue进入页面加载数据缓慢实现loading提示
  16. hivesql的几种优化的方法
  17. java生成pdf带图片_(例)Java生成PDF图片 iText
  18. 对冲基金小镇 鬼城_未来系统,代码寿命和网络鬼城
  19. Android(15)——ButterKnife
  20. 重庆华侨城携手T.M.D PCP 发财潮流文化节2.0国庆重磅来袭

热门文章

  1. 微信定时自动发消息。每天和你的obj准时说晚安
  2. 医疗行业软件开发流程-立项阶段
  3. Visio2016 层次方框图
  4. 7大浏览器颜值代表,谁才是真正的浏览器颜值之王呢?
  5. 走在身后的2021,迎面走来的2022
  6. 诱人的 TypeScript 视频教程(69 个视频)
  7. PPT模板、素材下载网站(纯干货,建议收藏)
  8. 用冰封服务器安装系统,冰封一键重装系统怎么使用 冰封一键重装系统使用教程...
  9. 下载Linux系统内文件到Windows
  10. 计算机算法应用状况,详解机器学习中的现状,算法,应用