Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386////////////////////////////////////////////////////////////////////// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine// All rights reserved// This file was released under the GPLv2 on June 2015./////////////////////////////////////////////////////////////////////* Module Name: Phys_lib.cpp
Execution: Kernel mode only
Description:
Contains code that implement read/write operations for physical device*/
#include "phys_lib.h"
static const char Signature [16] = {CDRW_SIGNATURE_v1};
// Local functions:
OSSTATUSUDFSetSpeeds( IN PVCB Vcb );
NTSTATUSUDFSetCaching( IN PVCB Vcb );
OSSTATUSUDFRecoverFromError( IN PVCB Vcb, IN BOOLEAN WriteOp, IN OSSTATUS status, IN uint32 Lba, IN uint32 BCount, IN OUT uint32* retry);
#ifdef _BROWSE_UDF_
uint32UDFFixFPAddress( IN PVCB Vcb, // Volume control block from this DevObj IN uint32 Lba );
#endif //_BROWSE_UDF_
NTSTATUSUDFSyncCache( IN PVCB Vcb ){ UDFPrint(("UDFSyncCache:\n")); OSSTATUS RC; RC = UDFPhSendIOCTL( IOCTL_CDRW_SYNC_CACHE, Vcb->TargetDeviceObject, NULL,0, NULL,0, FALSE, NULL); if(OS_SUCCESS(RC)) { // clear LAST_WRITE flag Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE; } return RC;} // end UDFSyncCache()
OSSTATUSUDFReallocTrackMap( IN PVCB Vcb, IN uint32 TrackNum ){#ifdef _BROWSE_UDF_ if(Vcb->TrackMap) { MyFreePool__(Vcb->TrackMap); Vcb->TrackMap = NULL; } Vcb->TrackMap = (PUDFTrackMap) MyAllocatePool__(NonPagedPool, TrackNum*sizeof(UDFTrackMap)); if(!Vcb->TrackMap) { return STATUS_INSUFFICIENT_RESOURCES; }#endif //_BROWSE_UDF_ RtlZeroMemory(Vcb->TrackMap,TrackNum*sizeof(UDFTrackMap)); return STATUS_SUCCESS;} // end UDFReallocTrackMap()
#ifdef _BROWSE_UDF_
OSSTATUS__fastcallUDFTIOVerify( IN void* _Vcb, IN void* Buffer, // Target buffer IN SIZE_T Length, IN uint32 LBA, OUT PSIZE_T IOBytes, IN uint32 Flags ){ OSSTATUS RC = STATUS_SUCCESS; uint32 i, j; SIZE_T mask; uint32 lba0, len, lba1; PUCHAR tmp_buff; PUCHAR p; PCHAR cached_block; SIZE_T tmp_wb; BOOLEAN need_remap; OSSTATUS final_RC = STATUS_SUCCESS; BOOLEAN zero; BOOLEAN non_zero; BOOLEAN packet_ok; BOOLEAN free_tmp = FALSE; BOOLEAN single_packet = FALSE;
#define Vcb ((PVCB)_Vcb) // ATTENTION! Do not touch bad block bitmap here, since it describes PHYSICAL addresses WITHOUT remapping, // while here we work with LOGICAL addresses
if(Vcb->VerifyCtx.ItemCount > UDF_MAX_VERIFY_CACHE) { UDFVVerify(Vcb, 0/*UFD_VERIFY_FLAG_WAIT*/); }
UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE); Flags |= PH_IO_LOCKED;
tmp_wb = (SIZE_T)_Vcb; if(Flags & PH_EX_WRITE) { UDFPrint(("IO-Write-Verify\n")); RC = UDFTWrite(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_VCB_IN_RETLEN); } else { UDFPrint(("IO-Read-Verify\n")); RC = UDFTRead(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_VCB_IN_RETLEN); } (*IOBytes) = tmp_wb;
switch(RC) { default: UDFReleaseResource(&(Vcb->IoResource)); return RC; case STATUS_FT_WRITE_RECOVERY: case STATUS_DEVICE_DATA_ERROR: case STATUS_IO_DEVICE_ERROR: break; /* FALL THROUGH */ } // end switch(RC)
if(!Vcb->SparingCount || !Vcb->SparingCountFree || Vcb->CDR_Mode) { UDFPrint(("Can't remap\n")); UDFReleaseResource(&(Vcb->IoResource)); return RC; }
if(Flags & PH_EX_WRITE) { UDFPrint(("Write failed, try relocation\n")); } else { if(Vcb->Modified) { UDFPrint(("Read failed, try relocation\n")); } else { UDFPrint(("no remap on not modified volume\n")); UDFReleaseResource(&(Vcb->IoResource)); return RC; } } if(Flags & PH_LOCK_CACHE) { UDFReleaseResource(&(Vcb->IoResource)); WCacheStartDirect__(&(Vcb->FastCache), Vcb, TRUE); UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE); }
Flags &= ~PH_KEEP_VERIFY_CACHE;
// NOTE: SparingBlockSize may be not equal to PacketSize // perform recovery mask = Vcb->SparingBlockSize-1; lba0 = LBA & ~mask; len = ((LBA+(Length>>Vcb->BlockSizeBits)+mask) & ~mask) - lba0; j=0; if((lba0 == LBA) && (len == mask+1) && (len == (Length>>Vcb->BlockSizeBits))) { single_packet = TRUE; tmp_buff = NULL; } else { tmp_buff = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, Vcb->SparingBlockSize << Vcb->BlockSizeBits, 'bNWD'); if(!tmp_buff) { UDFPrint((" can't alloc tmp\n")); UDFReleaseResource(&(Vcb->IoResource)); return STATUS_DEVICE_DATA_ERROR; } free_tmp = TRUE; }
for(i=0; i<len; i++) { if(!Vcb->SparingCountFree) { UDFPrint((" no more free spare blocks, abort verification\n")); break; } UDFPrint((" read LBA %x (%x)\n", lba0+i, j)); if(!j) { need_remap = FALSE; lba1 = lba0+i; non_zero = FALSE; if(single_packet) { // single packet requested tmp_buff = (PUCHAR)Buffer; if(Flags & PH_EX_WRITE) { UDFPrint((" remap single write\n")); UDFPrint((" try del from verify cache @ %x, %x\n", lba0, len)); UDFVForget(Vcb, len, UDFRelocateSector(Vcb, lba0), 0); goto do_remap; } else { UDFPrint((" recover and remap single read\n")); } } } p = tmp_buff+(j<<Vcb->BlockSizeBits); // not cached, try to read // prepare for error, if block cannot be read, assume it is zero-filled RtlZeroMemory(p, Vcb->BlockSize);
// check if block valid if(Vcb->BSBM_Bitmap) { if(UDFGetBit((uint32*)(Vcb->BSBM_Bitmap), UDFRelocateSector(Vcb, lba0+i))) { UDFPrint((" remap: known BB @ %x, mapped to %x\n", lba0+i, UDFRelocateSector(Vcb, lba0+i))); need_remap = TRUE; } } zero = FALSE; if(Vcb->FSBM_Bitmap) { if(UDFGetFreeBit((uint32*)(Vcb->FSBM_Bitmap), lba0+i)) { UDFPrint((" unused @ %x\n", lba0+i)); zero = TRUE; } } if(!zero && Vcb->ZSBM_Bitmap) { if(UDFGetZeroBit((uint32*)(Vcb->ZSBM_Bitmap), lba0+i)) { UDFPrint((" unused @ %x (Z)\n", lba0+i)); zero = TRUE; } } non_zero |= !zero;
if(!j) { packet_ok = FALSE; if(!single_packet) { // try to read entire packet, this returs error more often then sequential reading of all blocks one by one tmp_wb = (SIZE_T)_Vcb; RC = UDFTRead(_Vcb, p, Vcb->SparingBlockSize << Vcb->BlockSizeBits, lba0+i, &tmp_wb, Flags | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN); } else { // Note: we get here ONLY if original request failed // do not retry if it was single-packet request RC = STATUS_UNSUCCESSFUL; } if(RC == STATUS_SUCCESS) { UDFPrint((" packet ok @ %x\n", lba0+i)); packet_ok = TRUE; i += Vcb->SparingBlockSize-1; continue; } else { need_remap = TRUE; } }
if(!zero) { if(WCacheIsCached__(&(Vcb->FastCache), lba0+i, 1)) { // even if block is cached, we have to verify if it is readable if(!packet_ok && !UDFVIsStored(Vcb, lba0+i)) {
tmp_wb = (SIZE_T)_Vcb; RC = UDFTRead(_Vcb, p, Vcb->BlockSize, lba0+i, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN); if(!OS_SUCCESS(RC)) { UDFPrint((" Found BB @ %x\n", lba0+i)); }
} RC = WCacheDirect__(&(Vcb->FastCache), _Vcb, lba0+i, FALSE, &cached_block, TRUE/* cached only */); } else { cached_block = NULL; if(!packet_ok) { RC = STATUS_UNSUCCESSFUL; } else { RC = STATUS_SUCCESS; } } if(OS_SUCCESS(RC)) { // cached or successfully read if(cached_block) { // we can get from cache the most fresh data RtlCopyMemory(p, cached_block, Vcb->BlockSize); }
} else { if(!UDFVIsStored(Vcb, lba0+i)) { tmp_wb = (SIZE_T)_Vcb; RC = UDFTRead(_Vcb, p, Vcb->BlockSize, lba0+i, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN); } else { // get it from verify-cache RC = STATUS_UNSUCCESSFUL; } if(!OS_SUCCESS(RC)) {/* UDFPrint((" retry @ %x\n", lba0+i)); tmp_wb = (uint32)_Vcb; RC = UDFTRead(_Vcb, p, Vcb->BlockSize, lba0+i, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN);*/ UDFPrint((" try get from verify cache @ %x\n", lba0+i)); RC = UDFVRead(Vcb, p, 1, UDFRelocateSector(Vcb, lba0+i), Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER); need_remap = TRUE; } } } else { RtlZeroMemory(p, Vcb->BlockSize); } if(!packet_ok) { UDFPrint((" try del from verify cache @ %x\n", lba0+i)); RC = UDFVForget(Vcb, 1, UDFRelocateSector(Vcb, lba0+i), 0); }
if(!packet_ok || need_remap) { UDFPrint((" block in bad packet @ %x\n", lba0+i)); if(Vcb->BSBM_Bitmap) { UDFSetBit(Vcb->BSBM_Bitmap, lba0+i); } if(Vcb->FSBM_Bitmap) { UDFSetUsedBit(Vcb->FSBM_Bitmap, lba0+i); } }
j++; if(j >= Vcb->SparingBlockSize) { // remap this packet if(need_remap) { ASSERT(!packet_ok); if(!non_zero) { UDFPrint((" forget Z packet @ %x\n", lba1)); UDFUnmapRange(Vcb, lba1, Vcb->SparingBlockSize); RC = STATUS_SUCCESS; } else {do_remap: for(j=0; j<3; j++) { UDFPrint((" remap packet @ %x\n", lba1)); RC = UDFRemapPacket(Vcb, lba1, FALSE); if(!OS_SUCCESS(RC)) { if(RC == STATUS_SHARING_VIOLATION) { UDFPrint((" remap2\n")); // remapped location have died RC = UDFRemapPacket(Vcb, lba1, TRUE); } if(!OS_SUCCESS(RC)) { // packet cannot be remapped :( RC = STATUS_DEVICE_DATA_ERROR; } } UDFPrint((" remap status %x\n", RC)); if(OS_SUCCESS(RC)) { // write to remapped area tmp_wb = (SIZE_T)_Vcb; RC = UDFTWrite(_Vcb, tmp_buff, Vcb->SparingBlockSize << Vcb->BlockSizeBits, lba1, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN); UDFPrint((" write status %x\n", RC)); if(RC != STATUS_SUCCESS) { // will be remapped UDFPrint((" retry remap\n"));
// Note: when remap of already remapped block is requested, verify of // entire sparing are will be performed.
} else { UDFPrint((" remap OK\n")); break; } } else { UDFPrint((" failed remap\n")); break; } } // for } if(!OS_SUCCESS(RC) && !OS_SUCCESS(final_RC)) { final_RC = RC; } } else { UDFPrint((" NO remap for @ %x\n", (lba0+i) & ~mask)); } j=0; } } if(free_tmp) { DbgFreePool(tmp_buff); }
tmp_wb = (SIZE_T)_Vcb; if(Flags & PH_EX_WRITE) { UDFPrint(("IO-Write-Verify (2)\n")); //RC = UDFTWrite(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_VCB_IN_RETLEN); } else { UDFPrint(("IO-Read-Verify (2)\n")); RC = UDFTRead(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_VCB_IN_RETLEN); } (*IOBytes) = tmp_wb; UDFPrint(("Final %x\n", RC));
UDFReleaseResource(&(Vcb->IoResource)); if(Flags & PH_LOCK_CACHE) { WCacheEODirect__(&(Vcb->FastCache), Vcb); }
return RC;} // end UDFTIOVerify()
OSSTATUSUDFTWriteVerify( IN void* _Vcb, IN void* Buffer, // Target buffer IN SIZE_T Length, IN uint32 LBA, OUT PSIZE_T WrittenBytes, IN uint32 Flags ){ return UDFTIOVerify(_Vcb, Buffer, Length, LBA, WrittenBytes, Flags | PH_VCB_IN_RETLEN | PH_EX_WRITE | PH_KEEP_VERIFY_CACHE);} // end UDFTWriteVerify()
OSSTATUSUDFTReadVerify( IN void* _Vcb, IN void* Buffer, // Target buffer IN SIZE_T Length, IN uint32 LBA, OUT PSIZE_T ReadBytes, IN uint32 Flags ){ return UDFTIOVerify(_Vcb, Buffer, Length, LBA, ReadBytes, Flags | PH_VCB_IN_RETLEN | PH_KEEP_VERIFY_CACHE);} // end UDFTReadVerify()#endif //_BROWSE_UDF_
/* This routine performs low-level write
ATTENTION! When we are in Variable-Packet mode (CDR_Mode = TRUE) LBA is ignored and assumed to be equal to NWA by CD-R(W) driver */OSSTATUSUDFTWrite( IN void* _Vcb, IN void* Buffer, // Target buffer IN SIZE_T Length, IN uint32 LBA, OUT PSIZE_T WrittenBytes, IN uint32 Flags ){#ifndef UDF_READ_ONLY_BUILD#define Vcb ((PVCB)_Vcb)
#ifdef _BROWSE_UDF_ PEXTENT_MAP RelocExtent; PEXTENT_MAP RelocExtent_saved = NULL;#endif //_BROWSE_UDF_ uint32 retry; BOOLEAN res_acq = FALSE;
OSSTATUS RC = STATUS_SUCCESS; uint32 rLba; uint32 BCount; uint32 i;
#ifdef DBG //ASSERT(!(LBA & (32-1)));#endif //DBG
(*WrittenBytes) = 0; BCount = Length>>Vcb->BlockSizeBits;
UDFPrint(("TWrite %x (%x)\n", LBA, BCount));#ifdef _BROWSE_UDF_ if(Vcb->VCBFlags & UDF_VCB_FLAGS_DEAD) { UDFPrint(("DEAD\n")); return STATUS_NO_SUCH_DEVICE; }
Vcb->VCBFlags |= (UDF_VCB_SKIP_EJECT_CHECK | UDF_VCB_LAST_WRITE); if(!Vcb->CDR_Mode) { RelocExtent = UDFRelocateSectors(Vcb, LBA, BCount); if(!RelocExtent) { UDFPrint(("can't relocate\n")); return STATUS_INSUFFICIENT_RESOURCES; } rLba = LBA; } else { RelocExtent = UDF_NO_EXTENT_MAP; rLba = Vcb->NWA; }#else //_BROWSE_UDF_ rLba = LBA;#endif //_BROWSE_UDF_
#ifdef DBG //ASSERT(!(rLba & (32-1)));#endif //DBG
_SEH2_TRY {#ifdef _BROWSE_UDF_
if(!(Flags & PH_IO_LOCKED)) { UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE); res_acq = TRUE; }
if(RelocExtent == UDF_NO_EXTENT_MAP) {#endif //_BROWSE_UDF_ retry = UDF_WRITE_MAX_RETRY;retry_1: RC = UDFPrepareForWriteOperation(Vcb, rLba, BCount); if(!OS_SUCCESS(RC)) { UDFPrint(("prepare failed\n")); try_return(RC); } if(Flags & PH_VCB_IN_RETLEN) { (*WrittenBytes) = (ULONG_PTR)Vcb; } RC = UDFPhWriteVerifySynchronous(Vcb->TargetDeviceObject, Buffer, Length, ((uint64)rLba) << Vcb->BlockSizeBits, WrittenBytes, Flags);#ifdef _BROWSE_UDF_ Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;#endif //_BROWSE_UDF_ if(!OS_SUCCESS(RC) && OS_SUCCESS(RC = UDFRecoverFromError(Vcb, TRUE, RC, rLba, BCount, &retry)) ) goto retry_1; UDFUpdateNWA((PVCB)_Vcb, rLba, BCount, RC); try_return(RC);#ifdef _BROWSE_UDF_ } // write according to relocation table RelocExtent_saved = RelocExtent; for(i=0; RelocExtent->extLength; i++, RelocExtent++) { SIZE_T _WrittenBytes; rLba = RelocExtent->extLocation; BCount = RelocExtent->extLength>>Vcb->BlockSizeBits; retry = UDF_WRITE_MAX_RETRY;retry_2: RC = UDFPrepareForWriteOperation(Vcb, rLba, BCount); if(!OS_SUCCESS(RC)) { UDFPrint(("prepare failed (2)\n")); break; } if(Flags & PH_VCB_IN_RETLEN) { _WrittenBytes = (ULONG_PTR)Vcb; } RC = UDFPhWriteVerifySynchronous(Vcb->TargetDeviceObject, Buffer, RelocExtent->extLength, ((uint64)rLba) << Vcb->BlockSizeBits, &_WrittenBytes, Flags); Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK; if(!OS_SUCCESS(RC) && OS_SUCCESS(RC = UDFRecoverFromError(Vcb, TRUE, RC, rLba, BCount, &retry)) ) goto retry_2; UDFUpdateNWA((PVCB)_Vcb, rLba, BCount, RC); LBA += BCount; (*WrittenBytes) += _WrittenBytes; if(!OS_SUCCESS(RC)) break; *((uint32*)&Buffer) += RelocExtent->extLength; }#endif //_BROWSE_UDF_try_exit: NOTHING; } _SEH2_FINALLY { if(res_acq) { UDFReleaseResource(&(Vcb->IoResource)); }#ifdef _BROWSE_UDF_ if(RelocExtent_saved) { MyFreePool__(RelocExtent_saved); }#endif //_BROWSE_UDF_ } _SEH2_END; UDFPrint(("TWrite: %x\n", RC)); return RC;
#undef Vcb#else //UDF_READ_ONLY_BUILD return STATUS_ACCESS_DENIED;#endif //UDF_READ_ONLY_BUILD} // end UDFTWrite()
/* This routine performs low-level read */OSSTATUSUDFTRead( IN void* _Vcb, IN void* Buffer, // Target buffer IN SIZE_T Length, IN uint32 LBA, OUT PSIZE_T ReadBytes, IN uint32 Flags ){ uint32 rLba; OSSTATUS RC = STATUS_SUCCESS; uint32 retry; PVCB Vcb = (PVCB)_Vcb; uint32 BCount = Length >> Vcb->BlockSizeBits; uint32 i;#ifdef _BROWSE_UDF_ PEXTENT_MAP RelocExtent; PEXTENT_MAP RelocExtent_saved = NULL; BOOLEAN res_acq = FALSE;// LARGE_INTEGER delay; Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
ASSERT(Buffer);
(*ReadBytes) = 0;
if(Vcb->VCBFlags & UDF_VCB_FLAGS_DEAD) return STATUS_NO_SUCH_DEVICE;
RelocExtent = UDFRelocateSectors(Vcb, LBA, BCount); if(!RelocExtent) return STATUS_INSUFFICIENT_RESOURCES;
_SEH2_TRY {
if(!(Flags & PH_IO_LOCKED)) { UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE); res_acq = TRUE; }
if(RelocExtent == UDF_NO_EXTENT_MAP) { rLba = LBA; if(rLba >= (Vcb->CDR_Mode ? Vcb->NWA : Vcb->LastLBA + 1)) { RtlZeroMemory(Buffer, Length); try_return(RC = STATUS_SUCCESS); } retry = UDF_WRITE_MAX_RETRY;retry_1: RC = UDFPrepareForReadOperation(Vcb, rLba, Length >> Vcb->BlockSizeBits); if(!OS_SUCCESS(RC)) try_return(RC); rLba = UDFFixFPAddress(Vcb, rLba);#else rLba = LBA; retry = UDF_WRITE_MAX_RETRY;retry_1: RC = UDFPrepareForReadOperation(Vcb, rLba, Length >> Vcb->BlockSizeBits); if(!OS_SUCCESS(RC)) return RC; // this is for !_BROWSE_UDF only#endif //_BROWSE_UDF_ if(Flags & PH_VCB_IN_RETLEN) { (*ReadBytes) = (SIZE_T)Vcb; } RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, Buffer, Length, ((uint64)rLba) << Vcb->BlockSizeBits, ReadBytes, Flags); Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE;#ifdef _BROWSE_UDF_ Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;#endif //_BROWSE_UDF_ if(!OS_SUCCESS(RC) && OS_SUCCESS(RC = UDFRecoverFromError(Vcb, FALSE, RC, rLba, BCount, &retry)) ) { if(RC != STATUS_BUFFER_ALL_ZEROS) { goto retry_1; } RtlZeroMemory(Buffer, Length); (*ReadBytes) = Length; RC = STATUS_SUCCESS; }#ifdef _BROWSE_UDF_ try_return(RC); } // read according to relocation table RelocExtent_saved = RelocExtent; for(i=0; RelocExtent->extLength; i++, RelocExtent++) { SIZE_T _ReadBytes; rLba = RelocExtent->extLocation; if(rLba >= (Vcb->CDR_Mode ? Vcb->NWA : Vcb->LastLBA + 1)) { RtlZeroMemory(Buffer, _ReadBytes = RelocExtent->extLength); RC = STATUS_SUCCESS; goto TR_continue; } BCount = RelocExtent->extLength>>Vcb->BlockSizeBits; retry = UDF_WRITE_MAX_RETRY;retry_2: RC = UDFPrepareForReadOperation(Vcb, rLba, RelocExtent->extLength >> Vcb->BlockSizeBits); if(!OS_SUCCESS(RC)) break; rLba = UDFFixFPAddress(Vcb, rLba); if(Flags & PH_VCB_IN_RETLEN) { _ReadBytes = (SIZE_T)Vcb; } RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, Buffer, RelocExtent->extLength, ((uint64)rLba) << Vcb->BlockSizeBits, &_ReadBytes, Flags); Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE; Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK; if(!OS_SUCCESS(RC) && OS_SUCCESS(RC = UDFRecoverFromError(Vcb, FALSE, RC, rLba, BCount, &retry)) ) { if(RC != STATUS_BUFFER_ALL_ZEROS) { goto retry_2; } RtlZeroMemory(Buffer, RelocExtent->extLength); _ReadBytes = RelocExtent->extLength; RC = STATUS_SUCCESS; }TR_continue: (*ReadBytes) += _ReadBytes; if(!OS_SUCCESS(RC)) break; *((uint32*)&Buffer) += RelocExtent->extLength; }try_exit: NOTHING; } _SEH2_FINALLY { if(res_acq) { UDFReleaseResource(&(Vcb->IoResource)); } if(RelocExtent_saved) { MyFreePool__(RelocExtent_saved); } } _SEH2_END;#endif //_BROWSE_UDF_ return RC;} // end UDFTRead()
#ifdef UDF_ASYNC_IO/* This routine performs asynchronous low-level read Is not used now. */OSSTATUSUDFTReadAsync( IN void* _Vcb, IN void* _WContext, IN void* Buffer, // Target buffer IN SIZE_T Length, IN uint32 LBA, OUT PSIZE_T ReadBytes ){ PEXTENT_MAP RelocExtent; PEXTENT_MAP RelocExtent_saved; OSSTATUS RC = STATUS_SUCCESS;// LARGE_INTEGER delay; uint32 retry = UDF_READ_MAX_RETRY; PVCB Vcb = (PVCB)_Vcb; Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK; uint32 rLba; uint32 BCount;
ASSERT(Buffer);
(*ReadBytes) = 0;
RelocExtent = UDFRelocateSectors(Vcb, LBA, BCount = Length >> Vcb->BlockSizeBits); if(!RelocExtent) return STATUS_INSUFFICIENT_RESOURCES; if(RelocExtent == UDF_NO_EXTENT_MAP) { rLba = LBA; if(rLba >= (Vcb->CDR_Mode ? Vcb->NWA : Vcb->LastLBA + 1)) { RtlZeroMemory(Buffer, Length); return STATUS_SUCCESS; }retry_1: RC = UDFPrepareForReadOperation(Vcb, rLba, BCount); if(!OS_SUCCESS(RC)) return RC; rLba = UDFFixFPAddress(Vcb, rLba); RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, Buffer, Length, ((uint64)rLba) << Vcb->BlockSizeBits, ReadBytes, 0); Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE; Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK; if(!OS_SUCCESS(RC) && OS_SUCCESS(RC = UDFRecoverFromError(Vcb, FALSE, RC, rLba, BCount, &retry)) ) goto retry_1; return RC; } // read according to relocation table RelocExtent_saved = RelocExtent; for(uint32 i=0; RelocExtent->extLength; i++, RelocExtent++) { SIZE_T _ReadBytes; rLba = RelocExtent->extLocation; if(rLba >= (Vcb->CDR_Mode ? Vcb->NWA : Vcb->LastLBA + 1)) { RtlZeroMemory(Buffer, _ReadBytes = RelocExtent->extLength); RC = STATUS_SUCCESS; goto TR_continue; } BCount = RelocExtent->extLength>>Vcb->BlockSizeBits;retry_2: RC = UDFPrepareForReadOperation(Vcb, rLba, RelocExtent->extLength >> Vcb->BlockSizeBits); if(!OS_SUCCESS(RC)) break; rLba = UDFFixFPAddress(Vcb, rLba); RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, Buffer, RelocExtent->extLength, ((uint64)rLba) << Vcb->BlockSizeBits, &_ReadBytes, 0); Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE; Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK; if(!OS_SUCCESS(RC) && OS_SUCCESS(RC = UDFRecoverFromError(Vcb, FALSE, RC, rLba, BCount, &retry)) ) goto retry_2;TR_continue: (*ReadBytes) += _ReadBytes; if(!OS_SUCCESS(RC)) break; *((uint32*)&Buffer) += RelocExtent->extLength; } MyFreePool__(RelocExtent_saved); return RC;} // end UDFTReadAsync()
#endif //UDF_ASYNC_IO
/*
*/NTSTATUSUDFSetMRWMode( IN PVCB Vcb ){ GET_MRW_MODE_USER_OUT MRWPage; OSSTATUS RC;
if(Vcb->MediaClassEx != CdMediaClass_CDRW) return STATUS_SUCCESS;//#ifdef _BROWSE_UDF_ if(Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM) return STATUS_SUCCESS;//#endif //_BROWSE_UDF_
if(!Vcb->MRWStatus) { UDFPrint(("Non-MRW disk. Skip setting MRW_MODE\n")); return STATUS_SUCCESS; } UDFPrint(("try set MRW_MODE\n")); RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_MRW_MODE, Vcb->TargetDeviceObject, NULL,0, (PVOID)&MRWPage,sizeof(MRWPage), FALSE, NULL); if(!NT_SUCCESS(RC)) { return RC; } UDFPrint(("GET_MRW_MODE ok (current %x)\n", MRWPage.AddressMode)); MRWPage.AddressMode = Vcb->MRWStatus ? 0 : MrwPage_use_GAA; UDFPrint(("SET_MRW_MODE %x\n", MRWPage.AddressMode)); RC = UDFPhSendIOCTL(IOCTL_CDRW_SET_MRW_MODE, Vcb->TargetDeviceObject, (PVOID)&MRWPage,sizeof(MRWPage), NULL,0, FALSE, NULL); UDFPrint(("SET_MRW_MODE status %x\n", RC));
return STATUS_SUCCESS;} // end UDFSetMRWMode()
OSSTATUSUDFDoOPC( IN PVCB Vcb ){ OSSTATUS RC; if(Vcb->OPCNum && !Vcb->OPCDone) { UDFPrint(("UDFDoOPC\n")); if(!Vcb->OPCh) { Vcb->OPCh = (PSEND_OPC_INFO_HEADER_USER_IN)MyAllocatePool__(NonPagedPool, sizeof(SEND_OPC_INFO_HEADER_USER_IN) ); } if(!Vcb->OPCh) return STATUS_INSUFFICIENT_RESOURCES; Vcb->OPCh->DoOpc = TRUE; Vcb->OPCh->OpcBlocksNumber = 0; RC = UDFPhSendIOCTL(IOCTL_CDRW_SEND_OPC_INFO, Vcb->TargetDeviceObject, (void*)(Vcb->OPCh),sizeof(SEND_OPC_INFO_HEADER_USER_IN), NULL,0, FALSE, NULL); if(!OS_SUCCESS(RC)) { UDFPrint(("UDFDoOPC failed\n")); Vcb->OPCNum = 0;// Vcb->VCBFlags |= UDF_VCB_FLAGS_OPC_FAILED; } Vcb->OPCDone = TRUE; } return RC;} // end UDFDoOPC()
/* This routine performs media-type dependent preparations for write operation.
For CDR/RW it sets WriteParameters according to track parameters, in some cases issues SYNC_CACHE command. It can also send OPC info if requered. If write-requested block is located beyond last formatted LBA on incompletely formatted DVD media, this routine performs all neccessary formatting operations in order to satisfy subsequent write request. */OSSTATUSUDFPrepareForWriteOperation( IN PVCB Vcb, IN uint32 Lba, IN uint32 BCount ){#ifndef UDF_READ_ONLY_BUILD#ifdef UDF_FORMAT_MEDIA PUDFFmtState fms = Vcb->fms;#else #define fms FALSE#endif //UDF_FORMAT_MEDIA
#ifdef _UDF_STRUCTURES_H_ if(Vcb->BSBM_Bitmap) { ULONG i; for(i=0; i<BCount; i++) { if(UDFGetBit((uint32*)(Vcb->BSBM_Bitmap), Lba+i)) { UDFPrint(("W: Known BB @ %#x\n", Lba)); //return STATUS_FT_WRITE_RECOVERY; // this shall not be treated as error and // we shall get IO request to BAD block return STATUS_DEVICE_DATA_ERROR; } } }#endif //_UDF_STRUCTURES_H_
Vcb->VCBFlags |= UDF_VCB_LAST_WRITE;
if(#ifdef _BROWSE_UDF_ (((Vcb->FsDeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM) || !(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED) || (Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK)) && !fms ) ||#endif //_BROWSE_UDF_#ifdef UDF_FORMAT_MEDIA (fms && fms->SkipPrepareW) ||#endif //UDF_FORMAT_MEDIA !(Vcb->VCBFlags & UDF_VCB_FLAGS_OUR_DEVICE_DRIVER) ) { UDFPrint(("Skip prepare for Write @%x\n", Lba)); return STATUS_SUCCESS; }
// check if the device requires OPC before each write operation UDFDoOPC(Vcb);
if(Vcb->SyncCacheState == SYNC_CACHE_RECOVERY_ATTEMPT) { Vcb->SyncCacheState = SYNC_CACHE_RECOVERY_RETRY; } else { Vcb->SyncCacheState = SYNC_CACHE_RECOVERY_NONE; } if(Vcb->LastModifiedTrack && (Vcb->TrackMap[Vcb->LastModifiedTrack].FirstLba <= Lba) && (Vcb->TrackMap[Vcb->LastModifiedTrack].LastLba >= Lba) && !( (Vcb->MediaClassEx == CdMediaClass_DVDRW || Vcb->MediaClassEx == CdMediaClass_DVDpRW || Vcb->MediaClassEx == CdMediaClass_DVDRAM || Vcb->MRWStatus == DiscInfo_BGF_Interrupted || Vcb->MRWStatus == DiscInfo_BGF_InProgress) && (Lba > Vcb->LastLBA)) ) { // Ok, we needn't change Write Parameters// if(Vcb->TrackMap[Vcb->LastModifiedTrack].Flags & TrackMap_Try_variation)// Vcb->TrackMap[Vcb->LastModifiedTrack].Flags |= TrackMap_Use_variation; UDFPrint(("Skip prepare for Write (2) @%x\n", Lba)); return STATUS_SUCCESS; }
UDFSetMRWMode(Vcb);
if(!UDFIsWriteParamsReq(Vcb)) {#ifdef UDF_FORMAT_MEDIA if(fms) { return STATUS_SUCCESS; }#endif //UDF_FORMAT_MEDIA }
for(uint32 i=Vcb->FirstTrackNum; i<=Vcb->LastTrackNum; i++) { if((Vcb->TrackMap[i].FirstLba > Lba) || (Vcb->TrackMap[i].LastLba < Lba)) { //UDFPrint(("not in track %d\n")); continue; } OSSTATUS RC; PGET_WRITE_MODE_USER_OUT WParams;
if(!UDFIsWriteParamsReq(Vcb)) { RC = STATUS_SUCCESS; goto check_dvd_bg_format; }
if(!Vcb->WParams) { Vcb->WParams = (PGET_WRITE_MODE_USER_OUT)MyAllocatePool__(NonPagedPool, 512); } if(!(WParams = Vcb->WParams)) { UDFPrint(("!WParams\n")); return STATUS_INSUFFICIENT_RESOURCES; }
RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_WRITE_MODE, Vcb->TargetDeviceObject, NULL,0, (void*)(Vcb->WParams),sizeof(GET_WRITE_MODE_USER_OUT), FALSE, NULL); if(!OS_SUCCESS(RC)) {#ifdef UDF_FORMAT_MEDIA if(fms) { fms->SkipPrepareW = 1; MyFreePool__(WParams); return STATUS_SUCCESS; }#endif //UDF_FORMAT_MEDIA UDFPrint(("!get WParams\n")); return RC; } // clear unnecassary flags WParams->Byte2.Flags &= ~WParam_TestWrite; WParams->Byte2.Flags &= ~WParam_WType_Mask; // select packet writing WParams->Byte2.Flags |= WParam_WType_Packet;
WParams->Byte3.Flags &= ~(WParam_TrkMode_Mask | WParam_TrkMode_AllowCpy | WParam_Copy); WParams->Byte3.Flags |= Vcb->TrackMap[i].TrackParam & (WParam_TrkMode_Mask | WParam_TrkMode_AllowCpy | WParam_Copy);
// set packet type (VP/FP)// if(opt_partition == PT_VAT15 ||// opt_blank_vat15) if(WParams->Byte2.Flags & WParam_LS_V) { WParams->LinkSize = 7; }
if(Vcb->TrackMap[i].DataParam & TrkInfo_Packet) { if((Vcb->TrackMap[i].DataParam & TrkInfo_FP) && !Vcb->CDR_Mode) { WParams->Byte3.Flags |= WParam_FP; } else { WParams->Byte3.Flags &= ~WParam_FP; } } else { if(!Vcb->CDR_Mode) { WParams->Byte3.Flags |= WParam_FP; } else { WParams->Byte3.Flags &= ~WParam_FP; } }
// select multisession mode WParams->Byte3.Flags &= ~WParam_MultiSes_Mask; if((Vcb->DiscStat & DiscInfo_Disk_Mask) == DiscInfo_Disk_Appendable) { WParams->Byte3.Flags |= WParam_Multises_Multi; } else if(Vcb->LastSession > 1) { WParams->Byte3.Flags |= WParam_Multises_Final; } else { WParams->Byte3.Flags |= WParam_Multises_None; } // set sector mode (Mode1/XA) WParams->Byte4.Flags &= ~WParam_BlkType_Mask; if((Vcb->TrackMap[i].DataParam & TrkInfo_Dat_Mask) == TrkInfo_Dat_XA) { // XA Mode2 WParams->Byte4.Flags |= WParam_BlkType_M2XAF1_2048; WParams->SesFmt = WParam_SesFmt_CdRomXa; } else if((Vcb->TrackMap[i].DataParam & TrkInfo_Dat_Mask) == TrkInfo_Dat_Mode1) { // Mode1 WParams->Byte4.Flags |= WParam_BlkType_M1_2048; WParams->SesFmt = WParam_SesFmt_CdRom; } else {#ifdef UDF_FORMAT_MEDIA if(fms) { fms->SkipPrepareW = 1; MyFreePool__(WParams); return STATUS_SUCCESS; }#endif //UDF_FORMAT_MEDIA UDFPrint((" inv sector mode\n")); return STATUS_INVALID_PARAMETER; } // set packet size *((uint32*)&(WParams->PacketSize)) = BCount; *((uint32*)&(WParams->SubHeader)) = 0; // set additional flags for VP
if(Vcb->CDR_Mode) {// if(opt_partition == PT_VAT15) WParams->SubHeader.Params.Params1.SubMode = WParam_SubHdr_SubMode1; } WParams->PageLength = sizeof(GET_WRITE_MODE_USER_OUT)-2; WParams->PageCode = MODE_PAGE_WRITE_PARAMS; // apply write parameters RC = UDFPhSendIOCTL(IOCTL_CDRW_SET_WRITE_MODE, Vcb->TargetDeviceObject, (void*)WParams,sizeof(SET_WRITE_MODE_USER_IN), NULL,0,FALSE,NULL);
#ifdef UDF_FORMAT_MEDIA if(fms) { if(!NT_SUCCESS(RC)) { fms->SkipPrepareW = 1; MyFreePool__(WParams); return STATUS_SUCCESS; }
RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_WRITE_MODE, Vcb->TargetDeviceObject, NULL,0, (PVOID)WParams,sizeof(GET_WRITE_MODE_USER_OUT), FALSE, NULL); if(!NT_SUCCESS(RC)) { MyFreePool__(WParams); return RC; }
if(fms->opt_partition == PT_VAT15 || fms->opt_blank_vat15) { if(WParams->Byte3.Flags & WParam_FP) { MyFreePool__(WParams); return STATUS_INVALID_DEVICE_STATE; } } else { if(!(WParams->Byte3.Flags & WParam_FP)) { MyFreePool__(WParams); return STATUS_INVALID_DEVICE_STATE; } } }#endif //UDF_FORMAT_MEDIA
// switch to random access mode ((PSET_RANDOM_ACCESS_USER_IN)WParams)->RandomAccessMode = Vcb->CDR_Mode ? FALSE : TRUE;// ((PSET_RANDOM_ACCESS_USER_IN)WParams)->RandomAccessMode = (opt_partition != PT_VAT15) ? TRUE : FALSE; RC = UDFPhSendIOCTL(IOCTL_CDRW_SET_RANDOM_ACCESS, Vcb->TargetDeviceObject, (void*)WParams,sizeof(SET_RANDOM_ACCESS_USER_IN), NULL,0,FALSE, NULL);
check_dvd_bg_format:
UDFPrint((" check BGF\n")); if(!Vcb->CDR_Mode) { if(OS_SUCCESS(RC)) { Vcb->LastModifiedTrack = i; if(!(Vcb->TrackMap[i].Flags & TrackMap_Use_variation)) { if(Vcb->TrackMap[i].Flags & TrackMap_Try_variation) { Vcb->TrackMap[i].Flags |= TrackMap_Use_variation; } else { Vcb->TrackMap[i].Flags |= TrackMap_Try_variation; } } } } else { Vcb->LastModifiedTrack = 0; }// fms->SkipPrepareW = 1;
if((Vcb->MediaClassEx == CdMediaClass_DVDRW || Vcb->MediaClassEx == CdMediaClass_DVDpRW || Vcb->MediaClassEx == CdMediaClass_DVDRAM || Vcb->MRWStatus == DiscInfo_BGF_Interrupted ) && (Lba > Vcb->LastLBA)) {
ULONG fLba; SIZE_T WrittenBytes; ULONG PSz = BCount << Vcb->BlockSizeBits;#ifdef _BROWSE_UDF_ ULONG retry;#endif //_BROWSE_UDF_ PFORMAT_CDRW_PARAMETERS_USER_IN ForBuf;
ASSERT((Vcb->LastLBA+1) == Vcb->NWA);
if(Lba+BCount <= (Vcb->LastLBA+1) ) { UDFPrint(("DVD cont. fmt, LBA+BCount<=NWA, exiting\n")); return STATUS_SUCCESS; } if((Vcb->MRWStatus != DiscInfo_BGF_Interrupted) && (Lba <= (Vcb->LastLBA+1)) ) { UDFPrint(("!PausedBGF + DVD cont. fmt, LBA<=NWA, exiting\n")); return STATUS_SUCCESS; }
if(Vcb->MRWStatus == DiscInfo_BGF_Interrupted) { // This code also can restart background MRW formatting UDFPrint(("DVD cont. fmt, LastLBA %x, Lba %x\n", Vcb->LastLBA, Lba));
ForBuf = (PFORMAT_CDRW_PARAMETERS_USER_IN)DbgAllocatePoolWithTag(NonPagedPool, sizeof(FORMAT_CDRW_PARAMETERS_USER_IN), 'zNWD'); if(ForBuf) { RtlZeroMemory(ForBuf, sizeof(FORMAT_CDRW_PARAMETERS_USER_IN)); ForBuf->Flags.FlagsEx = FORMAT_UNIT_RESTART_MRW; ForBuf->BlockCount = 0xffffffff;
RC = UDFPhSendIOCTL(IOCTL_CDRW_FORMAT_UNIT, Vcb->TargetDeviceObject, ForBuf,sizeof(FORMAT_CDRW_PARAMETERS_USER_IN), NULL,0,FALSE, NULL); DbgFreePool(ForBuf); if(OS_SUCCESS(RC)) { UDFPrint(("BGFormat restarted Interrupted->InProgress\n")); Vcb->MRWStatus = DiscInfo_BGF_InProgress; } else { PGET_LAST_ERROR_USER_OUT Error = NULL; if(!Vcb->Error) { Vcb->Error = (PGET_LAST_ERROR_USER_OUT) MyAllocatePool__(NonPagedPool, sizeof(GET_LAST_ERROR_USER_OUT)); } Error = Vcb->Error; if(Error) { UDFPhSendIOCTL( IOCTL_CDRW_GET_LAST_ERROR, Vcb->TargetDeviceObject, NULL,0, Error,sizeof(GET_LAST_ERROR_USER_OUT), TRUE,NULL); UDFPrint(("SK=%x ASC=%x, ASCQ=%x, IE=%x\n", Error->SenseKey, Error->AdditionalSenseCode, Error->AdditionalSenseCodeQualifier, Error->LastError)); // check for Long Write In Progress if( (Error->SenseKey == SCSI_SENSE_NOT_READY) && (Error->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) && ((Error->AdditionalSenseCodeQualifier == SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS) || (Error->AdditionalSenseCodeQualifier == SCSI_SENSEQ_FORMAT_IN_PROGRESS)) ) { RC = STATUS_SUCCESS; UDFPrint(("Seems, BGFormat already restarted\n")); Vcb->MRWStatus = DiscInfo_BGF_InProgress; } } } } } else { RC = STATUS_SUCCESS; }
UDFPrint(("DVD cont. write, LastLBA %x, Lba %x\n", Vcb->LastLBA, Lba));
ASSERT(Vcb->MediaClassEx == CdMediaClass_DVDRW); if(!Vcb->fZBuffer) { Vcb->fZBuffer = (PCHAR)DbgAllocatePoolWithTag(NonPagedPool, PSz, 'zNWD'); RtlZeroMemory(Vcb->fZBuffer, PSz); Vcb->fZBufferSize = PSz; } else if(Vcb->fZBufferSize < PSz) { PSz = Vcb->fZBufferSize; } if(!Vcb->fZBuffer) { BrutePoint(); RC = STATUS_INSUFFICIENT_RESOURCES; } else { for(fLba = Vcb->NWA; fLba < Lba; fLba+=BCount) {#ifdef _BROWSE_UDF_ retry = UDF_WRITE_MAX_RETRY;retry_1:#endif //_BROWSE_UDF_ RC = UDFPhWriteVerifySynchronous(Vcb->TargetDeviceObject, Vcb->fZBuffer, PSz, ((uint64)fLba) << Vcb->BlockSizeBits, &WrittenBytes, PH_TMP_BUFFER); Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK; UDFPrint(("Fmt status: %x\n", RC));#ifdef _BROWSE_UDF_ if(!OS_SUCCESS(RC) && OS_SUCCESS(RC = UDFRecoverFromError(Vcb, TRUE, RC, fLba, BCount, &retry)) ) { goto retry_1; UDFPrint(("Fmt retry\n")); }#endif //_BROWSE_UDF_ if(!OS_SUCCESS(RC)) { BrutePoint(); UDFPrint(("Fmt break on ERROR\n")); break; } UDFUpdateNWA(Vcb, fLba, BCount, RC); } } } else { UDFPrint((" no special processing\n")); }
return RC; }#endif //UDF_READ_ONLY_BUILD UDFPrint((" no suitable track!\n")); return STATUS_INVALID_PARAMETER;} // end UDFPrepareForWriteOperation()
//#ifdef _BROWSE_UDF_/* This routine tries to recover from hardware error Return: STATUS_SUCCESS - retry requst STATUS_XXX - unrecoverable error */OSSTATUSUDFRecoverFromError( IN PVCB Vcb, IN BOOLEAN WriteOp, IN OSSTATUS status, IN uint32 Lba, IN uint32 BCount, IN OUT uint32* retry ){ PGET_LAST_ERROR_USER_OUT Error = NULL; LARGE_INTEGER delay;// OSSTATUS RC; uint32 i; BOOLEAN UpdateBB = FALSE;
if(!(*retry) || !(Vcb->VCBFlags & UDF_VCB_FLAGS_OUR_DEVICE_DRIVER) || (Vcb->FsDeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM)) return status; (*retry)--; // allocate tmp buffer _SEH2_TRY { if(!Vcb->Error) { if(!(Vcb->Error = (PGET_LAST_ERROR_USER_OUT) MyAllocatePool__(NonPagedPool, sizeof(GET_LAST_ERROR_USER_OUT)))) try_return(status); } if(status == STATUS_NO_SUCH_DEVICE) { UDFPrint(("Error recovery: STATUS_NO_SUCH_DEVICE, die.....\n")); Vcb->VCBFlags |= UDF_VCB_FLAGS_UNSAFE_IOCTL | UDF_VCB_FLAGS_DEAD; try_return(status); }
#ifdef _UDF_STRUCTURES_H_ if(status == STATUS_NO_MEDIA_IN_DEVICE && !Vcb->EjectWaiter) { UDFPrint(("Error recovery: STATUS_NO_MEDIA_IN_DEVICE, prevent further remount.....\n")); // Make sure, that volume will never be quick-remounted // It is very important for ChkUdf utility and // some CD-recording libraries Vcb->SerialNumber--; try_return(status); }#endif //_UDF_STRUCTURES_H_
Error = Vcb->Error; UDFPhSendIOCTL( IOCTL_CDRW_GET_LAST_ERROR, Vcb->TargetDeviceObject, NULL,0, Error,sizeof(GET_LAST_ERROR_USER_OUT), TRUE,NULL); UDFPrint(("SK=%x ASC=%x, ASCQ=%x, IE=%x\n", Error->SenseKey, Error->AdditionalSenseCode, Error->AdditionalSenseCodeQualifier, Error->LastError)); // check for Long Write In Progress if( ((Error->SenseKey == SCSI_SENSE_NOT_READY) && (Error->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) && (Error->AdditionalSenseCodeQualifier == SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS)) ) { // we should wait... if(WriteOp) { if((*retry) == UDF_WRITE_MAX_RETRY-1) { UDFPrint(("Error recovery: reserve retry count for write retries\n")); (*retry) = UDF_WRITE_MAX_RETRY*3; } else if((*retry) == UDF_WRITE_MAX_RETRY) { UDFPrint(("Error recovery: jump over UDF_WRITE_MAX_RETRY\n")); (*retry)--; } delay.QuadPart = -500000; // 0.05 sec KeDelayExecutionThread(KernelMode, FALSE, &delay); if(WriteOp && ((*retry) > UDF_WRITE_MAX_RETRY-1)) { UDFPrint(("Error recovery: simple write retry with delay\n")); try_return(status = STATUS_SUCCESS); } } else { delay.QuadPart = -500000; // 0.05 sec KeDelayExecutionThread(KernelMode, FALSE, &delay); if((*retry) == UDF_WRITE_MAX_RETRY-1) { UDFPrint(("Error recovery: retry read after small delay\n")); try_return(status = STATUS_SUCCESS); } } UDFPrint(("Error recovery: sync cache\n")); // ...flush device cache... UDFSyncCache(Vcb); // wait again & retry delay.QuadPart = -1000000; // 0.1 sec KeDelayExecutionThread(KernelMode, FALSE, &delay);#ifdef _UDF_STRUCTURES_H_ if(Vcb->BGWriters) (*retry)++;#endif //_UDF_STRUCTURES_H_ try_return(status = STATUS_SUCCESS); } else // check for Long Write In Progress if((Error->SenseKey == SCSI_SENSE_NOT_READY) && (Error->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) && ((Error->AdditionalSenseCodeQualifier == SCSI_SENSEQ_FORMAT_IN_PROGRESS) || (Error->AdditionalSenseCodeQualifier == SCSI_SENSEQ_BECOMING_READY) || (Error->AdditionalSenseCodeQualifier == SCSI_SENSEQ_OPERATION_IN_PROGRESS) ) ) { // we should wait & retry UDFPrint(("Error recovery: op. in progress, waiting 0.3 sec\n")); delay.QuadPart = -3000000; // 0.3 sec KeDelayExecutionThread(KernelMode, FALSE, &delay);#ifdef _UDF_STRUCTURES_H_ if(Vcb->BGWriters) (*retry)++;#endif //_UDF_STRUCTURES_H_ Vcb->SyncCacheState = SYNC_CACHE_RECOVERY_ATTEMPT; try_return(status = STATUS_SUCCESS); } else // check for non empty cache special case if((Error->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) && (Error->AdditionalSenseCode == SCSI_ADSENSE_INVALID_CMD_SEQUENCE)) { // we should wait & retry if(!WriteOp) { UDFPrint(("Error recovery: invalid command sequence on read\n")); delay.QuadPart = -1000000; // 0.1 sec KeDelayExecutionThread(KernelMode, FALSE, &delay); UDFPrint(("Error recovery: sync cache\n")); // ...flush device cache... UDFSyncCache(Vcb); // wait again & retry delay.QuadPart = -1000000; // 0.1 sec KeDelayExecutionThread(KernelMode, FALSE, &delay);#ifdef _UDF_STRUCTURES_H_ if(Vcb->BGWriters) (*retry)++;#endif //_UDF_STRUCTURES_H_ try_return(status = STATUS_SUCCESS); } goto reinit_sector_mode; } else // check for Bus Reset (sometimes it happends...) if((Error->SenseKey == SCSI_SENSE_UNIT_ATTENTION) && (Error->AdditionalSenseCode == SCSI_ADSENSE_BUS_RESET) ) { // we should wait UDFPrint(("Error recovery: bus reset...\n")); Vcb->MediaChangeCount = Error->MediaChangeCount; delay.QuadPart = -1000000; // 0.1 sec KeDelayExecutionThread(KernelMode, FALSE, &delay); // reset driver UDFResetDeviceDriver(Vcb, Vcb->TargetDeviceObject, FALSE); delay.QuadPart = -1000000; // 0.1 sec KeDelayExecutionThread(KernelMode, FALSE, &delay); // lock it/* ((PPREVENT_MEDIA_REMOVAL_USER_IN)(Error))->PreventMediaRemoval = TRUE; UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL, Vcb->TargetDeviceObject, Error,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN), NULL,0, FALSE,NULL); delay.QuadPart = -1000000; // 0.1 sec KeDelayExecutionThread(KernelMode, FALSE, &delay);*/
// reinit write mode the following is performed inside UDFResetDeviceDriver() //Vcb->LastModifiedTrack = 0; //Vcb->OPCDone = FALSE;
reinit_sector_mode: // reinit sector mode Vcb->LastModifiedTrack = 0; UDFPrepareForWriteOperation(Vcb, Lba, BCount); try_return(status = STATUS_SUCCESS); } else // check for Illegal Sector Mode. // We can get this error 'cause of 2 reasons: // a) Bus reset occured. We should reinit // b) CopyProtection settings missmatch // c) preblems with DNA of firmware developer, some TEACs fall into such state // after failed streaming read if((Error->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) && (Error->AdditionalSenseCode == SCSI_ADSENSE_ILLEGAL_MODE_FOR_THIS_TRACK)) {bad_rw_seek_recovery: if(WriteOp) {
if((*retry) <= 1) { // Variate CopyProtection... for(i=Vcb->FirstTrackNum; i<=Vcb->LastTrackNum; i++) { if((Vcb->TrackMap[i].FirstLba > Lba) || (Vcb->TrackMap[i].LastLba < Lba)) continue; /* if(Vcb->TrackMap[i].Flags & TrackMap_CopyBit_variated) // Last chance.... goto reinit_sector_mode;*/
// check if we have successuflly completed WriteOp // using Variation. // We should not variate these bits again in this case. if(Vcb->TrackMap[i].Flags & TrackMap_Use_variation) break; Vcb->TrackMap[i].Flags &= ~TrackMap_Try_variation; /* if((Vcb->TrackMap[i].Flags & TrackMap_Try_variation) && (Vcb->TrackMap[i].Flags & (TrackMap_AllowCopyBit_variated | TrackMap_CopyBit_variated))) break;*/ /* if(Vcb->TrackMap[i].Flags & TrackMap_Use_variation) break;*/ Vcb->TrackMap[i].Flags |= TrackMap_Try_variation; // Try variation. if(!(Vcb->TrackMap[i].Flags ^= TrackMap_AllowCopyBit_variated)) Vcb->TrackMap[i].Flags ^= TrackMap_CopyBit_variated; if(Vcb->TrackMap[i].Flags & (TrackMap_AllowCopyBit_variated | TrackMap_CopyBit_variated) ) { (*retry) = 1; } else { Vcb->TrackMap[i].Flags &= ~TrackMap_Try_variation; } // reinit sector mode Vcb->LastModifiedTrack = 0; UDFPrepareForWriteOperation(Vcb, Lba, BCount); break; } } else { // Reinit...//reinit_sector_mode: // we should wait delay.QuadPart = -1000000; // 0.1 sec KeDelayExecutionThread(KernelMode, FALSE, &delay); // reinit sector mode goto reinit_sector_mode;/* Vcb->LastModifiedTrack = 0; UDFPrepareForWriteOperation(Vcb, Lba, BCount); try_return(status = STATUS_SUCCESS);*/ } } else if((Vcb->CompatFlags & UDF_VCB_IC_BAD_RW_SEEK) && (Vcb->IncrementalSeekState != INCREMENTAL_SEEK_DONE)) { UDFPrint(("Using incremental seek workaround...\n")); Vcb->IncrementalSeekState = INCREMENTAL_SEEK_WORKAROUND; try_return(status = STATUS_SUCCESS); } else { UDFPrint(("Seems to be BB @ %x\n", Lba)); UpdateBB = TRUE; } } else if((Error->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) && (Error->AdditionalSenseCode == SCSI_ADSENSE_INVALID_SESSION_MODE)) { if(WriteOp && (Vcb->SavedFeatures & CDRW_FEATURE_STREAMING) && Lba+BCount <= Vcb->LastLBA+1) { UDFPrint(("bad Session in streaming mode. Lba %x, try fix-up\n", Lba)); // ...flush device cache... UDFSyncCache(Vcb); // we should wait delay.QuadPart = -10000000; // 1 sec KeDelayExecutionThread(KernelMode, FALSE, &delay); try_return(status = STATUS_SUCCESS); } } else if((Error->LastError == CDRW_ERR_WRITE_IN_PROGRESS_BUSY) || (status == STATUS_DEVICE_BUSY)) { delay.QuadPart = -5000000; // 0.5 sec UDFPrint(("CDRW_ERR_WRITE_IN_PROGRESS_BUSY || STATUS_DEVICE_BUSY\n")); KeDelayExecutionThread(KernelMode, FALSE, &delay);#ifdef _UDF_STRUCTURES_H_ if(Vcb->BGWriters) (*retry)++;#endif //_UDF_STRUCTURES_H_ try_return(status = STATUS_SUCCESS); } else // some devices (SONY) return such a strange sequence.... if( ((Error->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) && (Error->AdditionalSenseCode == SCSI_ADSENSE_INVALID_CDB)) && WriteOp) { // reinit write mode Vcb->LastModifiedTrack = 0; UDFPrepareForWriteOperation(Vcb, Lba, BCount); try_return(status = STATUS_SUCCESS); } else // No seek on Read... to morgue, I'm afraid if((Error->SenseKey == SCSI_SENSE_MEDIUM_ERROR) /*&& ((Error->AdditionalSenseCode == SCSI_ADSENSE_CD_READ_ERROR) || (Error->AdditionalSenseCode == SCSI_ADSENSE_NO_SENSE) || (Error->AdditionalSenseCode == SCSI_ADSENSE_FORMAT_CORRUPTED) || (Error->AdditionalSenseCode == SCSI_ADSENSE_SEEK_ERROR))*/ && !WriteOp) { if(Error->AdditionalSenseCode == SCSI_ADSENSE_SEEK_ERROR) { UDFPrint(("Seek error\n")); if(Vcb->CompatFlags & UDF_VCB_IC_BAD_RW_SEEK) { UDFPrint(("try recovery\n")); goto bad_rw_seek_recovery; } UDFPrint(("map error to STATUS_NONEXISTENT_SECTOR\n")); status = STATUS_NONEXISTENT_SECTOR; } UDFPrint(("Seems to be BB @ %x (read 2)\n", Lba)); UpdateBB = TRUE; } else // handle invalid block address if( ((Error->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) && (Error->AdditionalSenseCode == SCSI_ADSENSE_ILLEGAL_BLOCK)) ) { if(!WriteOp && (Vcb->SavedFeatures & CDRW_FEATURE_STREAMING) && Lba+BCount <= Vcb->LastLBA+1) { UDFPrint(("bad LBA %x in streaming mode, try fix-up\n", Lba)); // ...flush device cache... UDFSyncCache(Vcb); try_return(status = STATUS_SUCCESS); }
if((Lba+BCount >= Vcb->LastLBA) && (Vcb->MRWStatus == DiscInfo_BGF_Interrupted)) { UDFPrint(("stupid drive, cannot read beyond formatted area on DiscInfo_BGF_Interrupted\n")); UpdateBB = FALSE; try_return(status = STATUS_BUFFER_ALL_ZEROS); } // prevent Bad Block Bitmap modification }
try_exit: NOTHING;
} _SEH2_FINALLY {#ifdef UDF_DBG if(OS_SUCCESS(status)) { UDFPrint(("Retry\n")); }#endif //UDF_DBG } _SEH2_END; if(!OS_SUCCESS(status)) { if((Vcb->MountPhErrorCount != (ULONG)-1) && (Vcb->MountPhErrorCount < 0x7fffffff)) { Vcb->MountPhErrorCount++; }//#ifdef _UDF_STRUCTURES_H_ if(UpdateBB && (BCount == 1)) { uint32* bm; if(!(bm = (uint32*)(Vcb->BSBM_Bitmap))) { bm = (uint32*)(Vcb->BSBM_Bitmap = (int8*)DbgAllocatePoolWithTag(NonPagedPool, (i = (Vcb->LastPossibleLBA+1+7)>>3), 'mNWD' )); if(bm) { RtlZeroMemory(bm, i); } else { UDFPrint(("Can't alloc BSBM for %x blocks\n", Vcb->LastPossibleLBA)); } } if(bm) { UDFSetBit(bm, Lba); UDFPrint(("Set BB @ %#x\n", Lba)); }#ifdef _BROWSE_UDF_ bm = (uint32*)(Vcb->FSBM_Bitmap); if(bm) { UDFSetUsedBit(bm, Lba); UDFPrint(("Set BB @ %#x as used\n", Lba)); }#endif //_BROWSE_UDF_ }//#endif //_UDF_STRUCTURES_H_ } return status;} // end UDFRecoverFromError()
//#endif //_BROWSE_UDF_/* This routine attempts to read disk layout using ReadDisk/Track info cmd */OSSTATUSUDFReadDiscTrackInfo( PDEVICE_OBJECT DeviceObject, // the target device object PVCB Vcb // Volume Control Block for ^ DevObj ){ OSSTATUS RC = STATUS_SUCCESS; PDISC_INFO_BLOCK_USER_OUT DiscInfo = (PDISC_INFO_BLOCK_USER_OUT)MyAllocatePool__(NonPagedPool,sizeof(DISC_INFO_BLOCK_USER_OUT) ); PTRACK_INFO_BLOCK_USER_OUT TrackInfoOut = (PTRACK_INFO_BLOCK_USER_OUT)MyAllocatePool__(NonPagedPool,sizeof(TRACK_INFO_BLOCK_USER_OUT) ); PTRACK_INFO_BLOCK_USER_IN TrackInfoIn = (PTRACK_INFO_BLOCK_USER_IN)TrackInfoOut; READ_CAPACITY_USER_OUT CapacityBuffer; LONG TrackNumber; BOOLEAN NotFP = FALSE; BOOLEAN ForceFP = FALSE; BOOLEAN PacketTrack = FALSE; BOOLEAN MRWRetry = FALSE;// BOOLEAN ReadCapacityOk = FALSE;#ifdef UDF_FORMAT_MEDIA PUDFFmtState fms = Vcb->fms;#endif
_SEH2_TRY { if(!DiscInfo || !TrackInfoOut) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
MRWRetry_label:
RC = UDFPhSendIOCTL(IOCTL_CDRW_READ_DISC_INFO, DeviceObject, NULL, 0, DiscInfo,sizeof(DISC_INFO_BLOCK_USER_OUT), TRUE, NULL); if(!OS_SUCCESS(RC)) { UDFPrint(("ReadDiskInfo failed. Use default.\n")); if(Vcb->MediaClassEx == CdMediaClass_DVDRW || Vcb->MediaClassEx == CdMediaClass_DVDpRW || Vcb->MediaClassEx == CdMediaClass_DVDRAM) { Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_DVD; } else if(Vcb->MediaClassEx == CdMediaClass_BDRE) { Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_BD; } else { Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_FP_CD; } try_return(RC); }#ifdef UDF_FORMAT_MEDIA if(fms && fms->opt_disk_info) { UserPrint(("ReadDiskInfo OK\n")); }#endif //UDF_FORMAT_MEDIA
RC = UDFPhSendIOCTL(IOCTL_CDRW_READ_CAPACITY, DeviceObject, NULL, 0, &CapacityBuffer,sizeof(READ_CAPACITY_USER_OUT), TRUE, NULL); if(!OS_SUCCESS(RC)) { UDFPrint(("ReadCapacity failed.\n")); if(Vcb->MediaClassEx == CdMediaClass_DVDpRW) { Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_DVD; } } else { UDFPrint(("ReadCapacity ok.\n")); UDFPrint(("Last possible LBA %#x.\n", CapacityBuffer.LogicalBlockAddress)); if(!(CapacityBuffer.LogicalBlockAddress & 0xc0000000) && (CapacityBuffer.LogicalBlockAddress != 0x7fffffff)) { // good value from ReadCapacity UDFPrint(("Update Last possible LBA %#x.\n", CapacityBuffer.LogicalBlockAddress)); Vcb->LastPossibleLBA = CapacityBuffer.LogicalBlockAddress;// ReadCapacityOk = TRUE;#ifdef UDF_FORMAT_MEDIA if(fms && fms->opt_disk_info) { UserPrint(("ReadCapacity OK\n")); }#endif //UDF_FORMAT_MEDIA } }
#ifdef _CONSOLE Vcb->PhDeviceType = FILE_DEVICE_CD_ROM;#endif //_CONSOLE Vcb->PhSerialNumber = *((uint32*)&(DiscInfo->DiskId)); Vcb->PhErasable = DiscInfo->DiscStat.Flags & DiscInfo_Disk_Erasable; Vcb->PhDiskType = DiscInfo->DiskType; // save OPC info if(DiscInfo->OPCNum) Vcb->OPCNum = DiscInfo->OPCNum; UDFPrint(("DiskInfo: SN %x, OPCn %x(%x), Stat %x, Flg: %x\n", Vcb->PhSerialNumber, Vcb->OPCNum, DiscInfo->OPCNum, DiscInfo->DiscStat.Flags, DiscInfo->Flags.Flags));#ifdef UDF_FORMAT_MEDIA if(fms && fms->opt_disk_info) { UserPrint(("Media type: ")); switch(Vcb->MediaClassEx) { case CdMediaClass_CDROM : UserPrint(("CD-ROM \n")); break; case CdMediaClass_CDR : UserPrint(("CD-R \n")); break; case CdMediaClass_CDRW : UserPrint(("CD-RW \n")); break; case CdMediaClass_DVDROM : UserPrint(("DVD-ROM \n")); break; case CdMediaClass_DVDRAM : UserPrint(("DVD-RAM \n")); break; case CdMediaClass_DVDR : UserPrint(("DVD-R \n")); break; case CdMediaClass_DVDRW : UserPrint(("DVD-RW \n")); break; case CdMediaClass_DVDpR : UserPrint(("DVD+R \n")); break; case CdMediaClass_DVDpRW : UserPrint(("DVD+RW \n")); break; case CdMediaClass_DDCDROM : UserPrint(("DDCD-ROM \n")); break; case CdMediaClass_DDCDR : UserPrint(("DDCD-R \n")); break; case CdMediaClass_DDCDRW : UserPrint(("DDCD-RW \n")); break; case CdMediaClass_BDROM : UserPrint(("BD-ROM \n")); break; case CdMediaClass_BDRE : UserPrint(("BD-RE \n")); break; case CdMediaClass_BDR : UserPrint(("BD-R \n")); break; case CdMediaClass_HD_DVDROM : UserPrint(("HD DVD-ROM \n")); break; case CdMediaClass_HD_DVDRAM : UserPrint(("HD DVD-RAM \n")); break; case CdMediaClass_HD_DVDR : UserPrint(("HD DVD-R \n")); break; case CdMediaClass_HD_DVDRW : UserPrint(("HD DVD-RW \n")); break; default: UserPrint(("Unknown\n")); break; } UserPrint(("SN %#x, OPCn %#x\n", Vcb->PhSerialNumber, Vcb->OPCNum, DiscInfo->OPCNum)); UserPrint(("Disk State: ")); switch(DiscInfo->DiscStat.Flags & DiscInfo_Disk_Mask) { case DiscInfo_Disk_Empty: UserPrint(("Empty\n")); break; case DiscInfo_Disk_Appendable: UserPrint(("Appendable\n")); break; case DiscInfo_Disk_Complete: UserPrint(("Complete\n")); break; case DiscInfo_Disk_OtherRW: UserPrint(("RW in unknown state\n")); break; } UserPrint(("Last Session State: ")); switch(DiscInfo->DiscStat.Flags & DiscInfo_Ses_Mask) { case DiscInfo_Ses_Empty: UserPrint(("Empty\n")); break; case DiscInfo_Ses_Incomplete: UserPrint(("Incomplete\n")); break; case DiscInfo_Ses_Complete: UserPrint(("Complete\n")); break; default: UserPrint(("unknown state\n")); break; } UserPrint(("Erasable: %s\n", (DiscInfo->DiscStat.Flags & DiscInfo_Disk_Erasable) ? "yes" : "no" )); }#endif //UDF_FORMAT_MEDIA // Save disk status Vcb->DiscStat = DiscInfo->DiscStat.Flags; if((DiscInfo->DiscStat.Flags & DiscInfo_Disk_Mask) == DiscInfo_Disk_Empty) { UDFPrint(("Blank\n")); Vcb->BlankCD = TRUE; } if( (DiscInfo->DiscStat.Flags & DiscInfo_Disk_Mask) == DiscInfo_Disk_Empty || (DiscInfo->DiscStat.Flags & DiscInfo_Ses_Mask) == DiscInfo_Ses_Incomplete) { // we shall mount empty disk to make it possible for // external applications to perform format operation // or something like this UDFPrint(("Try RAW_MOUNT\n")); Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK; PacketTrack = TRUE; }
#ifndef _BROWSE_UDF_ // If drive returned reasonable value from ReadCapacity, do not use // last LeadIn/LeadOut if(Vcb->MediaClassEx != CdMediaClass_DVDpRW && !ReadCapacityOk) { // +RW returns bad value UDFPrint(("+RW returns bad value\n")); Vcb->LastPossibleLBA = (DiscInfo->LastSesLeadOutLBA & 0x80000000) ? 0 : DiscInfo->LastSesLeadOutLBA; if(!(DiscInfo->LastSesLeadInLBA & 0x80000000)) { Vcb->LastPossibleLBA = max(DiscInfo->LastSesLeadInLBA, Vcb->LastPossibleLBA); } }#endif // _BROWSE_UDF_ if((DiscInfo->Flags.Flags & DiscInfo_BGF_Mask) != 0) { UDFPrint(("ForceFP + MRW\n")); ForceFP = TRUE; Vcb->MRWStatus = DiscInfo->Flags.Flags & DiscInfo_BGF_Mask; // update addressing mode if(!MRWRetry) { UDFSetMRWMode(Vcb); MRWRetry = TRUE; goto MRWRetry_label; } } UDFPrint(("MRW state %x\n", Vcb->MRWStatus)); if(Vcb->MediaClassEx == CdMediaClass_DVDRW) { if(Vcb->PhMediaCapFlags & CdCapFlags_RandomWritable) { UDFPrint(("DVD-RW Rewritable\n")); ForceFP = TRUE; } else if((DiscInfo->DiscStat.Flags & DiscInfo_Disk_Mask) == DiscInfo_Disk_Empty) { UDFPrint(("Blank DVD-RW\n")); ForceFP = TRUE; } else { UDFPrint(("DVD-RW Sequential\n")); NotFP = TRUE; } } else if(CdrwIsDvdOverwritable(Vcb->MediaClassEx)) { UDFPrint(("force Rewritable (2)\n")); ForceFP = TRUE; } // We have incomplete last session, so process each track from last to first// Vcb->LastPossibleLBA = DiscInfo->LastSesLeadInLBA;
Vcb->LastSession = DiscInfo->Status.NumOfSes; Vcb->LastTrackNum = DiscInfo->Status.LastTrackNumLastSes; Vcb->FirstTrackNum = DiscInfo->FirstTrackNum; // some devices report LastTrackNum=0 for full disks Vcb->LastTrackNum = max(Vcb->LastTrackNum, Vcb->FirstTrackNum); if(!Vcb->LastTrackNum) { UDFPrint(("Try read 1st track...\n")); Vcb->LastTrackNum = 1; } UDFPrint(("DiskInfo: 1st trk %x, last trk %x\n", Vcb->FirstTrackNum, Vcb->LastTrackNum));#ifdef UDF_FORMAT_MEDIA if(fms && fms->opt_disk_info) { UserPrint(("First track: %d\n" "Last track: %d\n", Vcb->FirstTrackNum, Vcb->LastTrackNum)); UserPrint(("------------------------------------------\n")); }#endif //UDF_FORMAT_MEDIA
RC = UDFReallocTrackMap(Vcb, Vcb->LastTrackNum+1); if(!OS_SUCCESS(RC)) try_return(RC);
// Get last LBA from invisible track (if any) RtlZeroMemory(TrackInfoOut,sizeof(TRACK_INFO_BLOCK_USER_OUT));
TrackInfoIn->LBA_TrkNum = 0; // invisible track TrackInfoIn->Track = TRUE;
RC = UDFPhSendIOCTL(IOCTL_CDRW_READ_TRACK_INFO, DeviceObject, TrackInfoIn, sizeof(TRACK_INFO_BLOCK_USER_IN), TrackInfoOut,sizeof(TRACK_INFO_BLOCK_USER_OUT), TRUE, NULL); if(OS_SUCCESS(RC)) { if((Vcb->LastTrackNum < TrackInfoOut->TrackNum) && TrackInfoOut->TrackLength && (TrackInfoOut->TrackStartLBA != TrackInfoOut->NextWriteLBA)) { Vcb->LastTrackNum = TrackInfoOut->TrackNum; if(!(TrackInfoOut->NextWriteLBA & 0x80000000)) Vcb->NWA = TrackInfoOut->NextWriteLBA; if(TrackInfoOut->TrackLength > 1) { Vcb->LastPossibleLBA = TrackInfoOut->TrackStartLBA + TrackInfoOut->TrackLength - (TrackInfoOut->TrackLength ? 1 : 0); UDFPrint((" set LastPossibleLBA=%x\n", Vcb->LastPossibleLBA)); } }
UDFPrint(("Ses %d, Track %d (%x, len %x) PckSize %x: \n" " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n" " LRA: %x (%s) RC_LBA:%x\n", TrackInfoOut->SesNum, 0, TrackInfoOut->TrackStartLBA, TrackInfoOut->TrackLength, TrackInfoOut->FixPacketSize,
TrackInfoOut->NextWriteLBA, TrackInfoOut->NWA_V & TrkInfo_NWA_V ? "vld" : "inv", TrackInfoOut->DataParam.Flags & TrkInfo_Dat_Mask, (TrackInfoOut->DataParam.Flags & TrkInfo_Packet) ? "Pck" : "", (TrackInfoOut->DataParam.Flags & TrkInfo_FP) ? "FP" : "", (TrackInfoOut->DataParam.Flags & TrkInfo_Blank) ? "Blank" : "", (TrackInfoOut->DataParam.Flags & TrkInfo_RT) ? "RT" : "",
TrackInfoOut->TrackParam.Flags & TrkInfo_Trk_Mask, (TrackInfoOut->TrackParam.Flags & TrkInfo_Copy) ? "Cpy" : "", (TrackInfoOut->TrackParam.Flags & TrkInfo_Damage) ? "Damage" : "",
TrackInfoOut->LastRecordedAddr, (TrackInfoOut->NWA_V & TrkInfo_LRA_V) ? "vld" : "inv",
TrackInfoOut->ReadCompatLBA ));#ifdef UDF_FORMAT_MEDIA if(fms && fms->opt_disk_info) { UserPrint(("Invisible track: \n")); UserPrint((" Ses %d, Track %d (%x, len %x) PckSize %x: \n" " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n" " LRA: %x (%s) RC_LBA:%x\n", TrackInfoOut->SesNum, 0, TrackInfoOut->TrackStartLBA, TrackInfoOut->TrackLength, TrackInfoOut->FixPacketSize,
TrackInfoOut->NextWriteLBA, TrackInfoOut->NWA_V & TrkInfo_NWA_V ? "vld" : "inv", TrackInfoOut->DataParam.Flags & TrkInfo_Dat_Mask, (TrackInfoOut->DataParam.Flags & TrkInfo_Packet) ? "Pck" : "", (TrackInfoOut->DataParam.Flags & TrkInfo_FP) ? "FP" : "", (TrackInfoOut->DataParam.Flags & TrkInfo_Blank) ? "Blank" : "", (TrackInfoOut->DataParam.Flags & TrkInfo_RT) ? "RT" : "",
TrackInfoOut->TrackParam.Flags & TrkInfo_Trk_Mask, (TrackInfoOut->TrackParam.Flags & TrkInfo_Copy) ? "Cpy" : "", (TrackInfoOut->TrackParam.Flags & TrkInfo_Damage) ? "Damage" : "",
TrackInfoOut->LastRecordedAddr, (TrackInfoOut->NWA_V & TrkInfo_LRA_V) ? "vld" : "inv",
TrackInfoOut->ReadCompatLBA )); }#endif //UDF_FORMAT_MEDIA
}
for (TrackNumber=(LONG)DiscInfo->FirstTrackNum;TrackNumber <= (LONG)Vcb->LastTrackNum;TrackNumber++) {
RtlZeroMemory(TrackInfoOut,sizeof(TRACK_INFO_BLOCK_USER_OUT)); TrackInfoIn->LBA_TrkNum = TrackNumber; TrackInfoIn->Track = TRUE;
RC = UDFPhSendIOCTL(IOCTL_CDRW_READ_TRACK_INFO, DeviceObject, TrackInfoIn, sizeof(TRACK_INFO_BLOCK_USER_IN), TrackInfoOut,sizeof(TRACK_INFO_BLOCK_USER_OUT), TRUE, NULL); // fill sector type map if(TrackInfoOut->TrackStartLBA & 0x80000000) { UDFPrint(("TrkInfo: Bad FirstLba (%x), change to %x\n", TrackInfoOut->TrackStartLBA, 0)); Vcb->TrackMap[TrackNumber].FirstLba = 0; } else { Vcb->TrackMap[TrackNumber].FirstLba = TrackInfoOut->TrackStartLBA; } if(TrackInfoOut->TrackLength & 0x80000000) { UDFPrint(("TrkInfo: Bad TrackLength (%x), change to %x\n", TrackInfoOut->TrackLength, Vcb->LastPossibleLBA - Vcb->TrackMap[TrackNumber].FirstLba + 1)); TrackInfoOut->TrackLength = Vcb->LastPossibleLBA - Vcb->TrackMap[TrackNumber].FirstLba + 1; } Vcb->TrackMap[TrackNumber].LastLba = TrackInfoOut->TrackStartLBA + TrackInfoOut->TrackLength - (TrackInfoOut->TrackLength ? 1 : 0);
Vcb->TrackMap[TrackNumber].TrackParam = TrackInfoOut->TrackParam.Flags; Vcb->TrackMap[TrackNumber].DataParam = TrackInfoOut->DataParam.Flags; Vcb->TrackMap[TrackNumber].NWA_V = TrackInfoOut->NWA_V; if((TrackInfoOut->NextWriteLBA & 0x80000000) || (TrackInfoOut->NextWriteLBA < TrackInfoOut->TrackStartLBA)) { if(!(Vcb->TrackMap[TrackNumber].LastLba & 0x8000000)) { UDFPrint(("TrkInfo: set NWA to LastLba (%x)\n", Vcb->TrackMap[TrackNumber].LastLba)); Vcb->TrackMap[TrackNumber].NWA = Vcb->TrackMap[TrackNumber].LastLba; } else { UDFPrint(("TrkInfo: set NWA to INV (1)\n")); Vcb->TrackMap[TrackNumber].NWA = 0; Vcb->TrackMap[TrackNumber].NWA_V = 0; } } else { if(!(TrackInfoOut->NextWriteLBA & 0x80000000)) { UDFPrint(("TrkInfo: Good NWA (%x)\n", TrackInfoOut->NextWriteLBA)); Vcb->TrackMap[TrackNumber].NWA = TrackInfoOut->NextWriteLBA; } else { UDFPrint(("TrkInfo: set NWA to INV (2)\n")); Vcb->TrackMap[TrackNumber].NWA = 0; Vcb->TrackMap[TrackNumber].NWA_V = 0; } } Vcb->TrackMap[TrackNumber].Session = TrackInfoOut->SesNum; // for FP tracks we shall get PacketSize from returned info // otherwise set to default UDF value (0x20) if(NotFP) { UDFPrint(("Apply NotFP\n")); Vcb->TrackMap[TrackNumber].DataParam &= ~TrkInfo_FP;#ifdef DBG TrackInfoOut->DataParam.Flags &= ~TrkInfo_FP;#endif //DBG } else if(ForceFP) { UDFPrint(("Apply ForceFP\n")); PacketTrack = TRUE; Vcb->TrackMap[TrackNumber].DataParam |= TrkInfo_FP;#ifdef DBG TrackInfoOut->DataParam.Flags |= TrkInfo_FP;#endif //DBG } if(Vcb->TrackMap[TrackNumber].DataParam & TrkInfo_FP) { Vcb->TrackMap[TrackNumber].PacketSize = TrackInfoOut->FixPacketSize; Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK; Vcb->FP_disc = TRUE; } else { Vcb->TrackMap[TrackNumber].PacketSize = PACKETSIZE_UDF; } // presence of Damaged track means, that we should mount this disk in RAW mode if(Vcb->TrackMap[TrackNumber].TrackParam & TrkInfo_Damage) { UDFPrint(("TrkInfo_Damage, Try RAW_MOUNT\n")); Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK; } // presence of track with Unknown data type means, that we should mount // this disk in RAW mode if((TrackInfoOut->DataParam.Flags & TrkInfo_Dat_Mask) == TrkInfo_Trk_unknown) { UDFPrint(("Unknown DatType, Try RAW_MOUNT\n")); Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK; }
PacketTrack |= ((TrackInfoOut->DataParam.Flags & TrkInfo_Packet) != 0);
UDFPrint(("Ses %d, Track %d (%x - %x) PckSize %x: \n" " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n" " LRA: %x (%s) RC_LBA:%x\n", TrackInfoOut->SesNum, TrackNumber, Vcb->TrackMap[TrackNumber].FirstLba, Vcb->TrackMap[TrackNumber].LastLba, TrackInfoOut->FixPacketSize,
TrackInfoOut->NextWriteLBA, TrackInfoOut->NWA_V & TrkInfo_NWA_V ? "vld" : "inv", TrackInfoOut->DataParam.Flags & TrkInfo_Dat_Mask, (TrackInfoOut->DataParam.Flags & TrkInfo_Packet) ? "Pck" : "", (TrackInfoOut->DataParam.Flags & TrkInfo_FP) ? "FP" : "", (TrackInfoOut->DataParam.Flags & TrkInfo_Blank) ? "Blank" : "", (TrackInfoOut->DataParam.Flags & TrkInfo_RT) ? "RT" : "",
TrackInfoOut->TrackParam.Flags & TrkInfo_Trk_Mask, (TrackInfoOut->TrackParam.Flags & TrkInfo_Copy) ? "Cpy" : "", (TrackInfoOut->TrackParam.Flags & TrkInfo_Damage) ? "Damage" : "",
TrackInfoOut->LastRecordedAddr, (TrackInfoOut->NWA_V & TrkInfo_LRA_V) ? "vld" : "inv",
TrackInfoOut->ReadCompatLBA ));#ifdef UDF_FORMAT_MEDIA if(fms && fms->opt_disk_info) { UserPrint(("Track %d: \n", TrackNumber)); UserPrint((" Ses %d, Track %d (%x, len %x) PckSize %x: \n" " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n" " LRA: %x (%s) RC_LBA:%x\n", TrackInfoOut->SesNum, TrackNumber, TrackInfoOut->TrackStartLBA, TrackInfoOut->TrackLength, TrackInfoOut->FixPacketSize,
TrackInfoOut->NextWriteLBA, TrackInfoOut->NWA_V & TrkInfo_NWA_V ? "vld" : "inv", TrackInfoOut->DataParam.Flags & TrkInfo_Dat_Mask, (TrackInfoOut->DataParam.Flags & TrkInfo_Packet) ? "Pck" : "", (TrackInfoOut->DataParam.Flags & TrkInfo_FP) ? "FP" : "", (TrackInfoOut->DataParam.Flags & TrkInfo_Blank) ? "Blank" : "", (TrackInfoOut->DataParam.Flags & TrkInfo_RT) ? "RT" : "",
TrackInfoOut->TrackParam.Flags & TrkInfo_Trk_Mask, (TrackInfoOut->TrackParam.Flags & TrkInfo_Copy) ? "Cpy" : "", (TrackInfoOut->TrackParam.Flags & TrkInfo_Damage) ? "Damage" : "",
TrackInfoOut->LastRecordedAddr, (TrackInfoOut->NWA_V & TrkInfo_LRA_V) ? "vld" : "inv",
TrackInfoOut->ReadCompatLBA )); }#endif //UDF_FORMAT_MEDIA
if(TrackNumber == DiscInfo->FirstTrackNum) { if(!(Vcb->TrackMap[TrackNumber].FirstLba & 0x80000000)) { UDFPrint(("TrkInfo: Update FirstLBA (%x)\n", Vcb->TrackMap[TrackNumber].FirstLba)); Vcb->FirstLBA = Vcb->TrackMap[TrackNumber].FirstLba; } } if((TrackInfoOut->SesNum == Vcb->LastSession) && !Vcb->FirstTrackNumLastSes) { if(!(Vcb->TrackMap[TrackNumber].FirstLba & 0x80000000)) { UDFPrint(("TrkInfo: Update FirstLBALastSes (%x)\n", Vcb->TrackMap[TrackNumber].FirstLba)); Vcb->FirstLBALastSes = Vcb->TrackMap[TrackNumber].FirstLba; } Vcb->FirstTrackNumLastSes = TrackNumber; } }
if(!(TrackInfoOut->NextWriteLBA & 0x80000000) && !(TrackInfoOut->TrackLength & 0x80000000) && (Vcb->NWA < TrackInfoOut->NextWriteLBA) ) { UDFPrint((" set NWA to %x\n", TrackInfoOut->NextWriteLBA)); if(Vcb->MediaClassEx != CdMediaClass_DVDpRW) { Vcb->NWA = TrackInfoOut->NextWriteLBA; } else { Vcb->NWA = TrackInfoOut->TrackStartLBA + TrackInfoOut->TrackLength - (TrackInfoOut->TrackLength ? 1 : 0); } } if(Vcb->MediaClassEx != CdMediaClass_DVDpRW && !(TrackInfoOut->TrackLength & 0x80000000) && TrackInfoOut->TrackLength > 1) { Vcb->LastPossibleLBA = TrackInfoOut->TrackStartLBA + TrackInfoOut->TrackLength - (TrackInfoOut->TrackLength ? 1 : 0); UDFPrint((" set LastPossibleLBA=%x\n", Vcb->LastPossibleLBA)); } TrackNumber = Vcb->LastTrackNum; // quick formatted +RW returns bogus value if(Vcb->MediaClassEx == CdMediaClass_DVDpRW) { UDFPrint((" check quick formatted +RW\n")); if(Vcb->TrackMap[TrackNumber].LastLba && !(Vcb->TrackMap[TrackNumber].LastLba & 0x80000000) && Vcb->TrackMap[TrackNumber].LastLba < Vcb->LastPossibleLBA /*&& Vcb->TrackMap[TrackNumber].LastLba != Vcb->LastPossibleLBA*/ ) { UDFPrint((" track LastLBA %x != LastPossibleLBA %x, verify\n", Vcb->TrackMap[TrackNumber].LastLba, Vcb->LastPossibleLBA));
if(Vcb->MRWStatus == DiscInfo_BGF_Complete) { UDFPrint((" complete MRW state\n"));#ifdef _BROWSE_UDF_ Vcb->LastPossibleLBA = Vcb->NWA = Vcb->LastLBA = Vcb->TrackMap[TrackNumber].LastLba; goto valid_track_length;#endif // _BROWSE_UDF_ } else if(Vcb->MRWStatus) { uint8* buff; SIZE_T ReadBytes;
UDFPrint((" MRW state %x\n", Vcb->MRWStatus));
buff = (uint8*)DbgAllocatePoolWithTag(NonPagedPool, Vcb->WriteBlockSize, 'bNWD' ); if(buff) { RC = UDFTRead(Vcb, buff, Vcb->WriteBlockSize, Vcb->TrackMap[TrackNumber].LastLba+1, &ReadBytes, PH_TMP_BUFFER); DbgFreePool(buff); if(!OS_SUCCESS(RC)) { UDFPrint((" Can't read beyond track LastLBA (%x)\n", Vcb->TrackMap[TrackNumber].LastLba+1)); Vcb->LastLBA = Vcb->TrackMap[TrackNumber].LastLba; Vcb->NWA = Vcb->LastLBA+1; Vcb->TrackMap[TrackNumber].NWA_V = 1; Vcb->TrackMap[TrackNumber].NWA = Vcb->NWA; Vcb->TrackMap[TrackNumber].LastLba = Vcb->LastPossibleLBA; RC = STATUS_SUCCESS; goto valid_track_length; } } } } UDFPrint((" set track LastLBA %x\n", Vcb->LastPossibleLBA)); Vcb->NWA = Vcb->LastLBA = Vcb->TrackMap[TrackNumber].LastLba = Vcb->LastPossibleLBA; }valid_track_length: // Test for last empty session if((Vcb->TrackMap[TrackNumber].Session != Vcb->TrackMap[TrackNumber-1].Session) && (Vcb->LastSession > 1)) { // Note: some devices return negative track length if((Vcb->TrackMap[TrackNumber].LastLba <= Vcb->TrackMap[TrackNumber].FirstLba) || (Vcb->TrackMap[TrackNumber].FirstLba == Vcb->TrackMap[TrackNumber].NWA)) { // empty last session... Vcb->LastTrackNum--;// TrackNumber--;/* for(SesNum = Vcb->TrackMap[TrackNumber].Session; Vcb->TrackMap[TrackNumber].Session == SesNum; TrackNumber--) { }*/ if(TrackNumber>1) Vcb->LastSession = Vcb->TrackMap[TrackNumber-1].Session; } }
TrackNumber = Vcb->LastTrackNum;#ifdef _BROWSE_UDF_ Vcb->LastLBA = min(Vcb->TrackMap[TrackNumber].LastLba, Vcb->TrackMap[TrackNumber].NWA);#endif //_BROWSE_UDF_
if(Vcb->TrackMap[TrackNumber].NWA_V & TrkInfo_NWA_V) { UDFPrint((" NWA ok, set LastLBA to min(Last %x, NWA %x\n", Vcb->TrackMap[TrackNumber].LastLba, Vcb->TrackMap[TrackNumber].NWA)); Vcb->LastLBA = min(Vcb->TrackMap[TrackNumber].LastLba, Vcb->TrackMap[TrackNumber].NWA); } else { UDFPrint((" no NWA, set LastLBA to Last %x\n", Vcb->TrackMap[TrackNumber].LastLba)); Vcb->LastLBA = Vcb->TrackMap[TrackNumber].LastLba; }
Vcb->VCBFlags |= UDF_VCB_FLAGS_TRACKMAP; if(!PacketTrack && Vcb->MediaClassEx != CdMediaClass_DVDRAM ) { UDFPrint((" disable Raw mount\n")); Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK; }
try_exit: NOTHING;
} _SEH2_FINALLY { if(DiscInfo) MyFreePool__(DiscInfo); if(TrackInfoOut) MyFreePool__(TrackInfoOut); } _SEH2_END;
return RC;} // end UDFReadDiscTrackInfo()
/* This routine attempts to read disk layout using ReadFullTOC cmd */OSSTATUSUDFReadAndProcessFullToc( PDEVICE_OBJECT DeviceObject, // the target device object PVCB Vcb ){ OSSTATUS RC = STATUS_SUCCESS; PREAD_FULL_TOC_USER_OUT toc = (PREAD_FULL_TOC_USER_OUT)MyAllocatePool__(NonPagedPool,sizeof(READ_FULL_TOC_USER_OUT) ); uint32 index; uint8 POINT; uint8 CurTrack = 0; uint32 LastLeadOut = 0;// BOOLEAN IsMRW = FALSE;
UDFPrint(("UDFReadAndProcessFullToc\n"));
if(!toc) return STATUS_INSUFFICIENT_RESOURCES; Vcb->FirstTrackNum = 0xFF;
RtlZeroMemory(toc,sizeof(READ_FULL_TOC_USER_OUT));
RC = UDFPhSendIOCTL(IOCTL_CDRW_READ_FULL_TOC,DeviceObject, NULL,0, toc,sizeof(READ_FULL_TOC_USER_OUT), TRUE,NULL);
if(!OS_SUCCESS(RC)) {
MyFreePool__(toc); return RC; }
#ifdef _CONSOLE Vcb->PhDeviceType = FILE_DEVICE_CD_ROM;#endif //_CONSOLE Vcb->LastSession = toc->Sessions.Last_TrackSes;
RC = UDFReallocTrackMap(Vcb, 0x100); if(!OS_SUCCESS(RC)) { MyFreePool__(toc); return RC; }
// get LastPossibleLBA
// Note: some drives return Full TOC items unordered. // So, LeadOut position may come before Track definition. // In order to handle such situation, we must initialize // CurTrack when First or Last Track descriptor comes for (index=0;(index<MAXIMUM_NUMBER_OF_SESSIONS);index++) {/* if((toc->SessionData[index].Adr == TOC_ADR_TrackInfo) && ((toc->SessionData[index].Control == TOC_CTL_MRWTrackInfo) || (toc->SessionData[index].Control == TOC_CTL_MRWLastSes))) { IsMRW = TRUE; }*/ if(toc->SessionData[index].Adr == 1) { switch (POINT = toc->SessionData[index].POINT) { case POINT_FirstTrackNum: { Vcb->FirstTrackNum = toc->SessionData[index].Params.FirstTrackNum.FirstTrackNum; if(!CurTrack) CurTrack = (uint8)(Vcb->FirstTrackNum); break; } case POINT_LastTrackNum: { Vcb->LastTrackNum = toc->SessionData[index].Params.LastTrackNum.LastTrackNum; if(CurTrack < Vcb->LastTrackNum) CurTrack = (uint8)(Vcb->FirstTrackNum); break; } case POINT_StartPositionOfLeadOut: {#define TempMSF toc->SessionData[index].Params.StartPositionOfLeadOut.MSF Vcb->TrackMap[CurTrack].LastLba = MSF_TO_LBA(TempMSF[0],TempMSF[1],TempMSF[2]); LastLeadOut = max(LastLeadOut, Vcb->TrackMap[CurTrack].LastLba);#undef TempMSF break; } default: { if( (Vcb->FirstTrackNum != 0x0FF) && (toc->SessionData[index].POINT == Vcb->FirstTrackNum) ) {#define TempMSF toc->SessionData[index].Params.StartPositionOfTrack.MSF Vcb->FirstLBA = MSF_TO_LBA(TempMSF[0],TempMSF[1],TempMSF[2]); if(Vcb->FirstLBA & 0x80000000) { Vcb->FirstLBA = 0; }#undef TempMSF } break; } } if((POINT >= POINT_StartPositionOfTrack_Min) && (POINT <= POINT_StartPositionOfTrack_Max)) {#define TempMSF toc->SessionData[index].Params.StartPositionOfTrack.MSF Vcb->TrackMap[POINT].FirstLba = MSF_TO_LBA(TempMSF[0],TempMSF[1],TempMSF[2])-1; if(Vcb->TrackMap[POINT].FirstLba & 0x80000000) { if(POINT == 1) { Vcb->TrackMap[POINT].FirstLba = 0; } else { if(Vcb->TrackMap[POINT-1].LastLba) { Vcb->TrackMap[POINT].FirstLba = Vcb->TrackMap[POINT-1].LastLba+1; } } }#undef TempMSF if(POINT > POINT_StartPositionOfTrack_Min) { Vcb->TrackMap[POINT-1].LastLba = Vcb->TrackMap[POINT].FirstLba-1; } CurTrack = POINT; } } else if(toc->SessionData[index].Adr == 5) { switch (POINT = toc->SessionData[index].POINT) { case POINT_StartPositionOfNextProgramArea: {#define TempMSF toc->SessionData[index].Params.StartPositionOfNextProgramArea.MaxLeadOut_MSF Vcb->LastPossibleLBA = MSF_TO_LBA(TempMSF[0],TempMSF[1],TempMSF[2]);#undef TempMSF break; } default: { break; } } }
}
/* if(!IsMRW) { UDFPrint(("No MRW\n")); Vcb->CompatFlags &= ~UDF_VCB_IC_MRW_ADDR_PROBLEM; }*/// Vcb->CompatFlags &= ~UDF_VCB_IC_MRW_ADDR_PROBLEM; // some devices report LastTrackNum=0 for full disks Vcb->LastTrackNum = max(Vcb->LastTrackNum, Vcb->FirstTrackNum); Vcb->TrackMap[Vcb->LastTrackNum].LastLba = max(LastLeadOut, Vcb->TrackMap[Vcb->LastTrackNum].LastLba);
Vcb->LastLBA = Vcb->TrackMap[Vcb->LastTrackNum].LastLba;
MyFreePool__(toc);// Vcb->LastLBA=PacketVariable2Fixed(Vcb->LastLBA)-2; return STATUS_SUCCESS;} // end UDFReadAndProcessFullToc()
/* use standard way to determine disk layout (ReadTOC cmd) */OSSTATUSUDFUseStandard( PDEVICE_OBJECT DeviceObject, // the target device object PVCB Vcb // Volume control block from this DevObj ){ OSSTATUS RC = STATUS_SUCCESS; PREAD_TOC_USER_OUT toc = (PREAD_TOC_USER_OUT)MyAllocatePool__(NonPagedPool,max(Vcb->BlockSize, sizeof(READ_TOC_USER_OUT)) ); PGET_LAST_SESSION_USER_OUT LastSes = (PGET_LAST_SESSION_USER_OUT)MyAllocatePool__(NonPagedPool,sizeof(GET_LAST_SESSION_USER_OUT) ); uint32 LocalTrackCount;// uint32 LocalTocLength; uint32 TocEntry;#ifdef _BROWSE_UDF_ uint32 OldTrkNum; uint32 TrkNum; SIZE_T ReadBytes, i, len;#endif //_BROWSE_UDF_#ifdef UDF_FORMAT_MEDIA PUDFFmtState fms = Vcb->fms;#else #define fms FALSE#endif //UDF_FORMAT_MEDIA
UDFPrint(("UDFUseStandard\n"));
_SEH2_TRY {
if(!toc || !LastSes) { try_return (RC = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory(toc,sizeof(READ_TOC_TOC));
Vcb->VCBFlags |= UDF_VCB_FLAGS_USE_STD;
RC = UDFPhSendIOCTL(IOCTL_CDROM_READ_TOC,DeviceObject, toc,sizeof(READ_TOC_USER_OUT), toc,sizeof(READ_TOC_USER_OUT), TRUE,NULL );
if((RC == STATUS_DEVICE_NOT_READY) || (RC == STATUS_NO_MEDIA_IN_DEVICE)) { try_return(RC); }#ifdef UDF_FORMAT_MEDIA if(fms->opt_media == MT_none) { try_return(RC = STATUS_NO_MEDIA_IN_DEVICE); }#endif //UDF_FORMAT_MEDIA
// If even standard read toc does not work, then use default values if(!OS_SUCCESS(RC)) {
RC = UDFReallocTrackMap(Vcb, 2); if(!OS_SUCCESS(RC)) { try_return(RC); }
Vcb->LastSession=1; Vcb->FirstTrackNum=1;// Vcb->FirstLBA=0; Vcb->LastTrackNum=1; Vcb->TrackMap[1].FirstLba = Vcb->FirstLBA; Vcb->TrackMap[1].LastLba = Vcb->LastLBA; Vcb->TrackMap[1].PacketSize = PACKETSIZE_UDF;#ifdef UDF_FORMAT_MEDIA if(!fms) {#endif //UDF_FORMAT_MEDIA
#ifdef _BROWSE_UDF_#ifdef UDF_HDD_SUPPORT if(UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) { try_return(RC = STATUS_SUCCESS); }#endif //UDF_HDD_SUPPORT#endif //_BROWSE_UDF_
#ifdef UDF_FORMAT_MEDIA } else {
if(fms->opt_media == MT_HD) { Vcb->LastPossibleLBA = Vcb->LastLBA; try_return(RC = STATUS_SUCCESS); } }#endif //UDF_FORMAT_MEDIA Vcb->LastPossibleLBA = max(Vcb->LastLBA, DEFAULT_LAST_LBA_FP_CD); Vcb->TrackMap[1].DataParam = TrkInfo_Dat_XA | TrkInfo_FP | TrkInfo_Packet; Vcb->TrackMap[1].TrackParam = TrkInfo_Trk_XA; Vcb->TrackMap[1].NWA = 0xffffffff; Vcb->NWA = DEFAULT_LAST_LBA_FP_CD + 7 + 1; try_return(RC = STATUS_SUCCESS); }
#ifdef _CONSOLE Vcb->PhDeviceType = FILE_DEVICE_CD_ROM;#endif //_CONSOLE
LocalTrackCount = toc->Tracks.Last_TrackSes - toc->Tracks.First_TrackSes + 1;// LocalTocLength = PtrOffset( toc, &(toc->TrackData[LocalTrackCount + 1]) ); /* FIXME ReactOS Assume PtrOffset is not changing it's arguments? */
// Get out if there is an immediate problem with the TOC. if(toc->Tracks.First_TrackSes > toc->Tracks.Last_TrackSes) { try_return(RC = STATUS_DISK_CORRUPT_ERROR); }
#ifdef _BROWSE_UDF_ Vcb->LastTrackNum=toc->Tracks.Last_TrackSes; Vcb->FirstTrackNum=toc->Tracks.First_TrackSes; // some devices report LastTrackNum=0 for full disks Vcb->LastTrackNum = max(Vcb->LastTrackNum, Vcb->FirstTrackNum);
RC = UDFReallocTrackMap(Vcb, MAXIMUM_NUMBER_OF_TRACKS+1);/* if(Vcb->TrackMap) { MyFreePool__(Vcb->TrackMap); Vcb->TrackMap = NULL; } Vcb->TrackMap = (PUDFTrackMap) MyAllocatePool__(NonPagedPool, (MAXIMUM_NUMBER_OF_TRACKS+1)*sizeof(UDFTrackMap)); if(!Vcb->TrackMap) { MyFreePool__(toc); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(Vcb->TrackMap,(MAXIMUM_NUMBER_OF_TRACKS+1)*sizeof(UDFTrackMap));*/ if(!OS_SUCCESS(RC)) { BrutePoint(); try_return(RC); } // find 1st and last session RC = UDFPhSendIOCTL(IOCTL_CDROM_GET_LAST_SESSION,DeviceObject, LastSes,sizeof(GET_LAST_SESSION_USER_OUT), LastSes,sizeof(GET_LAST_SESSION_USER_OUT), TRUE,NULL );
if(OS_SUCCESS(RC)) { TrkNum = LastSes->LastSes_1stTrack.TrackNum; Vcb->LastSession = LastSes->Sessions.First_TrackSes; for(TocEntry=0;TocEntry<LocalTrackCount + 1;TocEntry++) { if(toc->TrackData[TocEntry].TrackNum == TrkNum) { Vcb->TrackMap[TrkNum].Session = Vcb->LastSession; } } }
OldTrkNum = 0; // Scan toc for first & last LBA for(TocEntry=0;TocEntry<LocalTrackCount + 1;TocEntry++) {#define TempMSF toc->TrackData[TocEntry].LBA TrkNum = toc->TrackData[TocEntry].TrackNum;#ifdef UDF_DBG if (TrkNum >= MAXIMUM_NUMBER_OF_TRACKS && TrkNum != TOC_LastTrack_ID) { UDFPrint(("UDFUseStandard: Array out of bounds\n")); BrutePoint(); try_return(RC = STATUS_SUCCESS); } UDFPrint(("Track N %d (0x%x) first LBA %ld (%lx) \n",TrkNum,TrkNum, MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3]), MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3])));#endif // UDF_DBG if(Vcb->FirstTrackNum == TrkNum) { Vcb->FirstLBA = MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3]); if(Vcb->FirstLBA & 0x80000000) { Vcb->FirstLBA = 0; } } if(TOC_LastTrack_ID == TrkNum) { Vcb->LastLBA = MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3])-1; Vcb->TrackMap[OldTrkNum].LastLba = Vcb->LastLBA-1; UDFPrint(("UDFUseStandard: Last track entry, break TOC scan\n"));// continue; break; } else { Vcb->TrackMap[TrkNum].FirstLba = MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3]); if(Vcb->TrackMap[TrkNum].FirstLba & 0x80000000) Vcb->TrackMap[TrkNum].FirstLba = 0; if(TrkNum) { if (TOC_LastTrack_ID == OldTrkNum) { UDFPrint(("UDFUseStandard: Wrong previous track number\n")); BrutePoint(); } else { Vcb->TrackMap[OldTrkNum].LastLba = Vcb->TrackMap[TrkNum].FirstLba-1; } } } // check track type switch(toc->TrackData[TocEntry].Control & TocControl_TrkMode_Mask) { case TocControl_TrkMode_Data: case TocControl_TrkMode_IncrData: Vcb->TrackMap[TrkNum].DataParam = TrkInfo_Dat_XA; Vcb->TrackMap[TrkNum].TrackParam = TrkInfo_Trk_XA; break; default: Vcb->TrackMap[TrkNum].DataParam = TrkInfo_Dat_unknown; Vcb->TrackMap[TrkNum].TrackParam = TrkInfo_Trk_unknown; } OldTrkNum = TrkNum;#undef TempMSF }
TrkNum = Vcb->LastTrackNum; RC = STATUS_SUCCESS; // find last _valid_ track for(;TrkNum;TrkNum--) { if((Vcb->TrackMap[TrkNum].DataParam != TrkInfo_Dat_unknown) && (Vcb->TrackMap[TrkNum].TrackParam != TrkInfo_Trk_unknown)) { RC = STATUS_UNSUCCESSFUL; Vcb->LastTrackNum = TrkNum; break; } } // no valid tracks... if(!TrkNum) { UDFPrint(("UDFUseStandard: no valid tracks...\n")); try_return(RC = STATUS_UNRECOGNIZED_VOLUME); } i = 0;
// Check for last VP track. Some last sectors may belong to Link-data & // be unreadable. We should forget about them, because UDF needs // last _readable_ sector. while(!OS_SUCCESS(RC) && (i<8)) { RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, (int8*)toc, Vcb->BlockSize, ((uint64)(Vcb->TrackMap[TrkNum].LastLba-i)) << Vcb->BlockSizeBits, &ReadBytes, PH_TMP_BUFFER); i++; } if(OS_SUCCESS(RC)) { Vcb->LastLBA = Vcb->TrackMap[TrkNum].LastLba-i+1;/* if(i) { Vcb->TrackMap[TrkNum].PacketSize = PACKETSIZE_UDF; Vcb->TrackMap[TrkNum].; }*/ } else {
// Check for FP track. READ_TOC reports actual track length, but // Link-data is hidden & unreadable for us. So, available track // length may be less than actual. Here we assume that Packet-size // is PACKETSIZE_UDF. i = 0; len = Vcb->TrackMap[TrkNum].LastLba - Vcb->TrackMap[TrkNum].FirstLba + 1; len = (uint32)(((int64)len*PACKETSIZE_UDF) / (PACKETSIZE_UDF+7));
while(!OS_SUCCESS(RC) && (i<9)) { RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, (int8*)toc, Vcb->BlockSize, ((uint64)(Vcb->TrackMap[TrkNum].FirstLba-i+len)) << Vcb->BlockSizeBits, &ReadBytes, PH_TMP_BUFFER); i++; } if(OS_SUCCESS(RC)) { Vcb->LastLBA = Vcb->TrackMap[TrkNum].LastLba = Vcb->TrackMap[TrkNum].FirstLba-i+len+1; Vcb->TrackMap[TrkNum].PacketSize = PACKETSIZE_UDF;// Vcb->TrackMap[TrkNum].; } else if(RC == STATUS_INVALID_DEVICE_REQUEST) { // wrap return code from Audio-disk RC = STATUS_SUCCESS; } }
#ifdef UDF_CDRW_EMULATION_ON_ROM Vcb->LastPossibleLBA = Vcb->LastLBA+7+1+1024; Vcb->NWA = Vcb->LastLBA+7+1;#else Vcb->LastPossibleLBA = Vcb->NWA = Vcb->LastLBA+7+1;#endif //UDF_CDRW_EMULATION_ON_ROM
#else //_BROWSE_UDF_
Vcb->FirstTrackNum=toc->Tracks.Last_TrackSes; Vcb->LastTrackNum=toc->Tracks.First_TrackSes;
// Scan toc for first & last LBA for(TocEntry=0;TocEntry<LocalTrackCount + 1;TocEntry++) {#define TempMSF toc->TrackData[TocEntry].LBA if(Vcb->FirstTrackNum == toc->TrackData[TocEntry].TrackNum) { Vcb->FirstLBA = MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3]); if(Vcb->FirstLBA & 0x80000000) { Vcb->FirstLBA = 0; } } if(TOC_LastTrack_ID == toc->TrackData[TocEntry].TrackNum) { Vcb->LastLBA = MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3])-1; }#undef TempMSF }
// Vcb->LastLBA=PacketVariable2Fixed(Vcb->LastLBA)-2; Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_FP_CD;#endif //_BROWSE_UDF_try_exit: NOTHING; } _SEH2_FINALLY { if(toc) MyFreePool__(toc); if(LastSes) MyFreePool__(LastSes); } _SEH2_END;
return RC;} // end UDFUseStandard()
/* Get block size (for read operation) */OSSTATUSUDFGetBlockSize( IN PDEVICE_OBJECT DeviceObject, // the target device object IN PVCB Vcb // Volume control block from this DevObj ){ OSSTATUS RC = STATUS_SUCCESS; PDISK_GEOMETRY DiskGeometry = (PDISK_GEOMETRY)MyAllocatePool__(NonPagedPool,sizeof(DISK_GEOMETRY)); PPARTITION_INFORMATION PartitionInfo = (PPARTITION_INFORMATION)MyAllocatePool__(NonPagedPool,sizeof(PARTITION_INFORMATION)*2);#ifdef UDF_FORMAT_MEDIA PUDFFmtState fms = Vcb->fms;#else #define fms FALSE#endif //UDF_FORMAT_MEDIA
if(!DiskGeometry || !PartitionInfo) try_return (RC = STATUS_INSUFFICIENT_RESOURCES);
#ifdef _BROWSE_UDF_
#ifdef UDF_HDD_SUPPORT if(!fms) { if(UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) { UDFPrint(("UDFGetBlockSize: HDD\n")); RC = UDFPhSendIOCTL(IOCTL_DISK_GET_DRIVE_GEOMETRY,DeviceObject, 0,NULL, DiskGeometry,sizeof(DISK_GEOMETRY), TRUE,NULL ); Vcb->BlockSize = (OS_SUCCESS(RC)) ? DiskGeometry->BytesPerSector : 512; if(!NT_SUCCESS(RC)) try_return(RC); RC = UDFPhSendIOCTL(IOCTL_DISK_GET_PARTITION_INFO,DeviceObject, 0,NULL, PartitionInfo,sizeof(PARTITION_INFORMATION), TRUE,NULL ); if(!NT_SUCCESS(RC)) { UDFPrint(("UDFGetBlockSize: IOCTL_DISK_GET_PARTITION_INFO failed\n")); if(RC == STATUS_INVALID_DEVICE_REQUEST) /* ReactOS Code Change (was =) */ RC = STATUS_UNRECOGNIZED_VOLUME; try_return(RC); } if(PartitionInfo->PartitionType != PARTITION_IFS) { UDFPrint(("UDFGetBlockSize: PartitionInfo->PartitionType != PARTITION_IFS\n")); try_return(RC = STATUS_UNRECOGNIZED_VOLUME); } } else {#endif //UDF_HDD_SUPPORT RC = UDFPhSendIOCTL(IOCTL_CDROM_GET_DRIVE_GEOMETRY,DeviceObject, DiskGeometry,sizeof(DISK_GEOMETRY), DiskGeometry,sizeof(DISK_GEOMETRY), TRUE,NULL );
if(RC == STATUS_DEVICE_NOT_READY) { // probably, the device is really busy, may be by CD/DVD recording UserPrint((" busy (0)\n")); try_return(RC); }
Vcb->BlockSize = (OS_SUCCESS(RC)) ? DiskGeometry->BytesPerSector : 2048;#ifdef UDF_HDD_SUPPORT } }#endif //UDF_HDD_SUPPORT
#endif //_BROWSE_UDF_
#ifdef UDF_FORMAT_MEDIA if(fms) { RC = UDFPhSendIOCTL(IOCTL_CDROM_GET_DRIVE_GEOMETRY,DeviceObject, DiskGeometry,sizeof(DISK_GEOMETRY), DiskGeometry,sizeof(DISK_GEOMETRY), FALSE, NULL );
if(!NT_SUCCESS(RC)) { RC = UDFPhSendIOCTL(IOCTL_DISK_GET_DRIVE_GEOMETRY,DeviceObject, DiskGeometry,sizeof(DISK_GEOMETRY), DiskGeometry,sizeof(DISK_GEOMETRY), FALSE, NULL ); if(NT_SUCCESS(RC)) { fms->opt_media = MT_HD; RC = UDFPhSendIOCTL(IOCTL_DISK_GET_PARTITION_INFO,DeviceObject, NULL,0, PartitionInfo,sizeof(PARTITION_INFORMATION)*2, FALSE, NULL ); if(!NT_SUCCESS(RC)) { LONG HiOffs=0; RC = SetFilePointer(DeviceObject->h,0,&HiOffs,FILE_END); } } }
if(RC == STATUS_DEVICE_NOT_READY) { // probably, the device is really busy, may be by CD/DVD recording UserPrint((" busy\n")); try_return(RC ); }
Vcb->BlockSize = (NT_SUCCESS(RC)) ? DiskGeometry->BytesPerSector : 2048; }#endif //UDF_FORMAT_MEDIA
// Block size must be an even multiple of 512 switch (Vcb->BlockSize) { case 2048: Vcb->BlockSizeBits = 11; break;#ifdef UDF_HDD_SUPPORT case 512: Vcb->BlockSizeBits = 9; break; case 1024: Vcb->BlockSizeBits = 10; break; case 4096: Vcb->BlockSizeBits = 12; break; case 8192: Vcb->BlockSizeBits = 13; break;#endif //UDF_HDD_SUPPORT default: { UserPrint(("UDF: Bad block size (%ld)\n", Vcb->BlockSize)); try_return(RC = STATUS_UNSUCCESSFUL); } }
#ifdef UDF_HDD_SUPPORT if(#ifdef _BROWSE_UDF_ (!fms && (UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK)) ||#endif //_BROWSE_UDF_#ifdef UDF_FORMAT_MEDIA (fms && fms->opt_media == MT_HD) ||#endif //UDF_FORMAT_MEDIA FALSE ) {
#ifdef UDF_FORMAT_MEDIA if(fms && !NT_SUCCESS(RC)) try_return(STATUS_UNSUCCESSFUL);#endif //UDF_FORMAT_MEDIA
Vcb->FirstLBA=0;//(ULONG)(PartitionInfo->StartingOffset.QuadPart >> Vcb->BlockSizeBits); Vcb->LastPossibleLBA = Vcb->LastLBA = (uint32)(PartitionInfo->PartitionLength.QuadPart >> Vcb->BlockSizeBits)/* + Vcb->FirstLBA*/ - 1; } else {#endif //UDF_HDD_SUPPORT Vcb->FirstLBA=0; if(OS_SUCCESS(RC)) { Vcb->LastLBA = (uint32)(DiskGeometry->Cylinders.QuadPart * DiskGeometry->TracksPerCylinder * DiskGeometry->SectorsPerTrack - 1); if(Vcb->LastLBA == 0x7fffffff) { Vcb->LastLBA = UDFIsDvdMedia(Vcb) ? DEFAULT_LAST_LBA_DVD : DEFAULT_LAST_LBA_FP_CD; } } else { Vcb->LastLBA = UDFIsDvdMedia(Vcb) ? DEFAULT_LAST_LBA_DVD : DEFAULT_LAST_LBA_FP_CD; } Vcb->LastPossibleLBA = Vcb->LastLBA;#ifdef UDF_HDD_SUPPORT }#endif //UDF_HDD_SUPPORT
#ifdef _BROWSE_UDF_// if(UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) { Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize;// } else {// Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize;// }#else //_BROWSE_UDF_ if(fms->opt_media == MT_HD) { Vcb->WriteBlockSize = Vcb->BlockSize; } else { Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize; }#endif //_BROWSE_UDF_
RC = STATUS_SUCCESS;
try_exit: NOTHING;
UDFPrint(("UDFGetBlockSize:\nBlock size is %x, Block size bits %x, Last LBA is %x\n", Vcb->BlockSize, Vcb->BlockSizeBits, Vcb->LastLBA));
MyFreePool__(PartitionInfo); MyFreePool__(DiskGeometry); return RC;
} // end UDFGetBlockSize()
#ifdef _BROWSE_UDF_
OSSTATUSUDFCheckTrackFPAddressing(// IN PDEVICE_OBJECT DeviceObject, // the target device object IN PVCB Vcb, // Volume control block from this DevObj IN ULONG TrackNum ){ OSSTATUS RC = STATUS_SUCCESS;// OSSTATUS RC2 = STATUS_UNSUCCESSFUL; uint32 lba=0; uint32 i; uint8* Buffer;// SIZE_T ReadBytes;
uint8 user_data;
ULONG FirstChunkLen = 0;
ULONG NextChunkLen = 0; ULONG NextChunkLenCount = 0;
ULONG NextChunkLenOth = 0; ULONG NextChunkLenOthCount = 0;// ULONG MRW_Offset = 0;
PLL_READ_USER_IN pLLR_in; PCD_SECTOR_HEADER pHdr;/* uint8 cMSF[3] = {0,2,0}; uint8 cMSF1[3] = {0,2,1};*/
if(!Vcb->TrackMap) { Vcb->CompatFlags &= ~UDF_VCB_IC_FP_ADDR_PROBLEM; return STATUS_SUCCESS; }
Buffer = (uint8*)DbgAllocatePoolWithTag(NonPagedPool, max(Vcb->BlockSize, sizeof(LL_READ_USER_IN)+16), 'pNWD'); if(!Buffer) return STATUS_INSUFFICIENT_RESOURCES; pLLR_in = (PLL_READ_USER_IN)Buffer; pHdr = (PCD_SECTOR_HEADER)(Buffer+sizeof(LL_READ_USER_IN));
/* if(Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM) { MRW_Offset = (MRW_DMA_OFFSET/32)*39; }*/
user_data = 0; for(i=0; i<=0x200; i++) {
RtlZeroMemory(pLLR_in, sizeof(pLLR_in)+16); pLLR_in->ExpectedBlkType = ReadCd_BlkType_Any; pLLR_in->LBA = i; pLLR_in->NumOfBlocks = 1; pLLR_in->Flags.Flags = ReadCd_Header_Hdr;// pLLR_in->UseMFS = FALSE; // already zero// MOV_MSF(pLLR_in->Starting_MSF, cMSF);// MOV_MSF(pLLR_in->Ending_MSF, cMSF1); RtlZeroMemory(pHdr, sizeof(CD_SECTOR_HEADER)); RC = UDFPhSendIOCTL(IOCTL_CDRW_LL_READ, Vcb->TargetDeviceObject, pLLR_in, sizeof(LL_READ_USER_IN), pHdr, sizeof(CD_SECTOR_HEADER), TRUE, NULL );
/* RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, Buffer, Vcb->BlockSize, ((uint64)(i+MRW_Offset)) << Vcb->BlockSizeBits, &ReadBytes, 0);*/
// skip unreadable if(!OS_SUCCESS(RC)) { UDFPrint((" Read error at lba %x\n", i)); continue; }
// skip strange (damaged ?) blocks if((pHdr->Mode.Flags & WParam_SubHdr_Mode_Mask) != WParam_SubHdr_Mode1 && (pHdr->Mode.Flags & WParam_SubHdr_Mode_Mask) != WParam_SubHdr_Mode2) { UDFPrint((" Unexpected data type (%x) at lba %x\n", pHdr->Mode.Flags & WParam_SubHdr_Mode_Mask, i)); continue; }
if((pHdr->Mode.Flags & WParam_SubHdr_Format_Mask) == WParam_SubHdr_Format_UserData && !user_data) { lba = i; }
/* if(OS_SUCCESS(RC) && !OS_SUCCESS(RC2)) { lba = i; }*/
if((pHdr->Mode.Flags & WParam_SubHdr_Format_Mask) != WParam_SubHdr_Format_UserData && user_data) {// if(!OS_SUCCESS(RC) && OS_SUCCESS(RC2)) { UDFPrint((" %x - %x (%x sectors)\n", lba, i-1, i-lba)); if(!FirstChunkLen) { FirstChunkLen = i-lba; } else { if(!NextChunkLen) { NextChunkLen = i-lba; NextChunkLenCount++; } else { if(NextChunkLen == i-lba) { NextChunkLenCount++; } else { if((NextChunkLenOth+1) % (NextChunkLen+1)) { NextChunkLenOth = i-lba; NextChunkLenOthCount++; } else { NextChunkLenCount++; } } } } } user_data = ((pHdr->Mode.Flags & WParam_SubHdr_Format_Mask) == WParam_SubHdr_Format_UserData);// RC2 = RC; }
DbgFreePool(Buffer);
if(!NextChunkLenCount && !NextChunkLenOthCount) { Vcb->CompatFlags &= ~UDF_VCB_IC_FP_ADDR_PROBLEM; return STATUS_SUCCESS; } if(NextChunkLenOthCount > NextChunkLenCount) { NextChunkLen = NextChunkLenOth; } if(NextChunkLen > PACKETSIZE_UDF+7) { Vcb->CompatFlags &= ~UDF_VCB_IC_FP_ADDR_PROBLEM; return STATUS_SUCCESS; } Vcb->TrackMap[TrackNum].DataParam &= ~TrkInfo_Dat_Mask; Vcb->TrackMap[TrackNum].DataParam |= TrkInfo_Dat_XA; Vcb->TrackMap[TrackNum].Flags |= TrackMap_FixFPAddressing; Vcb->TrackMap[TrackNum].PacketSize = 1; while(NextChunkLen >> Vcb->TrackMap[TrackNum].PacketSize) { Vcb->TrackMap[TrackNum].PacketSize++; } Vcb->TrackMap[TrackNum].PacketSize = 1 << (Vcb->TrackMap[TrackNum].PacketSize-1); Vcb->TrackMap[TrackNum].TrackFPOffset = NextChunkLen - FirstChunkLen; // !!!!! Vcb->TrackMap[TrackNum].PacketFPOffset = Vcb->TrackMap[TrackNum].TrackFPOffset;//0;//NextChunkLenOth - FirstChunkLen; Vcb->TrackMap[TrackNum].LastLba = (Vcb->TrackMap[TrackNum].LastLba*Vcb->TrackMap[TrackNum].PacketSize) / (Vcb->TrackMap[TrackNum].PacketSize + 7);
return STATUS_SUCCESS;} // end UDFCheckTrackFPAddressing()
uint32UDFFixFPAddress( IN PVCB Vcb, // Volume control block from this DevObj IN uint32 Lba ){ uint32 i = Vcb->LastReadTrack; uint32 pk; uint32 rel;
// if(Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM) { if(Vcb->TrackMap[i].Flags & TrackMap_FixMRWAddressing) { pk = Lba / MRW_DA_SIZE; rel = Lba % MRW_DA_SIZE; Lba = pk*MRW_DMA_SEGMENT_SIZE + rel; Lba += MRW_DMA_OFFSET; } if(Vcb->TrackMap[i].Flags & TrackMap_FixFPAddressing) { if(Lba < 0x20) return Lba; pk = Lba / Vcb->TrackMap[i].PacketSize; rel = Lba % Vcb->TrackMap[i].PacketSize; UDFPrint(("FixFPAddr: %x -> %x\n", Lba, pk*(Vcb->TrackMap[i].PacketSize+7) + rel)); return pk*(Vcb->TrackMap[i].PacketSize+7) + rel /*- Vcb->TrackMap[i].PacketFPOffset*/; } return Lba;} // end UDFFixFPAddress()
#endif //_BROWSE_UDF_
/* detect device driver & try to read disk layout (use all methods) */OSSTATUSUDFGetDiskInfo( IN PDEVICE_OBJECT DeviceObject, // the target device object IN PVCB Vcb // Volume control block from this DevObj ){ OSSTATUS RC = STATUS_UNRECOGNIZED_VOLUME; int8* ioBuf = (int8*)MyAllocatePool__(NonPagedPool,4096); uint8 MediaType; PLUN_WRITE_PERF_DESC_USER WPerfDesc; uint32 i;// BOOLEAN MRW_problem = FALSE; uint32 SavedFeatures = 0;#ifdef UDF_FORMAT_MEDIA PUDFFmtState fms = Vcb->fms;#else #define fms FALSE#endif //UDF_FORMAT_MEDIA
UDFPrint(("UDFGetDiskInfo\n"));
if(!ioBuf) { return STATUS_INSUFFICIENT_RESOURCES; }
_SEH2_TRY { RC = UDFGetBlockSize(DeviceObject, Vcb); if(!OS_SUCCESS(RC)) try_return(RC);
// Get lower driver signature RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_SIGNATURE,DeviceObject, ioBuf,sizeof(GET_SIGNATURE_USER_OUT), ioBuf,sizeof(GET_SIGNATURE_USER_OUT), TRUE,NULL);
if(!OS_SUCCESS(RC)) {
RC = UDFUseStandard(DeviceObject, Vcb);#ifdef _BROWSE_UDF_ if(!NT_SUCCESS(RC) || fms) try_return(RC);
// assume Device Recordable for now goto GetSignatureFailed;#endif //_BROWSE_UDF_ }
UDFPrint(("UDF: Signature of low driver is : %s \n", ((PGET_SIGNATURE_USER_OUT)(ioBuf))->VendorId));
if(!strncmp( (const char *)(&( ((PGET_SIGNATURE_USER_OUT)(ioBuf))->VendorId[0]) ), Signature,strlen(Signature) )) { UDFPrint(("UDF: *****************************************\n")); UDFPrint(("UDF: ********* Our Device Driver Found ******\n")); UDFPrint(("UDF: *****************************************\n"));
(Vcb->VCBFlags) |= UDF_VCB_FLAGS_OUR_DEVICE_DRIVER;#ifndef _BROWSE_UDF_ // reset driver#ifdef UDF_FORMAT_MEDIA if(!fms->opt_probe) {#endif //UDF_FORMAT_MEDIA UDFResetDeviceDriver(Vcb, Vcb->TargetDeviceObject, FALSE); // lock it ((PPREVENT_MEDIA_REMOVAL_USER_IN)(ioBuf))->PreventMediaRemoval = TRUE; UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL, DeviceObject, ioBuf,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN), NULL,0, FALSE, NULL);#ifdef UDF_FORMAT_MEDIA }#endif //UDF_FORMAT_MEDIA#endif //_BROWSE_UDF_//#else //_BROWSE_UDF_ // get device features UDFPhSendIOCTL( IOCTL_CDRW_GET_DEVICE_INFO, DeviceObject, NULL,0, ioBuf,sizeof(GET_DEVICE_INFO_USER_OUT), FALSE,NULL);
Vcb->SavedFeatures = SavedFeatures = ((PGET_DEVICE_INFO_USER_OUT)ioBuf)->Features; if(!(SavedFeatures & CDRW_FEATURE_SYNC_ON_WRITE)) { UDFPrint(("UDFGetDiskInfo: UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE\n")); Vcb->CompatFlags |= UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE; } if(!(SavedFeatures & CDRW_FEATURE_FORCE_SYNC_BEFORE_READ)) { UDFPrint(("UDFGetDiskInfo: UDF_VCB_IC_SYNCCACHE_BEFORE_READ\n")); Vcb->CompatFlags |= UDF_VCB_IC_SYNCCACHE_BEFORE_READ; } if(SavedFeatures & CDRW_FEATURE_BAD_RW_SEEK) { UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_BAD_RW_SEEK\n")); Vcb->CompatFlags |= UDF_VCB_IC_BAD_RW_SEEK; } // we must check if this is FP-formatted disk in old devices // independently of MediaType they report if(SavedFeatures & CDRW_FEATURE_FP_ADDRESSING_PROBLEM) { UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_FP_ADDRESSING_PROBLEM ?\n")); Vcb->CompatFlags |= UDF_VCB_IC_FP_ADDR_PROBLEM; } if(SavedFeatures & CDRW_FEATURE_MRW_ADDRESSING_PROBLEM) { UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM ?\n")); } if(SavedFeatures & CDRW_FEATURE_FORCE_SYNC_ON_WRITE) { UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_FORCE_SYNC_ON_WRITE\n")); Vcb->VCBFlags |= UDF_VCB_FLAGS_FORCE_SYNC_CACHE; } if(SavedFeatures & CDRW_FEATURE_BAD_DVD_LAST_LBA) { UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_BAD_DVD_LAST_LBA\n")); Vcb->CompatFlags |= UDF_VCB_IC_BAD_DVD_LAST_LBA; } if(SavedFeatures & CDRW_FEATURE_STREAMING) { UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_STREAMING\n")); } if(SavedFeatures & CDRW_FEATURE_OPC) { UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_OPC -> assume OPCNum=1\n")); Vcb->OPCNum = 1; }#ifdef UDF_FORMAT_MEDIA if(SavedFeatures & CDRW_FEATURE_FULL_BLANK_ON_FORMAT) { UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_FULL_BLANK_ON_FORMAT\n")); if((fms->opt_probe || fms->opt_smart_f)/* && (fms->format_media && fms->blank_media*/) { UDFPrint(("UDFGetDiskInfo: force Full Erase\n")); fms->opt_qblank = FALSE; } }#endif //UDF_FORMAT_MEDIA#ifdef _BROWSE_UDF_ // get device buffer size RC = UDFPhSendIOCTL( IOCTL_CDRW_BUFFER_CAPACITY, DeviceObject, NULL,0, ioBuf,sizeof(BUFFER_CAPACITY_BLOCK_USER_OUT), FALSE,NULL); if(NT_SUCCESS(RC)) { Vcb->CdrwBufferSize = ((PBUFFER_CAPACITY_BLOCK_USER_OUT)ioBuf)->BufferLength; } else { Vcb->CdrwBufferSize = 0; } UDFPrint(("UDFGetDiskInfo: CdrwBufferSize = %dKb\n", Vcb->CdrwBufferSize / 1024)); Vcb->CdrwBufferSizeCounter = 0;#endif //_BROWSE_UDF_ // get media type RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_MEDIA_TYPE,DeviceObject, NULL,0,ioBuf,sizeof(GET_MEDIA_TYPE_USER_OUT), FALSE, NULL); if(!OS_SUCCESS(RC)) goto Try_FullToc; Vcb->MediaType = MediaType = ((PGET_MEDIA_TYPE_USER_OUT)ioBuf)->MediaType; UDFPrint(("UDFGetDiskInfo: MediaType %x\n", MediaType));
#ifndef UDF_FORMAT_MEDIA // we shall ignore audio-disks switch(MediaType) { case MediaType_120mm_CDROM_AudioOnly: case MediaType_80mm_CDROM_AudioOnly: case MediaType_120mm_CDR_AudioOnly: case MediaType_80mm_CDR_AudioOnly: case MediaType_120mm_CDRW_AudioOnly: case MediaType_80mm_CDRW_AudioOnly:// case : UDFPrint(("UDFGetDiskInfo: we shall ignore audio-disks...\n")); try_return(RC = STATUS_UNRECOGNIZED_VOLUME); }#endif //UDF_FORMAT_MEDIA
UDFPrint(("UDFGetDiskInfo: Check DVD-disks...\n")); RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_MEDIA_TYPE_EX,DeviceObject, NULL,0,ioBuf,sizeof(GET_MEDIA_TYPE_EX_USER_OUT), FALSE, NULL); if(!OS_SUCCESS(RC)) goto Try_FullToc; Vcb->MediaClassEx = MediaType = (((PGET_MEDIA_TYPE_EX_USER_OUT)ioBuf)->MediaClass); UDFPrint(("UDFGetDiskInfo: MediaClassEx %x\n", MediaType));
#ifdef _BROWSE_UDF_ if(!fms) {
switch(MediaType) {
case CdMediaClass_CDR: case CdMediaClass_DVDR: case CdMediaClass_DVDpR: case CdMediaClass_HD_DVDR: case CdMediaClass_BDR: UDFPrint(("UDFGetDiskInfo: MediaClass R\n")); Vcb->MediaType = MediaType_UnknownSize_CDR; break; case CdMediaClass_CDRW:
if(SavedFeatures & CDRW_FEATURE_MRW_ADDRESSING_PROBLEM) { UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on CD-RW\n")); Vcb->CompatFlags |= UDF_VCB_IC_MRW_ADDR_PROBLEM; }
case CdMediaClass_DVDRW: case CdMediaClass_DVDpRW: case CdMediaClass_DVDRAM: case CdMediaClass_HD_DVDRW: case CdMediaClass_HD_DVDRAM: case CdMediaClass_BDRE: UDFPrint(("UDFGetDiskInfo: MediaClass RW\n")); Vcb->MediaType = MediaType_UnknownSize_CDRW; break; case CdMediaClass_CDROM: case CdMediaClass_DVDROM: case CdMediaClass_HD_DVDROM: case CdMediaClass_BDROM: UDFPrint(("UDFGetDiskInfo: MediaClass ROM\n")); Vcb->MediaType = MediaType_Unknown; // Vcb->MediaType = MediaType_UnknownSize_CDROM; break; default: UDFPrint(("UDFGetDiskInfo: MediaClass Unknown\n")); Vcb->MediaType = MediaType_Unknown; break; } MediaType = Vcb->MediaType;
}#endif //_BROWSE_UDF_
#ifdef UDF_FORMAT_MEDIA
if(fms) {
switch(MediaType) { case CdMediaClass_CDR: UDFPrint(("CdMediaClass_CDR\n")); MediaType = MediaType_UnknownSize_CDR; if(fms->opt_media == MT_AUTO) fms->opt_media = MT_CDR; break; case CdMediaClass_DVDR: UDFPrint(("CdMediaClass_DVDR -> MediaType_UnknownSize_CDR\n")); MediaType = MediaType_UnknownSize_CDR; if(fms->opt_media == MT_AUTO) fms->opt_media = MT_DVDR; break; case CdMediaClass_DVDpR: UDFPrint(("CdMediaClass_DVDpR -> MediaType_UnknownSize_CDR\n")); MediaType = MediaType_UnknownSize_CDR; if(fms->opt_media == MT_AUTO) fms->opt_media = MT_DVDpR; break; case CdMediaClass_HD_DVDR: UDFPrint(("CdMediaClass_HD_DVDR -> MediaType_UnknownSize_CDR\n")); MediaType = MediaType_UnknownSize_CDR; if(fms->opt_media == MT_AUTO) fms->opt_media = MT_DVDR; break; case CdMediaClass_BDR: UDFPrint(("CdMediaClass_BDR -> MediaType_UnknownSize_CDR\n")); MediaType = MediaType_UnknownSize_CDR; if(fms->opt_media == MT_AUTO) fms->opt_media = MT_DVDR; break; case CdMediaClass_CDRW: UDFPrint(("CdMediaClass_CDRW\n")); MediaType = MediaType_UnknownSize_CDRW; if(fms->opt_media == MT_AUTO) fms->opt_media = MT_CDRW; if(SavedFeatures & CDRW_FEATURE_MRW_ADDRESSING_PROBLEM) { UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on CD-RW\n")); Vcb->CompatFlags |= UDF_VCB_IC_MRW_ADDR_PROBLEM; } break; case CdMediaClass_DVDRW: UDFPrint((" CdMediaClass_DVDRW -> MediaType_UnknownSize_CDRW\n")); if(fms->opt_media == MT_AUTO) fms->opt_media = MT_DVDRW; MediaType = MediaType_UnknownSize_CDRW; break; case CdMediaClass_DVDpRW: UDFPrint((" CdMediaClass_DVDpRW -> MediaType_UnknownSize_CDRW\n")); if(fms->opt_media == MT_AUTO) fms->opt_media = MT_DVDpRW; MediaType = MediaType_UnknownSize_CDRW; break; case CdMediaClass_DVDRAM: UDFPrint((" CdMediaClass_DVDRAM -> MediaType_UnknownSize_CDRW\n")); if(fms->opt_media == MT_AUTO) fms->opt_media = MT_DVDRAM; MediaType = MediaType_UnknownSize_CDRW; break; case CdMediaClass_HD_DVDRW: UDFPrint((" CdMediaClass_HD_DVDRW -> MediaType_UnknownSize_CDRW\n")); if(fms->opt_media == MT_AUTO) fms->opt_media = MT_DVDRW; MediaType = MediaType_UnknownSize_CDRW; break; case CdMediaClass_HD_DVDRAM: UDFPrint((" CdMediaClass_HD_DVDRAM -> MediaType_UnknownSize_CDRW\n")); if(fms->opt_media == MT_AUTO) fms->opt_media = MT_DVDRAM; MediaType = MediaType_UnknownSize_CDRW; break; case CdMediaClass_BDRE: UDFPrint((" CdMediaClass_BDRE -> MediaType_UnknownSize_CDRW\n")); if(fms->opt_media == MT_AUTO) fms->opt_media = MT_DVDRW; MediaType = MediaType_UnknownSize_CDRW; break; case CdMediaClass_NoDiscPresent: UDFPrint((" CdMediaClass_NoDiscPresent -> MediaType_NoDiscPresent\n")); MediaType = MediaType_NoDiscPresent; fms->opt_media = MT_none; break; case CdMediaClass_DoorOpen: UDFPrint((" CdMediaClass_DoorOpen -> MediaType_DoorOpen\n")); MediaType = MediaType_DoorOpen; fms->opt_media = MT_none; break; default: UDFPrint((" MediaType_Unknown\n")); MediaType = MediaType_Unknown; break; } if(!apply_force_r(fms)) { my_exit(fms, MKUDF_CANT_APPLY_R); } }
#endif //UDF_FORMAT_MEDIA
Vcb->DVD_Mode = (((PGET_MEDIA_TYPE_EX_USER_OUT)ioBuf)->MediaClassEx == CdMediaClassEx_DVD); Vcb->PhMediaCapFlags = ((PGET_MEDIA_TYPE_EX_USER_OUT)ioBuf)->CapFlags; Vcb->WriteParamsReq = (Vcb->PhMediaCapFlags & CdCapFlags_WriteParamsReq) ? TRUE : FALSE; if(Vcb->DVD_Mode && !(Vcb->PhMediaCapFlags & CdCapFlags_RandomWritable)) { UDFPrint(("UDFGetDiskInfo: DVD && !CdCapFlags_RandomWritable\n")); UDFPrint((" Read-only volume\n"));// BrutePoint();#ifndef UDF_CDRW_EMULATION_ON_ROM Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;#endif }#ifdef UDF_FORMAT_MEDIA if(fms) { if((MediaType == MediaType_NoDiscPresent) || (MediaType == MediaType_DoorOpen)) { UserPrint(("No media in device\n")); my_exit(fms, MKUDF_NO_MEDIA_IN_DEVICE); } }#endif //UDF_FORMAT_MEDIA if(!Vcb->WriteParamsReq) { UDFPrint(("UDFGetDiskInfo: do not use WriteParams\n")); } if(Vcb->PhMediaCapFlags & CdCapFlags_Cav) { UDFPrint(("UDFGetDiskInfo: Use CAV (1)\n")); Vcb->VCBFlags |= UDF_VCB_FLAGS_USE_CAV; }
#ifdef _BROWSE_UDF_ if(!fms) { // check if this device is capable to write on such media if(UDFIsDvdMedia(Vcb)) { //RC = UDFPrint(("UDFGetDiskInfo: update defaulted LastLBA\n")); UDFGetBlockSize(DeviceObject,Vcb); //if(!OS_SUCCESS(RC)) goto Try_FullToc; } else { if((SavedFeatures & CDRW_FEATURE_MRW_ADDRESSING_PROBLEM) && (SavedFeatures & UDF_VCB_IC_FP_ADDR_PROBLEM)) { UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on old CD-ROM\n")); Vcb->CompatFlags |= UDF_VCB_IC_MRW_ADDR_PROBLEM; } } }#endif //_BROWSE_UDF_
/*#ifdef UDF_FORMAT_MEDIA if(fms) { if(MediaType == CdMediaClass_DVDRW) { UserPrint(("Not empty media. Erase required.\n")); my_exit(fms, MKUDF_BLANK_FORMAT_REQUIRED); } }#endif //UDF_FORMAT_MEDIA*/
#define cap ((PGET_CAPABILITIES_3_USER_OUT)ioBuf) // get device capabilities RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_CAPABILITIES,DeviceObject, NULL,0,ioBuf,sizeof(GET_CAPABILITIES_3_USER_OUT), FALSE, NULL); if(!OS_SUCCESS(RC)) goto Try_FullToc;
// check if this device is capable to write on such media RC = UDFPhSendIOCTL(IOCTL_DISK_IS_WRITABLE,DeviceObject, NULL,0,NULL,0,FALSE, NULL); if(RC != STATUS_SUCCESS) { UDFPrint(("IS_WRITABLE - false, doing additional check...\n")); if( ((MediaType >= MediaType_UnknownSize_CDRW) && !(cap->WriteCap & DevCap_write_cd_rw)) || ((MediaType >= MediaType_UnknownSize_CDR) && !(cap->WriteCap & DevCap_write_cd_r)) || (MediaType < MediaType_UnknownSize_CDR) ) { UserPrint(("Hardware Read-only volume\n"));#ifndef UDF_CDRW_EMULATION_ON_ROM Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;#endif //UDF_CDRW_EMULATION_ON_ROM#ifdef UDF_FORMAT_MEDIA if(fms && !fms->opt_read_iso) my_exit(fms, MKUDF_HW_READ_ONLY);#endif //UDF_FORMAT_MEDIA } } else { UDFPrint(("Writable disk\n")); } Vcb->MaxWriteSpeed = cap->MaximumWriteSpeedSupported; Vcb->MaxReadSpeed = cap->MaximumSpeedSupported; if(cap->PageLength >= (sizeof(GET_CAPABILITIES_3_USER_OUT)-2)) { Vcb->CurSpeed = max(cap->CurrentSpeed, cap->CurrentWriteSpeed3); if(cap->LunWPerfDescriptorCount && cap->LunWPerfDescriptorCount != 0xffff) { ULONG n; UDFPrint(("Write performance descriptor(s) found: %x\n", cap->LunWPerfDescriptorCount)); n = (4096 - sizeof(GET_CAPABILITIES_3_USER_OUT)) / sizeof(LUN_WRITE_PERF_DESC_USER); n = min(n, cap->LunWPerfDescriptorCount); // get device capabilities RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_CAPABILITIES,DeviceObject, ioBuf,sizeof(GET_CAPABILITIES_3_USER_OUT)+n*sizeof(LUN_WRITE_PERF_DESC_USER), ioBuf,sizeof(GET_CAPABILITIES_3_USER_OUT)+n*sizeof(LUN_WRITE_PERF_DESC_USER), TRUE,NULL); if(OS_SUCCESS(RC)) { WPerfDesc = (PLUN_WRITE_PERF_DESC_USER)(ioBuf + sizeof(GET_CAPABILITIES_3_USER_OUT)); n = FALSE; for(i = 0; i<n; i++) { if((WPerfDesc[i].RotationControl & LunWPerf_RotCtrl_Mask) == LunWPerf_RotCtrl_CAV) { Vcb->VCBFlags |= UDF_VCB_FLAGS_USE_CAV; if(!n) { Vcb->CurSpeed = WPerfDesc[i].WriteSpeedSupported; n = TRUE; UDFPrint(("Use CAV\n")); } else { Vcb->CurSpeed = max(WPerfDesc[i].WriteSpeedSupported, Vcb->CurSpeed); } UDFPrint(("supports speed %dX\n", Vcb->CurSpeed/176)); //break; } } if(n) { UDFPrint(("Set r/w speeds to %dX\n", Vcb->CurSpeed/176)); Vcb->MaxWriteSpeed = Vcb->MaxReadSpeed = Vcb->CurSpeed; } } } } else { Vcb->CurSpeed = max(cap->CurrentSpeed, cap->CurrentWriteSpeed); } UDFPrint((" Speeds r/w %dX/%dX\n", Vcb->CurSpeed/176, cap->CurrentWriteSpeed/176));
if(Vcb->VCBFlags & UDF_VCB_FLAGS_USE_CAV) { // limit both read & write speed to last write speed for CAV mode // some drives damage data when speed is adjusted during recording process // even in packet mode UDFSetSpeeds(Vcb); } UDFSetCaching(Vcb);
#undef cap#ifdef UDF_FORMAT_MEDIA if(fms) { if( (fms->auto_media || (fms->opt_media == MT_AUTO)) && (fms->opt_media < MT_DVDR) ) { if(MediaType < MediaType_UnknownSize_CDRW) { fms->opt_media = MT_CDR; } else { fms->opt_media = MT_CDRW; } } if(!apply_force_r(fms)) { my_exit(fms, MKUDF_CANT_APPLY_R); } }#endif //UDF_FORMAT_MEDIA RC = UDFReadDiscTrackInfo(DeviceObject, Vcb);
if(!OS_SUCCESS(RC)) { // may be we have a CD-ROM deviceTry_FullToc: UDFPrint(("Hardware Read-only volume (2)\n"));// BrutePoint();#ifndef UDF_CDRW_EMULATION_ON_ROM Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;#endif
RC = UDFReadAndProcessFullToc(DeviceObject, Vcb);
if(!OS_SUCCESS(RC)) { RC = UDFUseStandard(DeviceObject,Vcb); if(!OS_SUCCESS(RC)) try_return(RC); }
} } else {#ifdef _BROWSE_UDF_GetSignatureFailed:#endif RC = UDFUseStandard(DeviceObject, Vcb); if(!OS_SUCCESS(RC)) try_return(RC); }
try_exit: NOTHING;
} _SEH2_FINALLY {
if(ioBuf) MyFreePool__(ioBuf);
if(UDFIsDvdMedia(Vcb) && (Vcb->CompatFlags & UDF_VCB_IC_BAD_DVD_LAST_LBA) && (Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY) && Vcb->LastLBA && (Vcb->LastLBA < DEFAULT_LAST_LBA_DVD)) { UDFPrint(("UDF: Bad DVD last LBA %x, fixup!\n", Vcb->LastLBA)); Vcb->LastLBA = DEFAULT_LAST_LBA_DVD; Vcb->NWA = 0; }
if(UDFIsDvdMedia(Vcb) && !Vcb->FirstLBA && !Vcb->LastPossibleLBA) { UDFPrint(("UDF: Empty DVD. Use bogus values for now\n")); Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_DVD; Vcb->LastLBA = 0; }
if((Vcb->LastPossibleLBA & 0x80000000) || (Vcb->LastPossibleLBA < Vcb->LastLBA)) { UDFPrint(("UDF: bad LastPossibleLBA %x -> %x\n", Vcb->LastPossibleLBA, Vcb->LastLBA)); Vcb->LastPossibleLBA = Vcb->LastLBA; } if(!Vcb->WriteBlockSize) Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize;
#ifdef _BROWSE_UDF_ if(Vcb->TrackMap) { if(Vcb->TrackMap[Vcb->LastTrackNum].LastLba > Vcb->NWA) { if(Vcb->NWA) { if(Vcb->TrackMap[Vcb->LastTrackNum].DataParam & TrkInfo_FP) { Vcb->LastLBA = Vcb->NWA-1; } else { Vcb->LastLBA = Vcb->NWA-7-1; } } } else { if((Vcb->LastTrackNum > 1) && (Vcb->TrackMap[Vcb->LastTrackNum-1].FirstLba >= Vcb->TrackMap[Vcb->LastTrackNum-1].LastLba)) { Vcb->LastLBA = Vcb->TrackMap[Vcb->LastTrackNum-1].LastLba; } } }
for(i=0; i<32; i++) { if(!(Vcb->LastPossibleLBA >> i)) break; } if(i > 20) { Vcb->WCacheBlocksPerFrameSh = max(Vcb->WCacheBlocksPerFrameSh, (2*i)/5+2); Vcb->WCacheBlocksPerFrameSh = min(Vcb->WCacheBlocksPerFrameSh, 16); }
if(Vcb->CompatFlags & UDF_VCB_IC_FP_ADDR_PROBLEM) { // Check first 0x200 blocks UDFCheckTrackFPAddressing(Vcb, Vcb->FirstTrackNum); // if we really have such a problem, fix LastLBA if(Vcb->CompatFlags & UDF_VCB_IC_FP_ADDR_PROBLEM) { UDFPrint(("UDF: Fix LastLBA: %x -> %x\n", Vcb->LastLBA, (Vcb->LastLBA*32) / 39)); Vcb->LastLBA = (Vcb->LastLBA*32) / 39; } }#endif //_BROWSE_UDF_
if(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY) { if(!Vcb->BlankCD && Vcb->MediaType != MediaType_UnknownSize_CDRW) { UDFPrint(("UDFGetDiskInfo: R/O+!Blank+!RW -> !RAW\n")); Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK; } else { UDFPrint(("UDFGetDiskInfo: Blank or RW\n")); } }
UDFPrint(("UDF: ------------------------------------------\n")); UDFPrint(("UDF: Media characteristics\n")); UDFPrint(("UDF: Last session: %d\n",Vcb->LastSession)); UDFPrint(("UDF: First track in first session: %d\n",Vcb->FirstTrackNum)); UDFPrint(("UDF: First track in last session: %d\n",Vcb->FirstTrackNumLastSes)); UDFPrint(("UDF: Last track in last session: %d\n",Vcb->LastTrackNum)); UDFPrint(("UDF: First LBA in first session: %x\n",Vcb->FirstLBA)); UDFPrint(("UDF: First LBA in last session: %x\n",Vcb->FirstLBALastSes)); UDFPrint(("UDF: Last LBA in last session: %x\n",Vcb->LastLBA)); UDFPrint(("UDF: First writable LBA (NWA) in last session: %x\n",Vcb->NWA)); UDFPrint(("UDF: Last available LBA beyond end of last session: %x\n",Vcb->LastPossibleLBA)); UDFPrint(("UDF: blocks per frame: %x\n",1 << Vcb->WCacheBlocksPerFrameSh)); UDFPrint(("UDF: Flags: %s%s\n", Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK ? "RAW " : "", Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY ? "R/O " : "WR " )); UDFPrint(("UDF: ------------------------------------------\n"));
#ifdef UDF_FORMAT_MEDIA if(fms && fms->opt_disk_info) { UserPrint(("------------------------------------------\n")); UserPrint(("Media characteristics:\n")); UserPrint((" First writable LBA (NWA) in last session: %x\n",Vcb->NWA)); UserPrint((" Last available LBA beyond end of last session: %x\n",Vcb->LastPossibleLBA)); UserPrint(("------------------------------------------\n")); }#endif //UDF_FORMAT_MEDIA
} _SEH2_END;
UDFPrint(("UDFGetDiskInfo: %x\n", RC)); return(RC);
} // end UDFGetDiskInfo()
//#ifdef _BROWSE_UDF_
OSSTATUSUDFPrepareForReadOperation( IN PVCB Vcb, IN uint32 Lba, IN uint32 BCount ){ if( (Vcb->FsDeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM) ) { Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE; return STATUS_SUCCESS; } uint32 i = Vcb->LastReadTrack; BOOLEAN speed_changed = FALSE;#ifdef _BROWSE_UDF_ PUCHAR tmp; OSSTATUS RC; SIZE_T ReadBytes;#endif //_BROWSE_UDF_
#ifdef _UDF_STRUCTURES_H_ if(Vcb->BSBM_Bitmap) { ULONG i; for(i=0; i<BCount; i++) { if(UDFGetBit((uint32*)(Vcb->BSBM_Bitmap), Lba+i)) { UDFPrint(("R: Known BB @ %#x\n", Lba)); //return STATUS_FT_WRITE_RECOVERY; // this shall not be treated as error and // we shall get IO request to BAD block return STATUS_DEVICE_DATA_ERROR; } } }#endif //_UDF_STRUCTURES_H_
if(!UDFIsDvdMedia(Vcb) && (Vcb->VCBFlags & UDF_VCB_LAST_WRITE) && !(Vcb->VCBFlags & UDF_VCB_FLAGS_NO_SYNC_CACHE) && !(Vcb->CompatFlags & UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE)){
// OSSTATUS RC;
RC = UDFSyncCache(Vcb); } if( (Vcb->VCBFlags & UDF_VCB_LAST_WRITE) && !(Vcb->VCBFlags & UDF_VCB_FLAGS_NO_SYNC_CACHE) &&#ifndef UDF_FORMAT_MEDIA (Vcb->CompatFlags & UDF_VCB_IC_SYNCCACHE_BEFORE_READ) &&#endif //UDF_FORMAT_MEDIA TRUE) {// OSSTATUS RC; UDFSyncCache(Vcb); }
#ifdef _BROWSE_UDF_ if(!UDFIsDvdMedia(Vcb)) { // limit read speed after write operation // to avoid performance degrade durring speed-up/down // on read/write mode switching if(Vcb->VCBFlags & UDF_VCB_FLAGS_USE_CAV) { // limit both read & write speed to last write speed for CAV mode // some drives damage data when speed is adjusted during recording process // even in packet mode if(Vcb->CurSpeed != Vcb->MaxWriteSpeed || Vcb->CurSpeed != Vcb->MaxReadSpeed) { Vcb->CurSpeed = Vcb->MaxWriteSpeed; speed_changed = TRUE; } } else if(Vcb->VCBFlags & UDF_VCB_LAST_WRITE) { // limit read speed to last write speed if(Vcb->CurSpeed > Vcb->MaxWriteSpeed) { Vcb->CurSpeed = Vcb->MaxWriteSpeed; speed_changed = TRUE; } } else if(Vcb->CurSpeed < Vcb->MaxReadSpeed ) { // increment read speed (+1X) Vcb->CurSpeed += 176/1; speed_changed = TRUE; }
if(Vcb->CurSpeed > Vcb->MaxReadSpeed) { Vcb->CurSpeed = Vcb->MaxReadSpeed; } // send speed limits to drive if(speed_changed) { RtlZeroMemory(&(Vcb->SpeedBuf), sizeof(SET_CD_SPEED_EX_USER_IN)); Vcb->SpeedBuf.ReadSpeed = Vcb->CurSpeed; Vcb->SpeedBuf.WriteSpeed = Vcb->MaxWriteSpeed; if(Vcb->VCBFlags & UDF_VCB_FLAGS_USE_CAV) { Vcb->SpeedBuf.RotCtrl = CdSpeed_RotCtrl_CAV; } UDFPrint((" UDFPrepareForReadOperation: set speed to %s %dX/%dX\n", (Vcb->VCBFlags & UDF_VCB_FLAGS_USE_CAV) ? "CAV" : "CLV", Vcb->SpeedBuf.ReadSpeed, Vcb->SpeedBuf.WriteSpeed)); UDFPhSendIOCTL(IOCTL_CDRW_SET_SPEED, Vcb->TargetDeviceObject, &(Vcb->SpeedBuf),sizeof(SET_CD_SPEED_EX_USER_IN), NULL,0,TRUE,NULL); } }
if(UDFIsDvdMedia(Vcb)) return STATUS_SUCCESS;
if(Vcb->LastReadTrack && ((Vcb->TrackMap[i].FirstLba <= Lba) || (Vcb->TrackMap[i].FirstLba & 0x80000000)) && (Vcb->TrackMap[i].LastLba >= Lba)) {check_for_data_track: // check track mode (Mode1/XA) switch((Vcb->TrackMap[i].DataParam & TrkInfo_Dat_Mask)) { case TrkInfo_Dat_Mode1: // Mode1 case TrkInfo_Dat_XA: // XA Mode2 case TrkInfo_Dat_Unknown: // for some stupid irons UDFSetMRWMode(Vcb); break; default: Vcb->IncrementalSeekState = INCREMENTAL_SEEK_NONE; return STATUS_INVALID_PARAMETER; } } else { for(i=Vcb->FirstTrackNum; i<=Vcb->LastTrackNum; i++) { if(((Vcb->TrackMap[i].FirstLba > Lba) && !(Vcb->TrackMap[i].FirstLba & 0x80000000)) || (Vcb->TrackMap[i].LastLba < Lba)) continue; Vcb->LastReadTrack = i; goto check_for_data_track; } Vcb->LastReadTrack = 0; } if(Vcb->IncrementalSeekState != INCREMENTAL_SEEK_WORKAROUND) { Vcb->IncrementalSeekState = INCREMENTAL_SEEK_NONE; return STATUS_SUCCESS; } UDFPrint((" UDFPrepareForReadOperation: seek workaround...\n")); Vcb->IncrementalSeekState = INCREMENTAL_SEEK_DONE;
tmp = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, Vcb->BlockSize, 'bNWD'); if(!tmp) { Vcb->IncrementalSeekState = INCREMENTAL_SEEK_NONE; return STATUS_INSUFFICIENT_RESOURCES; } for(i=0x1000; i<=Lba; i+=0x1000) { RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, tmp, Vcb->BlockSize, ((uint64)UDFFixFPAddress(Vcb,i)) << Vcb->BlockSizeBits, &ReadBytes, 0); UDFPrint((" seek workaround, LBA %x, status %x\n", i, RC)); } DbgFreePool(tmp);#endif //_BROWSE_UDF_
return STATUS_SUCCESS;} // end UDFPrepareForReadOperation()
//#endif //_BROWSE_UDF_
voidUDFUpdateNWA( PVCB Vcb, uint32 LBA, // physical uint32 BCount, OSSTATUS RC ){#ifndef UDF_READ_ONLY_BUILD#ifdef _BROWSE_UDF_ if(!OS_SUCCESS(RC)) { return; } if(!Vcb->CDR_Mode) {
if((Vcb->MediaClassEx == CdMediaClass_DVDRW || Vcb->MediaClassEx == CdMediaClass_DVDpRW || Vcb->MediaClassEx == CdMediaClass_DVDRAM || Vcb->MRWStatus == DiscInfo_BGF_Interrupted || Vcb->MRWStatus == DiscInfo_BGF_InProgress) && (LBA+BCount-1) > Vcb->LastLBA) { ASSERT(Vcb->NWA > Vcb->LastLBA); Vcb->NWA = LBA+BCount; Vcb->LastLBA = Vcb->NWA-1; } if(Vcb->VCBFlags & UDF_VCB_FLAGS_FORCE_SYNC_CACHE) goto sync_cache;/* if(Vcb->CdrwBufferSize) { Vcb->CdrwBufferSizeCounter += BCount * 2048; if(Vcb->CdrwBufferSizeCounter >= Vcb->CdrwBufferSize + 2*2048) { UDFPrint((" UDFUpdateNWA: buffer is full, sync...\n")); Vcb->CdrwBufferSizeCounter = 0; goto sync_cache; } }*/ if(Vcb->SyncCacheState == SYNC_CACHE_RECOVERY_RETRY) { Vcb->VCBFlags |= UDF_VCB_FLAGS_FORCE_SYNC_CACHE; } Vcb->SyncCacheState = SYNC_CACHE_RECOVERY_NONE; return; } if(Vcb->LastLBA < (LBA+BCount)) Vcb->LastLBA = LBA+BCount; if(Vcb->NWA) Vcb->NWA+=BCount+7;sync_cache: if(!(Vcb->CompatFlags & UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE)) { UDFPrint((" UDFUpdateNWA: syncing...\n")); RC = UDFSyncCache(Vcb); }#endif //_BROWSE_UDF_#endif //UDF_READ_ONLY_BUILD} // end UDFUpdateNWA()
/* This routine reads physical sectors *//*OSSTATUSUDFReadSectors( IN PVCB Vcb, IN BOOLEAN Translate, // Translate Logical to Physical IN uint32 Lba, IN uint32 BCount, OUT int8* Buffer, OUT PSIZE_T ReadBytes ){
if(Vcb->FastCache.ReadProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) { return WCacheReadBlocks__(&(Vcb->FastCache), Vcb, Buffer, Lba, BCount, ReadBytes); } return UDFTRead(Vcb, Buffer, BCount*Vcb->BlockSize, Lba, ReadBytes);} // end UDFReadSectors()*/
#ifdef _BROWSE_UDF_
/* This routine reads physical sectors */OSSTATUSUDFReadInSector( IN PVCB Vcb, IN BOOLEAN Translate, // Translate Logical to Physical IN uint32 Lba, IN uint32 i, // offset in sector IN uint32 l, // transfer length IN BOOLEAN Direct, // Disable access to non-cached data OUT int8* Buffer, OUT PSIZE_T ReadBytes ){ int8* tmp_buff; OSSTATUS status; SIZE_T _ReadBytes;
(*ReadBytes) = 0; if(WCacheIsInitialized__(&(Vcb->FastCache)) && (KeGetCurrentIrql() < DISPATCH_LEVEL)) { status = WCacheDirect__(&(Vcb->FastCache), Vcb, Lba, FALSE, &tmp_buff, Direct); if(OS_SUCCESS(status)) { (*ReadBytes) += l; RtlCopyMemory(Buffer, tmp_buff+i, l); } if(!Direct) WCacheEODirect__(&(Vcb->FastCache), Vcb); } else { if(Direct) { return STATUS_INVALID_PARAMETER; } tmp_buff = (int8*)MyAllocatePool__(NonPagedPool, Vcb->BlockSize); if(!tmp_buff) return STATUS_INSUFFICIENT_RESOURCES; status = UDFReadSectors(Vcb, Translate, Lba, 1, FALSE, tmp_buff, &_ReadBytes); if(OS_SUCCESS(status)) { (*ReadBytes) += l; RtlCopyMemory(Buffer, tmp_buff+i, l); } MyFreePool__(tmp_buff); } return status;} // end UDFReadInSector()
/* This routine reads data of unaligned offset & length */OSSTATUSUDFReadData( IN PVCB Vcb, IN BOOLEAN Translate, // Translate Logical to Physical IN int64 Offset, IN uint32 Length, IN BOOLEAN Direct, // Disable access to non-cached data OUT int8* Buffer, OUT PSIZE_T ReadBytes ){ uint32 i, l, Lba, BS=Vcb->BlockSize; uint32 BSh=Vcb->BlockSizeBits; OSSTATUS status; SIZE_T _ReadBytes = 0; Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK; uint32 to_read;
(*ReadBytes) = 0; if(!Length) return STATUS_SUCCESS; if(Vcb->VCBFlags & UDF_VCB_FLAGS_DEAD) return STATUS_NO_SUCH_DEVICE; // read tail of the 1st sector if Offset is not sector_size-aligned Lba = (uint32)(Offset >> BSh); if((i = (uint32)(Offset & (BS-1)))) { l = (BS - i) < Length ? (BS - i) : Length; // here we use 'ReadBytes' 'cause now it's set to zero status = UDFReadInSector(Vcb, Translate, Lba, i, l, Direct, Buffer, ReadBytes); if(!OS_SUCCESS(status)) return status; if(!(Length = Length - l)) return STATUS_SUCCESS; Lba ++; Buffer += l; } // read sector_size-aligned part i = Length >> BSh; while(i) { to_read = min(i, 64); status = UDFReadSectors(Vcb, Translate, Lba, to_read, Direct, Buffer, &_ReadBytes); (*ReadBytes) += _ReadBytes; if(!OS_SUCCESS(status)) { return status; } Buffer += to_read<<BSh; Length -= to_read<<BSh; Lba += to_read; i -= to_read; } // read head of the last sector if(!Length) return STATUS_SUCCESS; status = UDFReadInSector(Vcb, Translate, Lba, 0, Length, Direct, Buffer, &_ReadBytes); (*ReadBytes) += _ReadBytes;
return status;} // end UDFReadData()
#endif //_BROWSE_UDF_
#ifndef UDF_READ_ONLY_BUILD/* This routine writes physical sectors. This routine supposes Lba & Length alignment on WriteBlock (packet) size. */OSSTATUSUDFWriteSectors( IN PVCB Vcb, IN BOOLEAN Translate, // Translate Logical to Physical IN uint32 Lba, IN uint32 BCount, IN BOOLEAN Direct, // Disable access to non-cached data IN int8* Buffer, OUT PSIZE_T WrittenBytes ){ OSSTATUS status;
#ifdef _BROWSE_UDF_ if(!Vcb->Modified || (Vcb->IntegrityType == INTEGRITY_TYPE_CLOSE)) { UDFSetModified(Vcb); if(Vcb->LVid && !Direct) { status = UDFUpdateLogicalVolInt(Vcb,FALSE); } }
if(Vcb->CDR_Mode) { if(Vcb->LastLBA < Lba+BCount-1) Vcb->LastLBA = Lba+BCount-1; }#endif //_BROWSE_UDF_
if(Vcb->FastCache.WriteProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) { status = WCacheWriteBlocks__(&(Vcb->FastCache), Vcb, Buffer, Lba, BCount, WrittenBytes, Direct); ASSERT(OS_SUCCESS(status));#ifdef _BROWSE_UDF_ UDFClrZeroBits(Vcb->ZSBM_Bitmap, Lba, BCount);#endif //_BROWSE_UDF_ return status; }/* void* buffer; OSSTATUS status; SIZE_T _ReadBytes; (*WrittenBytes) = 0; buffer = DbgAllocatePool(NonPagedPool, Vcb->WriteBlockSize); if(!buffer) return STATUS_INSUFFICIENT_RESOURCES; status = UDFTRead(Vcb, Buffer, BCount<<Vcb->BlockSizeBits, (Lba&~(Vcb->WriteBlockSize-1), _WrittenBytes);*/#ifdef UDF_DBG status = UDFTWrite(Vcb, Buffer, BCount<<Vcb->BlockSizeBits, Lba, WrittenBytes); ASSERT(OS_SUCCESS(status)); return status;#else // UDF_DBG return UDFTWrite(Vcb, Buffer, BCount<<Vcb->BlockSizeBits, Lba, WrittenBytes);#endif // UDF_DBG} // end UDFWriteSectors()
OSSTATUSUDFWriteInSector( IN PVCB Vcb, IN BOOLEAN Translate, // Translate Logical to Physical IN uint32 Lba, IN uint32 i, // offset in sector IN uint32 l, // transfer length IN BOOLEAN Direct, // Disable access to non-cached data OUT int8* Buffer, OUT PSIZE_T WrittenBytes ){ int8* tmp_buff; OSSTATUS status;#ifdef _BROWSE_UDF_ SIZE_T _WrittenBytes; SIZE_T ReadBytes;
if(!Vcb->Modified) { UDFSetModified(Vcb); if(Vcb->LVid) status = UDFUpdateLogicalVolInt(Vcb,FALSE); }
if(Vcb->CDR_Mode) { if(Vcb->LastLBA < Lba) Vcb->LastLBA = Lba; }#endif //_BROWSE_UDF_
(*WrittenBytes) = 0;#ifdef _BROWSE_UDF_ if(WCacheIsInitialized__(&(Vcb->FastCache)) && (KeGetCurrentIrql() < DISPATCH_LEVEL)) {#endif //_BROWSE_UDF_ status = WCacheDirect__(&(Vcb->FastCache), Vcb, Lba, TRUE, &tmp_buff, Direct); if(OS_SUCCESS(status)) {#ifdef _BROWSE_UDF_ UDFClrZeroBit(Vcb->ZSBM_Bitmap, Lba);#endif //_BROWSE_UDF_ (*WrittenBytes) += l; RtlCopyMemory(tmp_buff+i, Buffer, l); } if(!Direct) WCacheEODirect__(&(Vcb->FastCache), Vcb);#ifdef _BROWSE_UDF_ } else { // If Direct = TRUE we should never get here, but... if(Direct) { BrutePoint(); return STATUS_INVALID_PARAMETER; } tmp_buff = (int8*)MyAllocatePool__(NonPagedPool, Vcb->BlockSize); if(!tmp_buff) { BrutePoint(); return STATUS_INSUFFICIENT_RESOURCES; } // read packet status = UDFReadSectors(Vcb, Translate, Lba, 1, FALSE, tmp_buff, &ReadBytes); if(!OS_SUCCESS(status)) goto EO_WrSctD; // modify packet RtlCopyMemory(tmp_buff+i, Buffer, l); // write modified packet status = UDFWriteSectors(Vcb, Translate, Lba, 1, FALSE, tmp_buff, &_WrittenBytes); if(OS_SUCCESS(status)) (*WrittenBytes) += l;EO_WrSctD: MyFreePool__(tmp_buff); } ASSERT(OS_SUCCESS(status)); if(!OS_SUCCESS(status)) { UDFPrint(("UDFWriteInSector() for LBA %x failed\n", Lba)); }#endif //_BROWSE_UDF_ return status;} // end UDFWriteInSector()
/* This routine writes data at unaligned offset & length */OSSTATUSUDFWriteData( IN PVCB Vcb, IN BOOLEAN Translate, // Translate Logical to Physical IN int64 Offset, IN SIZE_T Length, IN BOOLEAN Direct, // setting this flag delays flushing of given // data to indefinite term IN int8* Buffer, OUT PSIZE_T WrittenBytes ){ uint32 i, l, Lba, BS=Vcb->BlockSize; uint32 BSh=Vcb->BlockSizeBits; OSSTATUS status; SIZE_T _WrittenBytes; Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
(*WrittenBytes) = 0; if(!Length) return STATUS_SUCCESS; if(Vcb->VCBFlags & UDF_VCB_FLAGS_DEAD) return STATUS_NO_SUCH_DEVICE; // write tail of the 1st sector if Offset is not sector_size-aligned Lba = (uint32)(Offset >> BSh); if((i = ((uint32)Offset & (BS-1)))) { l = (BS - i) < Length ? (BS - i) : Length; status = UDFWriteInSector(Vcb, Translate, Lba, i, l, Direct, Buffer, WrittenBytes); if(!OS_SUCCESS(status)) return status; if(!(Length = Length - l)) return STATUS_SUCCESS; Lba ++; Buffer += l; } // write sector_size-aligned part i = Length >> BSh; if(i) { status = UDFWriteSectors(Vcb, Translate, Lba, i, Direct, Buffer, &_WrittenBytes); (*WrittenBytes) += _WrittenBytes; if(!OS_SUCCESS(status)) return status; l = i<<BSh;#ifdef _BROWSE_UDF_ UDFClrZeroBits(Vcb->ZSBM_Bitmap, Lba, i);#endif //_BROWSE_UDF_ if(!(Length = Length - l)) return STATUS_SUCCESS; Lba += i; Buffer += l; } status = UDFWriteInSector(Vcb, Translate, Lba, 0, Length, Direct, Buffer, &_WrittenBytes); (*WrittenBytes) += _WrittenBytes;#ifdef _BROWSE_UDF_ UDFClrZeroBit(Vcb->ZSBM_Bitmap, Lba);#endif //_BROWSE_UDF_
return status;} // end UDFWriteData()
#endif //UDF_READ_ONLY_BUILD
OSSTATUSUDFResetDeviceDriver( IN PVCB Vcb, IN PDEVICE_OBJECT TargetDeviceObject, IN BOOLEAN Unlock ){ PCDRW_RESET_DRIVER_USER_IN tmp = (PCDRW_RESET_DRIVER_USER_IN) MyAllocatePool__(NonPagedPool, sizeof(CDRW_RESET_DRIVER_USER_IN)); OSSTATUS RC; if(!tmp) return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory(tmp, sizeof(CDRW_RESET_DRIVER_USER_IN)); tmp->UnlockTray = (Unlock ? 1 : 0); tmp->MagicWord = 0x3a6 | (Unlock ? 1 : 0); RC = UDFPhSendIOCTL(IOCTL_CDRW_RESET_DRIVER_EX, TargetDeviceObject, tmp, sizeof(CDRW_RESET_DRIVER_USER_IN), NULL, 0, TRUE,NULL); if(Vcb) { Vcb->LastReadTrack = 0; Vcb->LastModifiedTrack = 0; Vcb->OPCDone = FALSE; if((Vcb->VCBFlags & UDF_VCB_FLAGS_USE_CAV) && Vcb->TargetDeviceObject) { // limit both read & write speed to last write speed for CAV mode // some drives damage data when speed is adjusted during recording process // even in packet mode UDFSetSpeeds(Vcb); } UDFSetCaching(Vcb); }
MyFreePool__(tmp); return RC;} // end UDFResetDeviceDriver()
OSSTATUSUDFSetSpeeds( IN PVCB Vcb ){ OSSTATUS RC;
RtlZeroMemory(&(Vcb->SpeedBuf), sizeof(SET_CD_SPEED_EX_USER_IN)); if(Vcb->VCBFlags & UDF_VCB_FLAGS_USE_CAV) { Vcb->SpeedBuf.RotCtrl = CdSpeed_RotCtrl_CAV; Vcb->CurSpeed = Vcb->SpeedBuf.ReadSpeed = Vcb->SpeedBuf.WriteSpeed = Vcb->MaxWriteSpeed; } else { Vcb->SpeedBuf.ReadSpeed = Vcb->CurSpeed; Vcb->SpeedBuf.WriteSpeed = Vcb->MaxWriteSpeed; } UDFPrint((" UDFSetSpeeds: set speed to %s %dX/%dX\n", (Vcb->VCBFlags & UDF_VCB_FLAGS_USE_CAV) ? "CAV" : "CLV", Vcb->SpeedBuf.ReadSpeed / 176, Vcb->SpeedBuf.WriteSpeed / 176)); RC = UDFPhSendIOCTL(IOCTL_CDRW_SET_SPEED, Vcb->TargetDeviceObject, &(Vcb->SpeedBuf),sizeof(SET_CD_SPEED_EX_USER_IN), NULL,0,TRUE,NULL); UDFPrint(("UDFSetSpeeds: %x\n", RC)); return RC;} // end UDFSetSpeeds()
NTSTATUSUDFSetCaching( IN PVCB Vcb ){#pragma pack(push,1) struct { MODE_PARAMETER_HEADER Header; MODE_CACHING_PAGE Data; CHAR Padding [16]; } CachingPage;
struct { MODE_PARAMETER_HEADER Header; MODE_READ_WRITE_RECOVERY_PAGE Data; CHAR Padding [16]; } RecoveryPage;#ifdef _MSC_VER#pragma pack(pop,1)#else#pragma pack(pop)#endif
MODE_SENSE_USER_IN ModeSenseCtl; OSSTATUS RC;
UDFPrint(("UDFSetCaching:\n"));
ModeSenseCtl.PageCode.Byte = MODE_PAGE_ERROR_RECOVERY; RC = UDFPhSendIOCTL(IOCTL_CDRW_MODE_SENSE, Vcb->TargetDeviceObject, &ModeSenseCtl,sizeof(ModeSenseCtl), (PVOID)&RecoveryPage,sizeof(RecoveryPage), FALSE, NULL); if(OS_SUCCESS(RC)) { UDFPrint((" Error recovery page:\n" "PageCode %d\n" "PageLength %d\n"
"DCRBit %d\n" "DTEBit %d\n" "PERBit %d\n" "EERBit %d\n" "RCBit %d\n" "TBBit %d\n" "ARRE %d\n" "AWRE %d\n"
"ReadRetryCount %d\n" "CorrectionSpan %d\n" "HeadOffsetCount %d\n" "DataStrobOffsetCount %d\n"
"ErrorRecoveryParam2.Fields.EMCDR %d\n"
"WriteRetryCount %d\n",
RecoveryPage.Data.PageCode, RecoveryPage.Data.PageLength,
RecoveryPage.Data.ErrorRecoveryParam.Fields.DCRBit, RecoveryPage.Data.ErrorRecoveryParam.Fields.DTEBit, RecoveryPage.Data.ErrorRecoveryParam.Fields.PERBit, RecoveryPage.Data.ErrorRecoveryParam.Fields.EERBit, RecoveryPage.Data.ErrorRecoveryParam.Fields.RCBit, RecoveryPage.Data.ErrorRecoveryParam.Fields.TBBit, RecoveryPage.Data.ErrorRecoveryParam.Fields.ARRE, RecoveryPage.Data.ErrorRecoveryParam.Fields.AWRE,
RecoveryPage.Data.ReadRetryCount, RecoveryPage.Data.CorrectionSpan, RecoveryPage.Data.HeadOffsetCount, RecoveryPage.Data.DataStrobOffsetCount,
RecoveryPage.Data.ErrorRecoveryParam2.Fields.EMCDR,
RecoveryPage.Data.WriteRetryCount
)); }
ModeSenseCtl.PageCode.Byte = MODE_PAGE_CACHING; RC = UDFPhSendIOCTL(IOCTL_CDRW_MODE_SENSE, Vcb->TargetDeviceObject, &ModeSenseCtl,sizeof(ModeSenseCtl), (PVOID)&CachingPage,sizeof(CachingPage), FALSE, NULL); if(!OS_SUCCESS(RC)) { return RC; }
UDFPrint((" Caching page:\n" "PageCode %d\n" "PageLength %d\n" "ReadDisableCache %d\n" "MultiplicationFactor %d\n" "WriteCacheEnable %d\n" "WriteRetensionPriority %d\n" "ReadRetensionPriority %d\n",
CachingPage.Data.PageCode, CachingPage.Data.PageLength, CachingPage.Data.ReadDisableCache, CachingPage.Data.MultiplicationFactor, CachingPage.Data.WriteCacheEnable, CachingPage.Data.WriteRetensionPriority, CachingPage.Data.ReadRetensionPriority ));
RtlZeroMemory(&CachingPage.Header, sizeof(CachingPage.Header)); CachingPage.Data.PageCode = MODE_PAGE_CACHING; CachingPage.Data.PageSavable = 0; if( CachingPage.Data.ReadDisableCache || !CachingPage.Data.WriteCacheEnable) { CachingPage.Data.ReadDisableCache = 0; CachingPage.Data.WriteCacheEnable = 1; RC = UDFPhSendIOCTL(IOCTL_CDRW_MODE_SELECT, Vcb->TargetDeviceObject, (PVOID)&CachingPage,sizeof(CachingPage.Header) + 2 + CachingPage.Data.PageLength, NULL,0, FALSE, NULL); } else { RC = STATUS_SUCCESS; } UDFPrint(("UDFSetCaching: %x\n", RC)); return RC;} // end UDFSetCaching()