passignore_user_abort

ignore_user_abort  时间:2021-04-05  阅读:()
AnintroductiontoSCSIdriversAnintroductiontoSCSIdriversAnintroductiontoSCSIdriversAlanCoxalan@redhat.
com1.
CopyrightandLicensingCopyright(c)1999byAlanCox.
ThismaterialmaybedistributedonlysubjecttothetermsandconditionssetforthintheOpenPublicationLicense,v0.
4(8June1999)orlater(thelatestversionispresentlyavailableathttp://www.
opencontent.
org/openpub/).
2.
AnIntroductiontoSCSIDriversForthismonthsarticleI'mgoingtoattempttocoverwritingadriverforasimpleSCSIcontrollerunderLinux.
TheLinuxkerneldoesmostoftheworkforSCSIdevicessoa'dumb'SCSIinterfacecanactuallyberelativelypainlesstowrite.
FormoreadvanceddeviceshowevertheSCSIlayerisactuallytooclever.
Thereareplansafoottostreamlineitbecauseofthis.
ThejoboftheSCSIdriverisdifferenttothatofablockdriver.
TheupperlayersoftheSCSIcodehandletheCD-ROM,Diskandotherdevices.
RequestsareturnedintoSCSIcommandblocksbeforetheyarefedtoyourdriver.
ThismeansyourSCSIdriverneedonlyworryaboutSCSIandnotaboutotheraspectsofthekerneldevicestructure.
InordertoillustratetheSCSIdriversI'mgoingtoinventaSCSIcontrollerthathasasimpleandeasytousecommandinterface.
Theysadlydon'ttendtoexist.
Itdoeshowevermakeitaloteasiertofollowtheexample.
EvensowithinthelimitsofamagazineIcanonlycoverthebasicsandhopefullyenoughtogetpeoplestarted.
ALinuxSCSIdrivercontainssevenmainfunctionsThedetectfunctioniscalledfirstbytheSCSIlayer.
IthasthejobofscanningforthecontrollersandregisteringthoseitfindswiththeSCSIlayer.
OncetheyareregisteredtheSCSIlayerwillissuecommandstothecontrollertoprobetheSCSIdevicesonthechain.
Thecommandfunctionissuesacommandsynchronouslyandwaitsforittocomplete.
Mostdriversimplementthisbycallingtheirownqueuecommandfunction.
Thequeuecommandfunctionissuesacommandanddoesnotwaitforittofinish.
Thisisusedbyalmostalloperations.
WhenthecommandcompletesthedrivercallsbackintotheSCSIlayertoinformtheSCSIlayerofthecompletionandpassesbackanyerrorinformation.
AbortandResetareusedtohandleerrorsituationsorcaseswheretheSCSIlayerthinksacommandhasgonemissing.
TheSCSIlayerwillfirstattempttoabortthecommandthenifneedbestartusingalargerhammerontheproblemuntilitgetstothepointoftryingtoresettheentirecontroller.
Hopefullythiswillneverhappen.
Theinfofunctionreturnsadescriptionofthecontrolleritself.
Thisisgenerallyaveryshortpieceofcodeindeed.
FinallythemappingofSCSItoPCdiskgeometryhasneverbeenexactlyastandard.
Thebios_paramfunctioniscalledbytheSCSIlayertoaskthecontrollertoeitherqueryitsBIOSforthefakeddiskgeometryortocomputeageometry(hopefullyusingthesamealgorithmasthecontrollerBIOSitself).
Thefirstfunctiontolookatindetailistheprobefunction.
ThisiscalledatboottimeorwhenaSCSImoduleisloaded.
Forourexampleweassumetherecanonlybeonecardandthatitbehavessanely.
intmyscsi_detect(Scsi_Host_Template*tpnt){structScsi_Host*shpnt;intio=0x320,irq=11;/*Assumefixedforexample*/ForourexamplewewilluseafixedIOandIRQ.
ArealcontrollerwouldeitherreadPCIspaceorwouldprobealistofcommonaddresses.
Wewillalsohidetheprobelogicinafunction.
if(myscsi_probe(io,irq)==0){/*Found-createaninstanceofthiscontroller*/shpnt=scsi_register(tpnt,0);if(shpnt==NULL)return0;Thefirstthingwedoistoaskscsi_registertomakeusadevice.
Thetpntisthetemplatepassedintothisfunctionandwhosedefinitionwewilldescribelaterinthearticle.
Itbasicallydefinesthistypeofcard.
Thereturnedpointisaninstanceofthecard.
Wepass0forthesecondargumentasweneednoprivatedataareaattaching.
Passingasizearrangesforaprivateblocktobeallocatedasshpnt->hostdatashpnt->unique_id=io;shpnt->io_port=io;shpnt->n_io_port=MY_PORT_RANGE;shpnt->irq=irq;shpnt->this_id=MY_SCSI_ID;Nowwestarttofillinthestructure.
Theunique_idisfortellingcardsapart.
InourcasetheI/Oportisaconvenientchoiceforthis.
'this_id'holdstheIDofthecontrolleritself.
EachSCSIdevicehasanidentityincludingthecontroller.
TheSCSIlayerneedstoknowthecontrollersID.
Weassumeforthiscaseitisfixed.
my_hardware_init(shpnt);Initializemyhardware.
Yougettowriteallofthisbit.
if(request_irq(irq,my_irq_handler,0,"myscsi",shpnt)){scsi_unregister(shpnt);printk("my_scsi:IRQ%disbusy.
",irq);return0;}Ifwecan'tregisterourinterrupthandlerweareabitstuck.
Ifsoweunregisterourscsicontrollerandreportnocontrollersfound.
Wealsolettheuserknowsoastoavoidconfusion.
}return1;}Andifitworkedwereportthatwefound1controller.
TheSCSIlayerwillnowgooffandscanallourdevices.
Timetowritethecommandfunctions.
intmyscsi_queuecommand(Scsi_Cmnd*SCpnt,void(*done)(Scsi_Cmnd*)){intio,i;unsignedlongflags;io=SCpnt->host->io_port;/*DigoutourI/Oport*/current_command=Scpnt;Forthisexamplewewillassumethatthecontrollerhandlesonlyonecommandatatime.
TypicalforacheapISAcontroller,notfordecenthardware.
Ifwesupportedmanycommandswecouldn'tkeepaglobalcurrent_commandbutwouldneedtokeepsomekindoflistandmatchrepliesfromthecardtothelistentries.
current_command->scsi_done=done;current_command->SCp.
Status=0;Weneedtorememberwhattocallwhenthecommandcompletes.
Nextwesetupthecommand.
Ourcardishypotheticalandratherover-smartforabasicISAdevice.
Youwon'tbesolucky.
.
.
save_flags(flags);outb(SCpnt->target,io+TARGET_PORT);for(i=0;icmd_len;i++)outb(SCpnt->cmnd[i],io+BUF+i);outb(COMMAND_BEGIN,io+COMMAND);Firstlyweloadthetargetdeviceintothecard,thenthecommand.
SCSIcommandsareblocksofupto16bytesincludinglengthinformation.
Aftershovingitontothecardwecanletthecardbeginoperation,andalsowecanallowinterruptsaswearereadytohandletheresultofthecommand.
restore_flags(flags);return0;andwereturnbacktotheSCSIlayer,thecommandisqueuedandhopefullysomethingwillhappen.
IfnotthentheSCSIlayerwillbotherusafteratimeout.
WhentheSCSIlayerdoeswanttobotherusaboutcommandsthathavegonewalkiesthenitwillcallourabortfunctionthenifthatfailsourresetfunction.
Manysimplercontrollerscannotsupporttheabortfunction.
Ifsotheabortfunctionisniceandsimpleintmyscsi_abort(Scsi_Cmnd*SCpnt){returnSCSI_ABORT_SNOOZE;}Weaskthekerneltowaitabitlongerandhope.
Intheendthekernelwillgetboredofwaitingandcallourresethandler.
WecanalsoreportSCSI_ABORT_PENDINGtoindicatethecommandisbeingabortedbutthatithasnotyetaborted-forexampleifaninterruptmustoccurfromthecardconfirmingtheabort,andwecanreturnSCSI_ABORT_SUCCESSifweabortedthecommand.
FinallywecanreportSCSI_ABORT_BUSYifwearebusyorthereissomeotherreasonwewouldliketoabortbutcannotdosorightnow.
AftertryingtoabortandreissuefailingcommandstheSCSIlayerwilltrytoresetthings.
Ittriestoresetfirstthedeviceincasethathasbecomeconfused,thentoresettheSCSIbusincasethebusitselfhaslockedup.
Finallyittriestoresetthecontrollerincasethehardwarehaschoked.
Howyouhandlethisdependsontheabilityofthecontrolleritself.
intmyscsi_reset(Scsi_Cmnd*SCpnt,unsignedintflags){myhardware_reset(SCpnt->host);returnSCSI_RESET_PENDING;}Forourexampleweassumethatthecontrollerisfairlydumb.
Weignoretheflaghintsandweresetthedevice.
TheSCSI_RESET_PENDINGreturnindicatesthatthebushasbeenresetbutthatcommandswillbereturnedwithafailurestatuslater.
IfthecontrollerresetreturnedthecommandsimmediatelywecouldreissuethecommandsandreturnSCSI_RESET_SUCCESS.
IfwedonotthinkthistypeofresetisappropriatewecanreturnSCSI_RESET_PUNT.
Youshouldatleastsupportresettingthebus.
Theflagsfieldisasetoffourflagsdesignedtoprovidehintsastowhattoresetandhow.
TheimportantflagsareSCSI_RESET_SUGGEST_BUS_RESETwhentheSCSIlayerthinkstheentirebusshouldberesetandSCSI_RESET_SUGGEST_HOST_RESETwhichisthelastresorthinttothedriverthatthingsarebadandthatitmightbeappropriatetocompletelyrestarttheboarditself.
We'veissuedcommandsandwecanstartanabort.
Atthispointwecan'tgetanyfurtherwithoutconsideringtheinterrupthandler.
Theneedsoftheinterrupthandlercanvaryalotbetweencards.
ForourexampledriverI'mgoingtoassumethatitwillinterruptusoncewhenitwantsthedatatosend/receiveandonceoncommandcompletion.
intmy_irq_handler(intirq,void*dev_id,structpt_regs*regs){structScsi_Host*shpnt=dev_id;intio=shpnt->io_port;u16data;Whenwerequestedtheinterruptweusedthehostpointerasthe'dev_id'-adevicespecificfieldthatispassedtothehandlerbythekernel.
Thismakesitveryeasyforustofindwhichcardwearehandlinginadriverthatissupportingmultipleinterfacecards.
WethendigoutourI/Oportaswewillprobablyneedthisalotinamoment.
data=inw(io+READ_STATUS);if(data&RESET_DONE){current_command->result=DID_RESETscsi_done(current_command);return;}Firstlywecheckifthebushasbeenreset(eitherbyusorotherdevices).
Ifsowereportthecommandwasreset.
ThiswillalsotelltheSCSIlayerthattheresetwereportedaspendinginourresethandlerhasnowcompleted.
if(data&PARITY_ERROR){current_command->result=DID_PARITYscsi_done(current_command);return;}Wecheckforparityerrors.
Wewouldcheckforasmanyerrorsaswecanidentifycleanlyonarealcard.
Foranerrorwithnoexactdetailweif(data&GENERAL_ERROR){current_command->result=DID_ERRORscsi_done(current_command);return;}TheSCSImidlayerwillhandledoingtherightthingstorecoverfromanerrorsituation.
NextwelooktoseeifthisisaSCSIphasechange(SCSIcommandspassthroughasetofphases.
Asmartcontrollerhandlesallofthisadumboneless.
Inourcasewewillassumethattheonlyphasesthatneedhelpare'datain'and'dataout'-wherewecopybytestoorfromtheSCSIdeviceweissuedacommand.
if(data&DATA_OUT){outsw(port+DATA_FIFO,current_command->request_buffer,current_command->request_bufflen);}Tosenddataweblastthebuffertothecontroller.
ThismaywellbedonebyDMAinarealcontroller.
Ourexamplewekeepsimple.
Oninputwecheckhowmanybyteswerereceivedandcopythemtotherequestbuffer-whichisprobablyapageofdiskcachemostofthetime.
Wedon'thavetoworrywhereitgoeshowever,justthatitfits.
if(data&DATA_IN){intlen=inw(port+DATA_LEN);if(len>current_command->request_bufflen)len=current_command->request_bufflen;insw(port+DATA_FIFO,current_command->request_buffer,current_command->request_bufflen);}Finallycheckifacommandfinished.
IfsoputthedeviceSCSIstatusinthelowbyteoftheresponseandtelltheSCSIlayerthecommandhascompleted.
Thetop16bitsholdthekernelinfo,thebottomtheSCSIinfo.
Thetop16bitsfornoerrorare0preciselytomakethissimple.
if(data&COMMAND_DONE){current_command->status=inb(port+CMD_STATUS);current_command->scsi_done(current_command);}}andweexitourinterrupt.
SCSIcommandscanbeissuedsynchronouslyalthoughthisisnowbasicallydeadandwedothingsproperly.
Supportingthesynchronouscommandsisbestdoneintermsofthequeuecommandfunctionandthecodebelowisbasicallyboilerplateusedbyalmosteverydriver.
staticvoidit_finished(Scsi_Cmnd*SCpnt){SCpnt->SCp.
Status++;}intmyscsi_command(Scsi_Cmnd*SCpnt){myscsi_queuecommand(SCpnt,it_finished);while(!
SCpnt->SCp.
Status)barrier();returnSCpnt->result;}Wequeueacommandandtellthequeuefunctionthatthe'completion'handler(scsi_done)istoincrementthestatus.
Havingissuedthecommandwespininaloopuntilthecommandfinishes.
Thebarrier()statementisimportanthere.
Gccmightotherwiseoptimizewhile(variable)toif(variable)while(1);Barriertellsitthatitcannotcachevaluesfromvariablesacrossthebarrier()functioncall.
Thisensuresthatthestatus,whichischangedbyaninterruptwillbeseenbytheloopingcode.
ThiscompletestheSCSIcommandhandlersforoursimplecard.
Theyarenotoptimizedandourcardisalittlesimplistic.
Westillneedtofillinthegeometryfunctionandtheinfofunction.
Theinfofunctionreturnsatextdescriptionforourcontroller.
constchar*myscsi_info(structScsi_Host*SChost){return("MySCSIdevice");}itcould(perhapsshouldinfact)returntheI/OandIRQinformation,driverversionandothervaluableinformationtoo.
Thebios_paramfunctionmapsourSCSIdisktoaPCBIOSfakedgeometry.
Realdisksdon'thavethesimplegeometrythePChas,buteveryonehascarriedonfakingitratherthanfixingalltheoperatingsystems.
Thuswehavetocontinuethisfiction.
WeneedtousethesamealgorithmastheBIOSorlifewillbemessy.
ThisexampleistakenfromtheSymbios53c416driverandisquitetypicalintsym53c416_bios_param(Disk*disk,kdev_tdev,int*ip){intsize;size=disk->capacity;ip[0]=64;/*heads*/ip[1]=32;/*sectors*/if((ip[2]=size>>11)>1024)/*cylinders,testforbigdisk*/{ip[0]=255;/*heads*/ip[1]=63;/*sectors*/ip[2]=size/(255*63);/*cylinders*/}return0;}Giventhedisksizewefillinanarrayofintegersfortheheads,sectorsandcylindersofourdisk.
Weactuallywanttobesurethattheseareright.
GettingthemappingwrongwillgivepeoplewhousemixedLinux/DOSdiskscorruptedfilesystemsandgenerateunhappymail.
Allisnowfineexceptthattounloadthemoduleweneedtocleanupourresources.
Weprovideareleasefunctionforthis.
intmyscsi_release(structScsi_Host*SChost){free_irq(SChost->irq,SChost);return0;}ArealdrivershouldofcoursehaveallocatedandfreedtheI/Oportsitusedtoo.
TomakeourdriveraSCSImodulewehavetoincludesomemagicattheendofthefile#ifdefMODULEScsi_Host_Templatedriver_template=MYSCSI;#include"scsi_module.
c"#endifThisgeneratestheinit_moduleandcleanup_modulecodeneededforaSCSIdevice,ratherthantheauthorhavingtoreplicateiteachtime.
TheMYSCSIobjectisadefineweneedtocreateinaheaderfilewealsoinclude.
Itisadefineinaseparatefileasforacompiledindriverwewillneeditagain.
Ourmyscsi.
hfilelookslikeexternintmyscsi_detect(Scsi_Host_Template*);externconstchar*myscsi_info(structScsi_Host*).
.
.
todeclaretheroutinesweprovide.
ThenwedefinedtheMYSCSItemplate#defineMYSCSI{name:"MySCSIDemo",detect:myscsi_detect,info:myscsi_info,command:myscsi_command,queuecommand:myscsi_queuecommand,abort:myscsi_abort,reset:myscsi_reset,bios_param:myscsi_bios_param,ThispartdefinestheSCSIfunctionsweuse.
The"field:value"formatisagccextensionwhichsetsagivenfieldinastructureratherthanlistingallthefieldsinorder.
can_queue:1,Totellthekernelwecanqueuecommandsandreturnthis_id:MY_SCSI_ID,OurhostSCSIidsg_tablesize:SG_NONE,Scattergatherisaveryusefulextensionforperformance.
Forthissimpledriverwedon'tsupportit.
cmd_per_lun:1,WecanhaveatmostonecommandoutstandingperLUN(logicalunit).
unchecked_isa_dma:1,IfyousetthistozerothekernelwilldothehardworkofensuringallthediskbuffersarecopiedintoISAbusaccessiblememorywhenneeded.
ThisonlymatterstoISAbuscontrollersthatdoDMA.
use_clustering:ENABLE_CLUSTERING,Weturnonclustering.
ClusteringtellstheSCSIlayerthatitisworthtryingtomergemultiplediskreadorwriterequestsintoasingleSCSIcommand.
Averyintelligentcontrollermaywellnotsetthis.
proc_dir:&myscsi_proc}Lastlywedefineourdirectoryfor/proc/scsi.
Wehaven'tputthisintothedriveryetsoweaddstructproc_dirmyscsi_proc={PROC_SCSI_MYSCSI,"myscsi",6,/*Lengthofname*/S_IFDIR|S_IRUGO|S_IXUGO,2};whichwillbeusedtoinstallourdirectoryin/proc/scsi.
ThePROC_SCSI_MYSCSIneedstobeaddedtoinclude/linux//proc_fs.
htogetauniqueinodenumberforthisdirectoryin/proc/scsi.
Thescsi_directory_inosenumerationissimplyalistofallthepossibledevices.
WedropourentryinbeforethedebuggingdriverPROC_SCSI_FCAL,PROC_SCSI_I2O,PROC_SCSI_MYSCSI,/*here*/PROC_SCSI_SCSI_DEBUG,HopefullythisarticlehasprovidedenoughgroundingthatthoseinterestedinwritingSCSIdriverscannowfollowthroughexistingdrivers-especiallysimpleoneslikethesymbios53c416driverandseehowtoimplementanewone.

HostYun(月18元),CN2直连香港大带宽VPS 50M带宽起

对于如今的云服务商的竞争着实很激烈,我们可以看到国内国外服务商的各种内卷,使得我们很多个人服务商压力还是比较大的。我们看到这几年的服务商变动还是比较大的,很多新服务商坚持不超过三个月,有的是多个品牌同步进行然后分别的跑路赚一波走人。对于我们用户来说,便宜的服务商固然可以试试,但是如果是不确定的,建议月付或者主力业务尽量的还是注意备份。HostYun 最近几个月还是比较活跃的,在前面也有多次介绍到商...

HostYun全场9折,韩国VPS月付13.5元起,日本东京IIJ线路月付22.5元起

HostYun是一家成立于2008年的VPS主机品牌,原主机分享组织(hostshare.cn),商家以提供低端廉价VPS产品而广为人知,是小成本投入学习练手首选,主要提供基于XEN和KVM架构VPS主机,数据中心包括中国香港、日本、德国、韩国和美国的多个地区,大部分机房为国内直连或者CN2等优质线路。本月商家全场9折优惠码仍然有效,以KVM架构产品为例,优惠后韩国VPS月付13.5元起,日本东京...

Hosteons:洛杉矶/纽约/达拉斯免费升级10Gbps端口,KVM年付21美元起

今年1月的时候Hosteons开始提供1Gbps端口KVM架构VPS,目前商家在LET发布消息,到本月30日之前,用户下单洛杉矶/纽约/达拉斯三个地区机房KVM主机可以从1Gbps免费升级到10Gbps端口,最低年付仅21美元起。Hosteons是一家成立于2018年的国外VPS主机商,主要提供VPS、Hybrid Dedicated Servers及独立服务器租用等,提供IPv4+IPv6,支持...

ignore_user_abort为你推荐
kaixin001.com耍开心网的具体步骤有哪些?Baby被问婚变绯闻黄晓明婚礼上说baby碰他哪里最兴奋嘉兴商标注册嘉兴那里有设计商标的李子柒年入1.6亿魔兽rpg箱庭世界1.6怎么进入魔门月神谭求几个个性网名:www.gegeshe.comSHE个人资料www.baitu.com我看电影网www.5ken.com为什么百度就不上关键字呢baqizi.cc徐悲鸿到其中一张很美的女人体画www4399com4399网站是什么机器蜘蛛《不思议迷宫》四个机器蜘蛛怎么得 获得攻略方法介绍
万网免费域名 justhost stablehost parseerror qingyun web服务器的架设 免费美国空间 美国在线代理服务器 外贸空间 shuang12 免费的asp空间 湖南idc 阵亡将士纪念日 卡巴斯基试用版下载 美国主机 2016黑色星期五 comodo 低价 卡巴下载 远程主机强迫关闭了一个现有的连接 更多