




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
代碼布局:一、讀寫(xiě)數(shù)據(jù)流:drivers/scsi/scsi_lib.cscsi_execute_req===>scsi_execute===>blk_execute_rq===>blk_execute_rq_nowait錯(cuò)誤恢復(fù):drivers/scsi/scsi_error.c內(nèi)核線程scsi_error_handler===>二、初始化:(本文!)scsi高層(scsi磁盤(pán))驅(qū)動(dòng):1代碼分布2核心調(diào)用:drivers/scsi/sd.c(這里以scsidisk設(shè)備為例)同步執(zhí)行部分:sd_probe異步執(zhí)行部分:sd_probe_async===>sd_revalidate_disk===>sd_spinup_diskscsi子系統(tǒng)核心初始化:1代碼分布2核心調(diào)用:scsi_init_queue();scsi_init_procfs();scsi_init_devinfo();scsi_init_hosts();scsi_init_sysctl();scsi_sysfs_register(); scsi_netlink_init();scsi適配器驅(qū)動(dòng):1代碼分布2核心調(diào)用: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驅(qū)動(dòng):(前端以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);//調(diào)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í)通過(guò)模塊參數(shù)設(shè)定,未設(shè)定則用上面的默認(rèn)值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);//異步掃描準(zhǔn)備與判斷shost->async_scan=1 if(!data){//如果data=null,shost->async_scan仍為0 do_scsi_scan_host(shost); return;//同步掃描邏輯,不需要任何準(zhǔn)備工作 } p=kthread_run(do_scan_async,data,"scsi_scan_%d",shost->host_no);//異步掃描邏輯 if(IS_ERR(p))//有錯(cuò)誤時(shí) 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,表示重新掃描,即這個(gè)接口還有其他地方調(diào)用! 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:是異步掃描標(biāo)志,為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){//會(huì)調(diào)用scsi_probe_and_add_lun if(scsi_report_lun_scan(starget,bflags,rescan)!=0)//會(huì)調(diào)用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;//其他錯(cuò)誤 } 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掛入到總線的設(shè)備鏈表 device_add(&sdev->sdev_dev);// transport_add_device(&sdev->sdev_gendev); bsg_register_queue(rq,&sdev->sdev_gendev,NULL,NULL);}======================================================================scsi磁盤(pán)驅(qū)動(dòng)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);//見(jiàn)異步部分}//異步部分: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. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 食品藥品與服裝產(chǎn)業(yè)概覽
- 軟件開(kāi)發(fā)技術(shù)選型
- 圍術(shù)期膿毒性休克治療
- 信息技術(shù)未來(lái)發(fā)展趨勢(shì)
- 去醫(yī)院拔牙流程
- 文化活動(dòng)介紹
- 研究生第一次開(kāi)組會(huì)中文文獻(xiàn)匯報(bào)
- 精準(zhǔn)高效守護(hù)新生
- 社團(tuán)特色活動(dòng)介紹
- 熱泵原理與技術(shù)
- 2025年醫(yī)師定期考核法律法規(guī)試題及答案
- 學(xué)堂在線 大學(xué)計(jì)算機(jī)基礎(chǔ) 章節(jié)測(cè)試答案
- 縣域共配倉(cāng)農(nóng)村物流配送成本控制報(bào)告
- 二級(jí)實(shí)驗(yàn)室生物安全管理手冊(cè)
- 2024-2025學(xué)年北京市西城區(qū)人教版五年級(jí)下冊(cè)期末測(cè)試數(shù)學(xué)試卷(含答案)
- 全國(guó)“安康杯”職工安全健康意識(shí)與應(yīng)急技能知識(shí)競(jìng)賽試卷附答案
- 2025年taca試題及答案
- 皮膚科說(shuō)課課件
- 中國(guó)古代教育的發(fā)展歷程
- 骨科術(shù)后并發(fā)肺栓塞的急救與護(hù)理
- 助理工程師考試試題以及答案
評(píng)論
0/150
提交評(píng)論