Linux内核SCSI子系统驱动架构资料.docx

上传人:b****5 文档编号:28195687 上传时间:2023-07-09 格式:DOCX 页数:25 大小:23.03KB
下载 相关 举报
Linux内核SCSI子系统驱动架构资料.docx_第1页
第1页 / 共25页
Linux内核SCSI子系统驱动架构资料.docx_第2页
第2页 / 共25页
Linux内核SCSI子系统驱动架构资料.docx_第3页
第3页 / 共25页
Linux内核SCSI子系统驱动架构资料.docx_第4页
第4页 / 共25页
Linux内核SCSI子系统驱动架构资料.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

Linux内核SCSI子系统驱动架构资料.docx

《Linux内核SCSI子系统驱动架构资料.docx》由会员分享,可在线阅读,更多相关《Linux内核SCSI子系统驱动架构资料.docx(25页珍藏版)》请在冰豆网上搜索。

Linux内核SCSI子系统驱动架构资料.docx

Linux内核SCSI子系统驱动架构资料

SCSI子系统驱动架构

2013-2-2

代码布局:

一、读写数据流:

drivers/scsi/scsi_lib.c

scsi_execute_req===>scsi_execute===>blk_execute_rq===>blk_execute_rq_nowait

错误恢复:

drivers/scsi/scsi_error.c

内核线程scsi_error_handler===>

 

二、初始化:

(本文!

--------------------------------------------------------------------------------------------------------------------

scsi高层(scsi磁盘)驱动:

1代码分布

2核心调用:

drivers/scsi/sd.c(这里以scsidisk设备为例)

同步执行部分:

sd_probe

异步执行部分:

sd_probe_async===>sd_revalidate_disk===>sd_spinup_disk

--------------------------------------------------------------------------------------------------------------------

scsi子系统核心初始化:

1代码分布

2核心调用:

scsi_init_queue();

scsi_init_procfs();

scsi_init_devinfo();

scsi_init_hosts();

scsi_init_sysctl();

scsi_sysfs_register();

scsi_netlink_init();

--------------------------------------------------------------------------------------------------------------------

scsi适配器驱动:

1代码分布

2核心调用:

drivers/scsi/hosts.c

1)、structScsi_Host*scsi_host_alloc(structscsi_host_template*sht,intprivsize)

2)、scsi_add_host(structScsi_Host*host,structdevice*dev)

===>scsi_add_host_with_dma(host,dev,dev)

intscsi_add_host_with_dma(structScsi_Host*shost,structdevice*dev,structdevice*dma_dev)

3)、scsi_scan_host===>do_scsi_scan_host===>scsi_scan_host_selected===>scsi_scan_channel

===>__scsi_scan_target===>scsi_probe_and_add_lun===>scsi_probe_lun

scsi_add_lun

 

代码骨架:

----------------------------------------------------------------------------------------------------------------------

scsi子系统核心初始化:

drivers/scsi/scsi.c:

staticstructclassshost_class={

.name="scsi_host",

.dev_release=scsi_host_cls_release,

};

staticstructclasssdev_class={

.name="scsi_device",

.dev_release=scsi_device_cls_release,

};

structbus_typescsi_bus_type={

.name="scsi",

.match=scsi_bus_match,

.uevent=scsi_bus_uevent,

};

subsys_initcall(init_scsi)===>

staticint__initinit_scsi(void)

{

scsi_init_queue();

scsi_init_procfs();

scsi_init_devinfo();//

scsi_init_hosts();//

scsi_init_sysctl();

scsi_sysfs_register();//

scsi_netlink_init();

}

intscsi_init_hosts(void)

{

returnclass_register(&shost_class);

}

intscsi_sysfs_register(void)

{

interror;

error=bus_register(&scsi_bus_type);

if(!

error){

class_register(&sdev_class);

}

}

 

----------------------------------------------------------------------------------------------------------------------

scsiHBA驱动:

(前端以dmx3191d为例)

staticstructscsi_host_templatedmx3191d_driver_template={

.name="DomexDMX3191D",

.queuecommand=NCR5380_queue_command,

......,

};

staticstructpci_device_iddmx3191d_pci_tbl[]={

{PCI_VENDOR_ID_DOMEX,PCI_DEVICE_ID_DOMEX_DMX3191D,

PCI_ANY_ID,PCI_ANY_ID,0,0,4},

{}

};

staticstructpci_driverdmx3191d_pci_driver={

.name=DMX3191D_DRIVER_NAME,

.id_table=dmx3191d_pci_tbl,

.probe=dmx3191d_probe_one,

.remove=__devexit_p(dmx3191d_remove_one),

};

module_init(dmx3191d_init);

staticint__initdmx3191d_init(void)

{

returnpci_register_driver(&dmx3191d_pci_driver);//调dmx3191d_probe_one

}

staticint__devinitdmx3191d_probe_one(structpci_dev*pdev,conststructpci_device_id*id)

{

structScsi_Host*shost;

......;

scsi_host_alloc(&dmx3191d_driver_template,sizeof(structNCR5380_hostdata));//------

shost->irq=pdev->irq;

request_irq(pdev->irq,NCR5380_intr,IRQF_SHARED,NAME,shost);

......;

scsi_add_host(shost,&pdev->dev);

scsi_scan_host(shost);

}

 

----------------------------------------------------------------------------------------------------------

drivers/scsi/hosts.c

staticatomic_tscsi_host_next_hn;

structScsi_Host*scsi_host_alloc(structscsi_host_template*sht,intprivsize)

{

structScsi_Host*shost;

gfp_tgfp_mask=GFP_KERNEL;

shost=kzalloc(sizeof(structScsi_Host)+privsize,gfp_mask);

shost->host_no=atomic_inc_return(&scsi_host_next_hn)-1;

device_initialize(&shost->shost_gendev);

shost->shost_gendev.bus=&scsi_bus_type;

shost->shost_gendev.type=&scsi_host_type;

......;

device_initialize(&shost->shost_dev);

shost->shost_dev.parent=&shost->shost_gendev;

shost->shost_dev.class=&shost_class;

returnshost;

}

include/scsi/scsi_host.h

staticinlineint__must_checkscsi_add_host(structScsi_Host*host,structdevice*dev)

{

returnscsi_add_host_with_dma(host,dev,dev);

}

drivers/scsi/hosts.c

intscsi_add_host_with_dma(structScsi_Host*shost,structdevice*dev,structdevice*dma_dev)

{

structscsi_host_template*sht=shost->hostt;

......;

device_add(&shost->shost_gendev);//------

device_add(&shost->shost_dev);

......;

scsi_sysfs_add_host(shost);

......;

}

----------------------------------------------------------------------------------------------------------------------

drivers/scsi/scsi_scan.c

#ifdefCONFIG_SCSI_SCAN_ASYNC//0

#defineSCSI_SCAN_TYPE_DEFAULT"async"

#else

#defineSCSI_SCAN_TYPE_DEFAULT"sync"

#endif

staticcharscsi_scan_type[6]=SCSI_SCAN_TYPE_DEFAULT;

//变量的值可以在加载scsi中间层模块时通过模块参数设定,未设定则用上面的默认值

module_param_string(scan,scsi_scan_type,sizeof(scsi_scan_type),S_IRUGO);

#definejiffiesraid6_jiffies()

//specifyscanningorrescanningofallpossiblechannels,(target)ids,orluns,onagivenshost.

#defineSCAN_WILD_CARD~0

#defineMAX_COMMAND_SIZE16

voidscsi_scan_host(structScsi_Host*shost)

{

structtask_struct*p;

structasync_scan_data*data;

if(strncmp(scsi_scan_type,"none",4)==0)

return;

data=scsi_prep_async_scan(shost);//异步扫描准备与判断shost->async_scan=1

if(!

data){//如果data=null,shost->async_scan仍为0

do_scsi_scan_host(shost);

return;//同步扫描逻辑,不需要任何准备工作

}

p=kthread_run(do_scan_async,data,"scsi_scan_%d",shost->host_no);//异步扫描逻辑

if(IS_ERR(p))//有错误时

do_scan_async(data);//shost->async_scan=0

}

staticvoiddo_scsi_scan_host(structScsi_Host*shost)

{

if(shost->hostt->scan_finished){

......;//自定义的扫描逻辑

}else{

//通配符SCAN_WILD_CARD~0,表示需要尝试所有可能的值

//rescan=0,表示第一次扫描,为1,表示重新扫描,即这个接口还有其他地方调用!

scsi_scan_host_selected(shost,SCAN_WILD_CARD,SCAN_WILD_CARD,SCAN_WILD_CARD,0);

}

}

intscsi_scan_host_selected(structScsi_Host*shost,unsignedintchannel,

unsignedintid,unsignedintlun,intrescan)

{

......;

//shost->async_scan:

是异步扫描标志,为1--异步扫描,0--同步扫描

if(!

shost->async_scan)

scsi_complete_async_scans();

if(scsi_host_scan_allowed(shost)){

if(channel==SCAN_WILD_CARD)

for(channel=0;channel<=shost->max_channel;channel++)

scsi_scan_channel(shost,channel,id,lun,rescan);

else

scsi_scan_channel(shost,channel,id,lun,rescan);

}

}

 

staticvoidscsi_scan_channel(structScsi_Host*shost,unsignedintchannel,

unsignedintid,unsignedintlun,intrescan)

{

uintorder_id;

if(id==SCAN_WILD_CARD)

for(id=0;idmax_id;++id){

if(shost->reverse_ordering)

order_id=shost->max_id-id-1;

else

order_id=id;

__scsi_scan_target(&shost->shost_gendev,channel,order_id,lun,rescan);

}

else

__scsi_scan_target(&shost->shost_gendev,channel,id,lun,rescan);//----

}

staticvoid__scsi_scan_target(structdevice*parent,unsignedintchannel,

unsignedintid,unsignedintlun,intrescan)

{

structScsi_Host*shost=dev_to_shost(parent);

intbflags=0;

intres;

structscsi_target*starget;

if(shost->this_id==id)

return;

starget=scsi_alloc_target(parent,channel,id);

if(lun!

=SCAN_WILD_CARD){

scsi_probe_and_add_lun(starget,lun,NULL,NULL,rescan,NULL);//---------

gotoout_reap;

}

res=scsi_probe_and_add_lun(starget,0,&bflags,NULL,rescan,NULL);//--------

if(res==SCSI_SCAN_LUN_PRESENT||res==SCSI_SCAN_TARGET_PRESENT){

//会调用scsi_probe_and_add_lun

if(scsi_report_lun_scan(starget,bflags,rescan)!

=0)

//会调用scsi_probe_and_add_lun

scsi_sequential_lun_scan(starget,bflags,starget->scsi_level,rescan);

}

out_reap:

scsi_target_reap(starget);

put_device(&starget->dev);

}

 

staticintscsi_probe_and_add_lun(structscsi_target*starget,uintlun,int*bflagsp,

structscsi_device**sdevp,intrescan,void*hostdata)

{

structscsi_device*sdev;

unsignedchar*result;

intbflags,result_len=256;

structScsi_Host*shost=dev_to_shost(starget->dev.parent);

sdev=scsi_device_lookup_by_target(starget,lun);

if(sdev){

if(rescan||!

scsi_device_created(sdev)){

if(sdevp)

*sdevp=sdev;

else

scsi_device_put(sdev);

if(bflagsp)

*bflagsp=scsi_get_device_flags(sdev,sdev->vendor,sdev->model);

returnSCSI_SCAN_LUN_PRESENT;

}

......;

}else

sdev=scsi_alloc_sdev(starget,lun,hostdata);//-----------

result=kmalloc(result_len,GFP_ATOMIC|((shost->unchecked_isa_dma)?

__GFP_DMA:

0));

scsi_probe_lun(sdev,result,result_len,&bflags);//----------

if(bflagsp)

*bflagsp=bflags;

......;

res=scsi_add_lun(sdev,result,&bflags,shost->async_scan);//---------

returnres;

}

staticstructscsi_device*scsi_alloc_sdev(structscsi_target*starget,unsignedintlun,void*hostdata)

{

structscsi_device*sdev;

structScsi_Host*shost=dev_to_shost(starget->dev.parent);

......;

sdev=kzalloc(sizeof(*sdev)+shost->transportt->device_size,GFP_ATOMIC);

......;

sdev->request_queue=scsi_alloc_queue(sdev);

......;

scsi_sysfs_device_initialize(sdev);//---------

......;

returnsdev;

}

voidscsi_sysfs_device_initialize(structscsi_device*sdev)

{

structScsi_Host*shost=sdev->host;

structscsi_target*starget=sdev->sdev_target;

device_initialize(&sdev->sdev_gendev);//

sdev->sdev_gendev.bus=&scsi_bus_type;

sdev->sdev_gendev.type=&scsi_dev_type;

......;

device_initialize(&sdev->sdev_dev);//

......;

sdev->scsi_level=starget->scsi_level;

list_add_tail(&sdev->same_target_siblings,&starget->devi

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 财务管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1