版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
代碼布局:一、讀寫數(shù)據(jù)流:drivers/scsi/scsi_lib.cscsi_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設備為例)同步執(zhí)行部分:sd_probe異步執(zhí)行部分:sd_probe_async===>sd_revalidate_disk===>sd_spinup_diskscsi子系統(tǒng)核心初始化: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.c1)、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)、scsi_scan_host===>do_scsi_scan_host===>scsi_scan_host_selected===>scsi_scan_channel===>__scsi_scan_target===>scsi_probe_and_add_lun===>scsi_probe_lunscsi_add_lun代碼骨架:scsi子系統(tǒng)核心初始化: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.cstaticatomic_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.hstaticinlineint__must_checkscsi_add_host(structScsi_Host*host,structdevice*dev){ returnscsi_add_host_with_dma(host,dev,dev);}drivers/scsi/hosts.cintscsi_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"#endifstaticcharscsi_scan_type[6]=SCSI_SCAN_TYPE_DEFAULT;//變量的值可以在加載scsi中間層模塊時通過模塊參數(shù)設定,未設定則用上面的默認值module_param_string(scan,scsi_scan_type,sizeof(scsi_scan_type),S_IRUGO);#definejiffies raid6_jiffies()//specifyscanningorrescanningofallpossiblechannels,(target)ids,orluns,onagivenshost.#defineSCAN_WILD_CARD ~0#defineMAX_COMMAND_SIZE16voidscsi_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;id<shost->max_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->devices); list_add_tail(&sdev->siblings,&shost->__devices);}staticintscsi_probe_lun(structscsi_device*sdev,unsignedchar*inq_result,intresult_len,int*bflags){ unsignedcharscsi_cmd[MAX_COMMAND_SIZE]; intfirst_inquiry_len,try_inquiry_len,next_inquiry_len; intresponse_len=0; intpass,count,result; structscsi_sense_hdrsshdr; *bflags=0; first_inquiry_len=sdev->inquiry_len?sdev->inquiry_len:36; try_inquiry_len=first_inquiry_len; pass=1;next_pass: for(count=0;count<3;++count){ intresid; memset(scsi_cmd,0,6); scsi_cmd[0]=INQUIRY;// scsi_cmd[4]=(unsignedchar)try_inquiry_len;......; result=scsi_execute_req(sdev,scsi_cmd,DMA_FROM_DEVICE,inq_result,try_inquiry_len,&sshdr,HZ/2+HZ*scsi_inq_timeout,3,&resid);// if(result){ if((driver_byte(result)&DRIVER_SENSE)&&scsi_sense_valid(&sshdr)){ if((sshdr.sense_key==UNIT_ATTENTION)&& ((sshdr.asc==0x28)||(sshdr.asc==0x29))&&(sshdr.ascq==0)) continue; } }else{ if(resid==try_inquiry_len) continue; } break;//其他錯誤 } if(result==0){ response_len=inq_result[4]+5; if(response_len>255) response_len=first_inquiry_len; *bflags=scsi_get_device_flags(sdev,&inq_result[8],&inq_result[16]); if(pass==1){ if(BLIST_INQUIRY_36&*bflags) next_inquiry_len=36; elseif(BLIST_INQUIRY_58&*bflags) next_inquiry_len=58; elseif(sdev->inquiry_len) next_inquiry_len=sdev->inquiry_len; else next_inquiry_len=response_len; if(next_inquiry_len>try_inquiry_len){ try_inquiry_len=next_inquiry_len; pass=2; gotonext_pass;// } } }elseif(pass==2){ try_inquiry_len=first_inquiry_len; pass=3; gotonext_pass; } if(result) return-EIO;......; return0;}staticintscsi_add_lun(structscsi_device*sdev,unsignedchar*inq_result,int*bflags,intasync){ sdev->inquiry=kmemdup(inq_result,max_t(size_t,sdev->inquiry_len,36),GFP_ATOMIC); if(sdev->inquiry==NULL) returnSCSI_SCAN_NO_RESPONSE;......;if(*bflags&BLIST_NO_ULD_ATTACH) sdev->no_uld_attach=1;......; if(!async&&scsi_sysfs_add_sdev(sdev)!=0) returnSCSI_SCAN_NO_RESPONSE; returnSCSI_SCAN_LUN_PRESENT;}intscsi_sysfs_add_sdev(structscsi_device*sdev){ structrequest_queue*rq=sdev->request_queue; structscsi_target*starget=sdev->sdev_target; scsi_device_set_state(sdev,SDEV_RUNNING); scsi_target_add(starget);device_add(&sdev->sdev_gendev);//將lun掛入到總線的設備鏈表 device_add(&sdev->sdev_dev);// transport_add_device(&sdev->sdev_gendev); bsg_register_queue(rq,&sdev->sdev_gendev,NULL,NULL);}======================================================================scsi磁盤驅動drivers/scsi/sd.c#defineSD_MINORS 16staticDEFINE_IDA(sd_index_ida);//定義ida{}sd_index_ida變量staticconststructblock_device_operationssd_fops={ .owner =THIS_MODULE, .open =sd_open, .locked_ioctl =sd_ioctl, .getgeo =sd_getgeo, .media_changed =sd_media_changed, .revalidate_disk =sd_revalidate_disk,......;};staticstructclasssd_disk_class={ .name ="scsi_disk", .owner =THIS_MODULE, .dev_release =scsi_disk_release, .dev_attrs =sd_disk_attrs,};staticstructscsi_driversd_template={ .owner =THIS_MODULE, .gendrv={ .name ="sd", .probe =sd_probe, }, .rescan =sd_rescan, .done =sd_done,};module_init(init_sd)===>staticint__initinit_sd(void){ intmajors=0,i; for(i=0;i<SD_MAJORS;i++) if(register_blkdev(sd_major(i),"sd")==0)//?? majors++; class_register(&sd_disk_class); scsi_register_driver(&sd_template.gendrv);......;}staticintsd_major(intmajor_idx){ switch(major_idx){ case0: returnSCSI_DISK0_MAJOR; case1...7: returnSCSI_DISK1_MAJOR+major_idx-1; case8...15: returnSCSI_DISK8_MAJOR+major_idx-8; default: return0; }}intscsi_register_driver(structdevice_driver*drv){ drv->bus=&scsi_bus_type; returndriver_register(drv);}driver_register()-->bus_add_driver()-->driver_attach()-->bus_for_each_dev()-->__driver_attach()-->driver_match_device()====>scsi_bus_match()driver_probe_device()====>really_probe()====>sd_probe()staticintscsi_bus_match(structdevice*dev,structdevice_driver*gendrv){ structscsi_device*sdp; if(dev->type!=&scsi_dev_type) return0; sdp=to_scsi_device(dev); if(sdp->no_uld_attach) return0; return(sdp->inq_periph_qual==SCSI_INQ_PQ_CON)?1:0;}//同步部分staticintsd_probe(structdevice*dev){ structscsi_device*sdp=to_scsi_device(dev); structscsi_disk*sdkp; structgendisk*gd; u32index; interror; error=-ENODEV; if(sdp->type!=TYPE_DISK&&sdp->type!=TYPE_MOD&&sdp->type!=TYPE_RBC) gotoout; error=-ENOMEM; sdkp=kzalloc(sizeof(*sdkp),GFP_KERNEL); gd=alloc_disk(SD_MINORS);// do{ if(!ida_pre_get(&sd_index_ida,GFP_KERNEL)) gotoout_put;......; error=ida_get_new(&sd_index_ida,&index); }while(error==-EAGAIN); sd_format_disk_name("sd",index,gd->disk_name,DISK_NAME_LEN);......;sdkp->index=index;......; device_initialize(&sdkp->dev);......; device_add(&sdkp->dev);......; async_schedule(sd_probe_async,sdkp);//見異步部分}//異步部分:staticvoidsd_probe_async(void*data,async_cookie_tcookie){ structscsi_disk*sdkp=data; structscsi_device*sdp; structgendisk*gd; u32index;......; index=sdkp->index; if(index<SD_MAX_DISKS){ gd->major=sd_major((index&0xf0)>>4); gd->first_minor=((index&0xf)<<4)|(index&0xfff00); gd->minors=SD_MINORS; }......; gd->fops=&sd_fops; gd->queue=sdkp->device->request_queue;......;sdkp->media_present=1;sdkp->first_scan=1; sd_revalidate_disk(gd); blk_queue_prep_rq(sdp->request_queue,sd_prep_fn);......; add_disk(gd);......; sd_revalidate_disk(gd);}staticintsd_revalidate_disk(structgendisk*disk){ structscsi_disk*sdkp=scsi_disk(disk); structscsi_device*sdp=sdkp->device;......; if(!scsi_device_online(sdp)) gotoout;......; sd_spinup_disk(sdkp); if(sdkp->media_present){......;} sdkp-
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 贛州師范高等??茖W校《論文規(guī)范教育》2023-2024學年第一學期期末試卷
- 《急診科護理查房》課件
- 三年級數(shù)學上冊六平移旋轉和軸對稱平移和旋轉說課稿蘇教版
- 2021一建考試《建筑工程實務》題庫試卷考點題庫及參考答案解析四
- 《論壇推廣》課件
- 小學生生物安全課件下載
- 一元一次討論移項-課件
- 火災現(xiàn)場安全課件
- 《激光在眼科的運用》課件
- 小學生武警教育課件
- 仙桃市仙桃市2023-2024學年七年級上學期期末數(shù)學檢測卷(含答案)
- 智慧農(nóng)場整體建設實施方案
- 航空公司個人年終總結(共12篇)
- 產(chǎn)品供貨方案、售后服務方案
- 蘇教版小學數(shù)學六年級上冊第4單元解決問題的策略重難點練習【含答案】
- 安徽省池州市貴池區(qū)2023-2024學年高二數(shù)學第一學期期末綜合測試模擬試題含解析
- 干濕球溫度濕度換算表
- 兒童英文自我介紹演講PPT模板(完整版)
- 新加坡雙語教育發(fā)展史
- 研究生自我介紹ppt模板
- 管材管件采購方案投標方案(完整技術標)
評論
0/150
提交評論