ata.c 93 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. ata.c
  9. Abstract:
  10. This module implements the AT Attachment (ATA) driver.
  11. Author:
  12. Evan Green 4-Jun-2014
  13. Environment:
  14. Kernel
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <minoca/kernel/driver.h>
  20. #include <minoca/intrface/disk.h>
  21. #include <minoca/intrface/pci.h>
  22. #include <minoca/storage/ata.h>
  23. #include "ata.h"
  24. //
  25. // --------------------------------------------------------------------- Macros
  26. //
  27. //
  28. // This macro returns the correct time counter function depending on whether
  29. // the operation is occurring in critical mode or not.
  30. //
  31. #define ATA_GET_TIME_FUNCTION(_CriticalMode) \
  32. ((_CriticalMode) ? HlQueryTimeCounter : KeGetRecentTimeCounter)
  33. //
  34. // ---------------------------------------------------------------- Definitions
  35. //
  36. //
  37. // ------------------------------------------------------ Data Type Definitions
  38. //
  39. typedef
  40. ULONGLONG
  41. (*PATA_QUERY_TIME_COUNTER) (
  42. VOID
  43. );
  44. /*++
  45. Routine Description:
  46. This routine returns snap of the time counter.
  47. Arguments:
  48. None.
  49. Return Value:
  50. Returns a snap of the time counter.
  51. --*/
  52. //
  53. // ----------------------------------------------- Internal Function Prototypes
  54. //
  55. VOID
  56. AtapServiceInterruptForChannel (
  57. PATA_CHANNEL Channel,
  58. ULONG PendingBits
  59. );
  60. KSTATUS
  61. AtaAddDevice (
  62. PVOID Driver,
  63. PCSTR DeviceId,
  64. PCSTR ClassId,
  65. PCSTR CompatibleIds,
  66. PVOID DeviceToken
  67. );
  68. VOID
  69. AtaDispatchStateChange (
  70. PIRP Irp,
  71. PVOID DeviceContext,
  72. PVOID IrpContext
  73. );
  74. VOID
  75. AtaDispatchOpen (
  76. PIRP Irp,
  77. PVOID DeviceContext,
  78. PVOID IrpContext
  79. );
  80. VOID
  81. AtaDispatchClose (
  82. PIRP Irp,
  83. PVOID DeviceContext,
  84. PVOID IrpContext
  85. );
  86. VOID
  87. AtaDispatchIo (
  88. PIRP Irp,
  89. PVOID DeviceContext,
  90. PVOID IrpContext
  91. );
  92. VOID
  93. AtaDispatchSystemControl (
  94. PIRP Irp,
  95. PVOID DeviceContext,
  96. PVOID IrpContext
  97. );
  98. INTERRUPT_STATUS
  99. AtaInterruptService (
  100. PVOID Context
  101. );
  102. INTERRUPT_STATUS
  103. AtaInterruptServiceDpc (
  104. PVOID Context
  105. );
  106. VOID
  107. AtapDispatchControllerStateChange (
  108. PIRP Irp,
  109. PATA_CONTROLLER Controller
  110. );
  111. VOID
  112. AtapDispatchChildStateChange (
  113. PIRP Irp,
  114. PATA_CHILD Child
  115. );
  116. VOID
  117. AtapDispatchChildSystemControl (
  118. PIRP Irp,
  119. PATA_CHILD Device
  120. );
  121. KSTATUS
  122. AtapProcessResourceRequirements (
  123. PIRP Irp,
  124. PATA_CONTROLLER Controller
  125. );
  126. KSTATUS
  127. AtapStartController (
  128. PIRP Irp,
  129. PATA_CONTROLLER Controller
  130. );
  131. KSTATUS
  132. AtapResetController (
  133. PATA_CONTROLLER Controller
  134. );
  135. VOID
  136. AtapEnumerateDrives (
  137. PIRP Irp,
  138. PATA_CONTROLLER Controller
  139. );
  140. KSTATUS
  141. AtapIdentifyDevice (
  142. PATA_CHILD Device
  143. );
  144. KSTATUS
  145. AtapPerformDmaIo (
  146. PIRP Irp,
  147. PATA_CHILD Device,
  148. BOOL HaveDpcLock
  149. );
  150. KSTATUS
  151. AtapPerformPolledIo (
  152. PIRP_READ_WRITE Irp,
  153. PATA_CHILD Device,
  154. BOOL Write,
  155. BOOL CriticalMode
  156. );
  157. KSTATUS
  158. AtapSynchronizeDevice (
  159. PATA_CHILD Device
  160. );
  161. KSTATUS
  162. AtapBlockRead (
  163. PVOID DiskToken,
  164. PIO_BUFFER IoBuffer,
  165. ULONGLONG BlockAddress,
  166. UINTN BlockCount,
  167. PUINTN BlocksCompleted
  168. );
  169. KSTATUS
  170. AtapBlockWrite (
  171. PVOID DiskToken,
  172. PIO_BUFFER IoBuffer,
  173. ULONGLONG BlockAddress,
  174. UINTN BlockCount,
  175. PUINTN BlocksCompleted
  176. );
  177. KSTATUS
  178. AtapReadWriteSectorsPio (
  179. PATA_CHILD AtaDevice,
  180. ULONGLONG BlockAddress,
  181. UINTN SectorCount,
  182. PVOID Buffer,
  183. BOOL Write,
  184. BOOL CriticalMode
  185. );
  186. KSTATUS
  187. AtapPioCommand (
  188. PATA_CHILD Device,
  189. ATA_COMMAND Command,
  190. BOOL Lba48,
  191. BOOL Write,
  192. ULONG Features,
  193. ULONGLONG Lba,
  194. PVOID Buffer,
  195. ULONG SectorCount,
  196. ULONG MultiCount,
  197. BOOL CriticalMode
  198. );
  199. KSTATUS
  200. AtapExecuteCacheFlush (
  201. PATA_CHILD Child,
  202. BOOL CriticalMode
  203. );
  204. KSTATUS
  205. AtapSelectDevice (
  206. PATA_CHILD Device,
  207. BOOL CriticalMode
  208. );
  209. VOID
  210. AtapSetupCommand (
  211. PATA_CHILD Device,
  212. BOOL Lba48,
  213. ULONG FeaturesRegister,
  214. ULONG SectorCountRegister,
  215. ULONGLONG Lba,
  216. ULONG DeviceControl
  217. );
  218. VOID
  219. AtapStall (
  220. PATA_CHANNEL Channel
  221. );
  222. UCHAR
  223. AtapReadRegister (
  224. PATA_CHANNEL Channel,
  225. ATA_REGISTER Register
  226. );
  227. VOID
  228. AtapWriteRegister (
  229. PATA_CHANNEL Channel,
  230. ATA_REGISTER Register,
  231. UCHAR Value
  232. );
  233. VOID
  234. AtapProcessPciConfigInterfaceChangeNotification (
  235. PVOID Context,
  236. PDEVICE Device,
  237. PVOID InterfaceBuffer,
  238. ULONG InterfaceBufferSize,
  239. BOOL Arrival
  240. );
  241. //
  242. // -------------------------------------------------------------------- Globals
  243. //
  244. PDRIVER AtaDriver = NULL;
  245. UUID AtaPciConfigurationInterfaceUuid = UUID_PCI_CONFIG_ACCESS;
  246. UUID AtaDiskInterfaceUuid = UUID_DISK_INTERFACE;
  247. DISK_INTERFACE AtaDiskInterfaceTemplate = {
  248. DISK_INTERFACE_VERSION,
  249. NULL,
  250. ATA_SECTOR_SIZE,
  251. 0,
  252. NULL,
  253. NULL,
  254. AtapBlockRead,
  255. AtapBlockWrite
  256. };
  257. //
  258. // ------------------------------------------------------------------ Functions
  259. //
  260. __USED
  261. KSTATUS
  262. DriverEntry (
  263. PDRIVER Driver
  264. )
  265. /*++
  266. Routine Description:
  267. This routine is the entry point for the ATA driver. It registers its other
  268. dispatch functions, and performs driver-wide initialization.
  269. Arguments:
  270. Driver - Supplies a pointer to the driver object.
  271. Return Value:
  272. STATUS_SUCCESS on success.
  273. Failure code on error.
  274. --*/
  275. {
  276. DRIVER_FUNCTION_TABLE FunctionTable;
  277. KSTATUS Status;
  278. AtaDriver = Driver;
  279. RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
  280. FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
  281. FunctionTable.AddDevice = AtaAddDevice;
  282. FunctionTable.DispatchStateChange = AtaDispatchStateChange;
  283. FunctionTable.DispatchOpen = AtaDispatchOpen;
  284. FunctionTable.DispatchClose = AtaDispatchClose;
  285. FunctionTable.DispatchIo = AtaDispatchIo;
  286. FunctionTable.DispatchSystemControl = AtaDispatchSystemControl;
  287. Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
  288. return Status;
  289. }
  290. KSTATUS
  291. AtaAddDevice (
  292. PVOID Driver,
  293. PCSTR DeviceId,
  294. PCSTR ClassId,
  295. PCSTR CompatibleIds,
  296. PVOID DeviceToken
  297. )
  298. /*++
  299. Routine Description:
  300. This routine is called when a device is detected for which the ATA device
  301. acts as the function driver. The driver will attach itself to the stack.
  302. Arguments:
  303. Driver - Supplies a pointer to the driver being called.
  304. DeviceId - Supplies a pointer to a string with the device ID.
  305. ClassId - Supplies a pointer to a string containing the device's class ID.
  306. CompatibleIds - Supplies a pointer to a string containing device IDs
  307. that would be compatible with this device.
  308. DeviceToken - Supplies an opaque token that the driver can use to identify
  309. the device in the system. This token should be used when attaching to
  310. the stack.
  311. Return Value:
  312. STATUS_SUCCESS on success.
  313. Failure code if the driver was unsuccessful in attaching itself.
  314. --*/
  315. {
  316. PATA_CONTROLLER Controller;
  317. UINTN Index;
  318. ULONG IoBufferFlags;
  319. PVOID Prdt;
  320. PHYSICAL_ADDRESS PrdtPhysical;
  321. KSTATUS Status;
  322. Controller = MmAllocateNonPagedPool(sizeof(ATA_CONTROLLER),
  323. ATA_ALLOCATION_TAG);
  324. if (Controller == NULL) {
  325. Status = STATUS_INSUFFICIENT_RESOURCES;
  326. goto AddDeviceEnd;
  327. }
  328. RtlZeroMemory(Controller, sizeof(ATA_CONTROLLER));
  329. KeInitializeSpinLock(&(Controller->DpcLock));
  330. Controller->Type = AtaControllerContext;
  331. Controller->PrimaryInterruptHandle = INVALID_HANDLE;
  332. Controller->SecondaryInterruptHandle = INVALID_HANDLE;
  333. //
  334. // Allocate a page for the PRDT.
  335. //
  336. IoBufferFlags = IO_BUFFER_FLAG_PHYSICALLY_CONTIGUOUS |
  337. IO_BUFFER_FLAG_MAP_NON_CACHED;
  338. Controller->PrdtIoBuffer = MmAllocateNonPagedIoBuffer(0,
  339. MAX_ULONG,
  340. ATA_PRDT_TOTAL_SIZE,
  341. ATA_PRDT_TOTAL_SIZE,
  342. IoBufferFlags);
  343. if (Controller->PrdtIoBuffer == NULL) {
  344. Status = STATUS_INSUFFICIENT_RESOURCES;
  345. goto AddDeviceEnd;
  346. }
  347. ASSERT(Controller->PrdtIoBuffer->FragmentCount == 1);
  348. Prdt = Controller->PrdtIoBuffer->Fragment[0].VirtualAddress;
  349. PrdtPhysical = Controller->PrdtIoBuffer->Fragment[0].PhysicalAddress;
  350. //
  351. // Initialize the two channels, and then the four child contexts.
  352. //
  353. for (Index = 0; Index < ATA_CABLE_COUNT; Index += 1) {
  354. Controller->Channel[Index].Lock = KeCreateQueuedLock();
  355. if (Controller->Channel[Index].Lock == NULL) {
  356. Status = STATUS_INSUFFICIENT_RESOURCES;
  357. goto AddDeviceEnd;
  358. }
  359. Controller->Channel[Index].SelectedDevice = 0xFF;
  360. Controller->Channel[Index].Prdt = Prdt;
  361. Controller->Channel[Index].PrdtPhysicalAddress = PrdtPhysical;
  362. Prdt += ATA_PRDT_DISK_SIZE;
  363. PrdtPhysical += ATA_PRDT_DISK_SIZE;
  364. }
  365. for (Index = 0; Index < ATA_CHILD_COUNT; Index += 1) {
  366. Controller->ChildContexts[Index].Type = AtaChildContext;
  367. Controller->ChildContexts[Index].Controller = Controller;
  368. Controller->ChildContexts[Index].Channel =
  369. &(Controller->Channel[Index >> 1]);
  370. if ((Index & 0x1) != 0) {
  371. Controller->ChildContexts[Index].Slave = ATA_DRIVE_SELECT_SLAVE;
  372. } else {
  373. Controller->ChildContexts[Index].Slave = ATA_DRIVE_SELECT_MASTER;
  374. }
  375. }
  376. Status = IoAttachDriverToDevice(Driver, DeviceToken, Controller);
  377. if (!KSUCCESS(Status)) {
  378. goto AddDeviceEnd;
  379. }
  380. Status = STATUS_SUCCESS;
  381. AddDeviceEnd:
  382. if (!KSUCCESS(Status)) {
  383. if (Controller != NULL) {
  384. for (Index = 0; Index < ATA_CABLE_COUNT; Index += 1) {
  385. if (Controller->Channel[Index].Lock != NULL) {
  386. KeDestroyQueuedLock(Controller->Channel[Index].Lock);
  387. }
  388. }
  389. if (Controller->PrdtIoBuffer != NULL) {
  390. MmFreeIoBuffer(Controller->PrdtIoBuffer);
  391. }
  392. MmFreeNonPagedPool(Controller);
  393. }
  394. }
  395. return Status;
  396. }
  397. VOID
  398. AtaDispatchStateChange (
  399. PIRP Irp,
  400. PVOID DeviceContext,
  401. PVOID IrpContext
  402. )
  403. /*++
  404. Routine Description:
  405. This routine handles State Change IRPs.
  406. Arguments:
  407. Irp - Supplies a pointer to the I/O request packet.
  408. DeviceContext - Supplies the context pointer supplied by the driver when it
  409. attached itself to the driver stack. Presumably this pointer contains
  410. driver-specific device context.
  411. IrpContext - Supplies the context pointer supplied by the driver when
  412. the IRP was created.
  413. Return Value:
  414. None.
  415. --*/
  416. {
  417. PATA_CONTROLLER Controller;
  418. Controller = DeviceContext;
  419. switch (Controller->Type) {
  420. case AtaControllerContext:
  421. AtapDispatchControllerStateChange(Irp, Controller);
  422. break;
  423. case AtaChildContext:
  424. AtapDispatchChildStateChange(Irp, (PATA_CHILD)Controller);
  425. break;
  426. default:
  427. ASSERT(FALSE);
  428. IoCompleteIrp(AtaDriver, Irp, STATUS_INVALID_CONFIGURATION);
  429. break;
  430. }
  431. return;
  432. }
  433. VOID
  434. AtaDispatchOpen (
  435. PIRP Irp,
  436. PVOID DeviceContext,
  437. PVOID IrpContext
  438. )
  439. /*++
  440. Routine Description:
  441. This routine handles Open IRPs.
  442. Arguments:
  443. Irp - Supplies a pointer to the I/O request packet.
  444. DeviceContext - Supplies the context pointer supplied by the driver when it
  445. attached itself to the driver stack. Presumably this pointer contains
  446. driver-specific device context.
  447. IrpContext - Supplies the context pointer supplied by the driver when
  448. the IRP was created.
  449. Return Value:
  450. None.
  451. --*/
  452. {
  453. PATA_CHILD Disk;
  454. //
  455. // Only the disk can be opened or closed.
  456. //
  457. Disk = (PATA_CHILD)DeviceContext;
  458. if (Disk->Type != AtaChildContext) {
  459. return;
  460. }
  461. Irp->U.Open.DeviceContext = Disk;
  462. IoCompleteIrp(AtaDriver, Irp, STATUS_SUCCESS);
  463. return;
  464. }
  465. VOID
  466. AtaDispatchClose (
  467. PIRP Irp,
  468. PVOID DeviceContext,
  469. PVOID IrpContext
  470. )
  471. /*++
  472. Routine Description:
  473. This routine handles Close IRPs.
  474. Arguments:
  475. Irp - Supplies a pointer to the I/O request packet.
  476. DeviceContext - Supplies the context pointer supplied by the driver when it
  477. attached itself to the driver stack. Presumably this pointer contains
  478. driver-specific device context.
  479. IrpContext - Supplies the context pointer supplied by the driver when
  480. the IRP was created.
  481. Return Value:
  482. None.
  483. --*/
  484. {
  485. PATA_CHILD Disk;
  486. //
  487. // Only the disk can be opened or closed.
  488. //
  489. Disk = (PATA_CHILD)DeviceContext;
  490. if (Disk->Type != AtaChildContext) {
  491. return;
  492. }
  493. Irp->U.Open.DeviceContext = Disk;
  494. IoCompleteIrp(AtaDriver, Irp, STATUS_SUCCESS);
  495. return;
  496. }
  497. VOID
  498. AtaDispatchIo (
  499. PIRP Irp,
  500. PVOID DeviceContext,
  501. PVOID IrpContext
  502. )
  503. /*++
  504. Routine Description:
  505. This routine handles I/O IRPs.
  506. Arguments:
  507. Irp - Supplies a pointer to the I/O request packet.
  508. DeviceContext - Supplies the context pointer supplied by the driver when it
  509. attached itself to the driver stack. Presumably this pointer contains
  510. driver-specific device context.
  511. IrpContext - Supplies the context pointer supplied by the driver when
  512. the IRP was created.
  513. Return Value:
  514. None.
  515. --*/
  516. {
  517. BOOL CompleteIrp;
  518. PATA_CHILD Device;
  519. ULONG IrpReadWriteFlags;
  520. BOOL PmReferenceAdded;
  521. KSTATUS Status;
  522. BOOL Write;
  523. ASSERT(KeGetRunLevel() == RunLevelLow);
  524. Device = (PATA_CHILD)Irp->U.ReadWrite.DeviceContext;
  525. if (Device->Type != AtaChildContext) {
  526. return;
  527. }
  528. CompleteIrp = TRUE;
  529. Write = FALSE;
  530. if (Irp->MinorCode == IrpMinorIoWrite) {
  531. Write = TRUE;
  532. }
  533. //
  534. // If this IRP is on the way down, always add a power management reference.
  535. //
  536. PmReferenceAdded = FALSE;
  537. if (Irp->Direction == IrpDown) {
  538. Status = PmDeviceAddReference(Device->OsDevice);
  539. if (!KSUCCESS(Status)) {
  540. goto DispatchIoEnd;
  541. }
  542. PmReferenceAdded = TRUE;
  543. }
  544. //
  545. // Polled I/O is shared by a few code paths and prepares the IRP for I/O
  546. // further down the stack. It should also only be hit in the down direction
  547. // path as it always completes the IRP.
  548. //
  549. if (Device->DmaSupported == FALSE) {
  550. ASSERT(Irp->Direction == IrpDown);
  551. Status = AtapPerformPolledIo(&(Irp->U.ReadWrite), Device, Write, FALSE);
  552. goto DispatchIoEnd;
  553. }
  554. //
  555. // Set the IRP read/write flags for the preparation and completion steps.
  556. //
  557. IrpReadWriteFlags = IRP_READ_WRITE_FLAG_DMA;
  558. if (Write != FALSE) {
  559. IrpReadWriteFlags |= IRP_READ_WRITE_FLAG_WRITE;
  560. }
  561. //
  562. // If the IRP is on the way up, then clean up after the DMA as this IRP is
  563. // still sitting in the channel. An IRP going up is already complete.
  564. //
  565. if (Irp->Direction == IrpUp) {
  566. CompleteIrp = FALSE;
  567. ASSERT(Irp == Device->Channel->Irp);
  568. ASSERT(Device == Device->Channel->OwningChild);
  569. ASSERT(KeIsQueuedLockHeld(Device->Channel->Lock) != FALSE);
  570. Device->Channel->OwningChild = NULL;
  571. Device->Channel->Irp = NULL;
  572. KeReleaseQueuedLock(Device->Channel->Lock);
  573. PmDeviceReleaseReference(Device->OsDevice);
  574. Status = IoCompleteReadWriteIrp(&(Irp->U.ReadWrite), IrpReadWriteFlags);
  575. if (!KSUCCESS(Status)) {
  576. IoUpdateIrpStatus(Irp, Status);
  577. }
  578. //
  579. // Start the DMA on the way down.
  580. //
  581. } else {
  582. Irp->U.ReadWrite.NewIoOffset = Irp->U.ReadWrite.IoOffset;
  583. //
  584. // Before acquiring the channel's lock and starting the DMA, prepare
  585. // the I/O context for ATA (i.e. it must use physical addresses that
  586. // are less than 4GB and be sector size aligned).
  587. //
  588. Status = IoPrepareReadWriteIrp(&(Irp->U.ReadWrite),
  589. ATA_SECTOR_SIZE,
  590. 0,
  591. MAX_ULONG,
  592. IrpReadWriteFlags);
  593. if (!KSUCCESS(Status)) {
  594. goto DispatchIoEnd;
  595. }
  596. //
  597. // Fire off the DMA. If this succeeds, it will have pended the IRP.
  598. // Return with the lock held.
  599. //
  600. KeAcquireQueuedLock(Device->Channel->Lock);
  601. Device->Channel->Irp = Irp;
  602. Device->Channel->OwningChild = Device;
  603. CompleteIrp = FALSE;
  604. Status = AtapPerformDmaIo(Irp, Device, FALSE);
  605. if (!KSUCCESS(Status)) {
  606. Device->Channel->OwningChild = NULL;
  607. Device->Channel->Irp = NULL;
  608. KeReleaseQueuedLock(Device->Channel->Lock);
  609. IoCompleteReadWriteIrp(&(Irp->U.ReadWrite), IrpReadWriteFlags);
  610. CompleteIrp = TRUE;
  611. }
  612. }
  613. DispatchIoEnd:
  614. if (CompleteIrp != FALSE) {
  615. if (PmReferenceAdded != FALSE) {
  616. PmDeviceReleaseReference(Device->OsDevice);
  617. }
  618. IoCompleteIrp(AtaDriver, Irp, Status);
  619. }
  620. return;
  621. }
  622. VOID
  623. AtaDispatchSystemControl (
  624. PIRP Irp,
  625. PVOID DeviceContext,
  626. PVOID IrpContext
  627. )
  628. /*++
  629. Routine Description:
  630. This routine handles System Control IRPs.
  631. Arguments:
  632. Irp - Supplies a pointer to the I/O request packet.
  633. DeviceContext - Supplies the context pointer supplied by the driver when it
  634. attached itself to the driver stack. Presumably this pointer contains
  635. driver-specific device context.
  636. IrpContext - Supplies the context pointer supplied by the driver when
  637. the IRP was created.
  638. Return Value:
  639. None.
  640. --*/
  641. {
  642. PATA_CHILD Child;
  643. ASSERT(Irp->MajorCode == IrpMajorSystemControl);
  644. Child = (PATA_CHILD)DeviceContext;
  645. if (Child->Type == AtaChildContext) {
  646. AtapDispatchChildSystemControl(Irp, Child);
  647. }
  648. return;
  649. }
  650. INTERRUPT_STATUS
  651. AtaInterruptService (
  652. PVOID Context
  653. )
  654. /*++
  655. Routine Description:
  656. This routine implements the ATA interrupt service routine.
  657. Arguments:
  658. Context - Supplies the context pointer given to the system when the
  659. interrupt was connected. In this case, this points to the ATA
  660. controller.
  661. Return Value:
  662. Interrupt status.
  663. --*/
  664. {
  665. ULONG BusMasterStatus;
  666. PATA_CONTROLLER Controller;
  667. INTERRUPT_STATUS InterruptStatus;
  668. InterruptStatus = InterruptStatusNotClaimed;
  669. Controller = (PATA_CONTROLLER)Context;
  670. //
  671. // Check the primary channel's bus master status.
  672. //
  673. BusMasterStatus = AtapReadRegister(&(Controller->Channel[0]),
  674. AtaRegisterBusMasterStatus);
  675. BusMasterStatus &= IDE_STATUS_INTERRUPT | IDE_STATUS_ERROR;
  676. if (BusMasterStatus != 0) {
  677. AtapWriteRegister(&(Controller->Channel[0]),
  678. AtaRegisterBusMasterStatus,
  679. BusMasterStatus);
  680. AtapWriteRegister(&(Controller->Channel[0]),
  681. AtaRegisterBusMasterCommand,
  682. 0);
  683. //
  684. // Try the secondary one.
  685. //
  686. } else {
  687. BusMasterStatus = AtapReadRegister(&(Controller->Channel[1]),
  688. AtaRegisterBusMasterStatus);
  689. BusMasterStatus &= IDE_STATUS_INTERRUPT | IDE_STATUS_ERROR;
  690. if (BusMasterStatus != 0) {
  691. AtapWriteRegister(&(Controller->Channel[1]),
  692. AtaRegisterBusMasterStatus,
  693. BusMasterStatus);
  694. AtapWriteRegister(&(Controller->Channel[1]),
  695. AtaRegisterBusMasterCommand,
  696. 0);
  697. BusMasterStatus <<= BITS_PER_BYTE;
  698. }
  699. }
  700. if (BusMasterStatus != 0) {
  701. RtlAtomicOr32(&(Controller->PendingStatusBits), BusMasterStatus);
  702. InterruptStatus = InterruptStatusClaimed;
  703. }
  704. return InterruptStatus;
  705. }
  706. INTERRUPT_STATUS
  707. AtaInterruptServiceDpc (
  708. PVOID Context
  709. )
  710. /*++
  711. Routine Description:
  712. This routine implements the ATA dispatch-level interrupt service routine.
  713. Arguments:
  714. Context - Supplies the context pointer given to the system when the
  715. interrupt was connected. In this case, this points to the ATA
  716. controller.
  717. Return Value:
  718. Interrupt status.
  719. --*/
  720. {
  721. UCHAR BusMasterMask;
  722. PATA_CONTROLLER Device;
  723. ULONG PendingBits;
  724. Device = (PATA_CONTROLLER)Context;
  725. //
  726. // Clear out the pending bits.
  727. //
  728. PendingBits = RtlAtomicExchange32(&(Device->PendingStatusBits), 0);
  729. if (PendingBits == 0) {
  730. return InterruptStatusNotClaimed;
  731. }
  732. KeAcquireSpinLock(&(Device->DpcLock));
  733. //
  734. // Handle the primary controller.
  735. //
  736. BusMasterMask = IDE_STATUS_ERROR | IDE_STATUS_INTERRUPT;
  737. if ((PendingBits & BusMasterMask) != 0) {
  738. AtapServiceInterruptForChannel(&(Device->Channel[0]),
  739. PendingBits & BusMasterMask);
  740. }
  741. //
  742. // Handle the secondary controller.
  743. //
  744. PendingBits >>= 8;
  745. if ((PendingBits & BusMasterMask) != 0) {
  746. AtapServiceInterruptForChannel(&(Device->Channel[1]),
  747. PendingBits & BusMasterMask);
  748. }
  749. KeReleaseSpinLock(&(Device->DpcLock));
  750. return InterruptStatusClaimed;
  751. }
  752. //
  753. // --------------------------------------------------------- Internal Functions
  754. //
  755. VOID
  756. AtapServiceInterruptForChannel (
  757. PATA_CHANNEL Channel,
  758. ULONG PendingBits
  759. )
  760. /*++
  761. Routine Description:
  762. This routine services an interrupt for a given ATA channel.
  763. Arguments:
  764. Channel - Supplies a pointer to the channel.
  765. PendingBits - Supplies the pending bitmask.
  766. Return Value:
  767. None.
  768. --*/
  769. {
  770. BOOL CompleteIrp;
  771. UINTN IoSize;
  772. PIRP Irp;
  773. KSTATUS Status;
  774. UCHAR StatusRegister;
  775. Irp = Channel->Irp;
  776. if ((Irp != NULL) && (PendingBits != 0) && (Channel->IoSize != 0)) {
  777. IoSize = Channel->IoSize;
  778. Channel->IoSize = 0;
  779. Status = STATUS_SUCCESS;
  780. CompleteIrp = FALSE;
  781. StatusRegister = AtapReadRegister(Channel, AtaRegisterStatus);
  782. if (((PendingBits & IDE_STATUS_ERROR) != 0) ||
  783. ((StatusRegister & ATA_STATUS_ERROR_MASK) != 0)) {
  784. RtlDebugPrint("ATA: I/O Error: Status 0x%x, BMStatus 0x%x.\n",
  785. StatusRegister,
  786. PendingBits);
  787. Status = STATUS_DEVICE_IO_ERROR;
  788. CompleteIrp = FALSE;
  789. } else if ((PendingBits & IDE_STATUS_INTERRUPT) != 0) {
  790. CompleteIrp = TRUE;
  791. ASSERT(Irp->MajorCode == IrpMajorIo);
  792. Irp->U.ReadWrite.IoBytesCompleted += IoSize;
  793. Irp->U.ReadWrite.NewIoOffset += IoSize;
  794. ASSERT(Irp->U.ReadWrite.IoBytesCompleted <=
  795. Irp->U.ReadWrite.IoSizeInBytes);
  796. if (Irp->U.ReadWrite.IoBytesCompleted !=
  797. Irp->U.ReadWrite.IoSizeInBytes) {
  798. Status = AtapPerformDmaIo(Irp, Channel->OwningChild, TRUE);
  799. if (KSUCCESS(Status)) {
  800. CompleteIrp = FALSE;
  801. }
  802. }
  803. }
  804. if (CompleteIrp != FALSE) {
  805. //
  806. // If this is a synchronized write, then send a cache flush
  807. // command along with it.
  808. //
  809. if ((Status == STATUS_SUCCESS) &&
  810. (Irp->MinorCode == IrpMinorIoWrite) &&
  811. ((Irp->U.ReadWrite.IoFlags & IO_FLAG_DATA_SYNCHRONIZED) != 0)) {
  812. Status = AtapExecuteCacheFlush(Channel->OwningChild, FALSE);
  813. ASSERT(KSUCCESS(Status));
  814. }
  815. //
  816. // If successful, the I/O should be completed fully.
  817. //
  818. ASSERT((!KSUCCESS(Status)) ||
  819. (Irp->U.ReadWrite.IoBytesCompleted ==
  820. Irp->U.ReadWrite.IoSizeInBytes));
  821. //
  822. // Complete the IRP but do not release the lock as the channel is
  823. // cleaned up by this driver after the IRP is reversed to the up
  824. // direction. This allows it to perform said clean up at low level.
  825. //
  826. IoCompleteIrp(AtaDriver, Irp, Status);
  827. }
  828. }
  829. return;
  830. }
  831. VOID
  832. AtapDispatchControllerStateChange (
  833. PIRP Irp,
  834. PATA_CONTROLLER Controller
  835. )
  836. /*++
  837. Routine Description:
  838. This routine handles state change IRPs for an ATA controller.
  839. Arguments:
  840. Irp - Supplies a pointer to the I/O request packet.
  841. Controller - Supplies a pointer to the controller context.
  842. Return Value:
  843. None. The routine completes the IRP if appropriate.
  844. --*/
  845. {
  846. KSTATUS Status;
  847. if (Irp->Direction == IrpUp) {
  848. if (!KSUCCESS(IoGetIrpStatus(Irp))) {
  849. return;
  850. }
  851. switch (Irp->MinorCode) {
  852. case IrpMinorQueryResources:
  853. Status = AtapProcessResourceRequirements(Irp, Controller);
  854. if (!KSUCCESS(Status)) {
  855. IoCompleteIrp(AtaDriver, Irp, Status);
  856. }
  857. break;
  858. case IrpMinorStartDevice:
  859. Status = AtapStartController(Irp, Controller);
  860. if (!KSUCCESS(Status)) {
  861. IoCompleteIrp(AtaDriver, Irp, Status);
  862. }
  863. break;
  864. case IrpMinorQueryChildren:
  865. AtapEnumerateDrives(Irp, Controller);
  866. break;
  867. case IrpMinorIdle:
  868. case IrpMinorSuspend:
  869. case IrpMinorResume:
  870. default:
  871. break;
  872. }
  873. }
  874. return;
  875. }
  876. VOID
  877. AtapDispatchChildStateChange (
  878. PIRP Irp,
  879. PATA_CHILD Child
  880. )
  881. /*++
  882. Routine Description:
  883. This routine handles state change IRPs for an ATA child device.
  884. Arguments:
  885. Irp - Supplies a pointer to the I/O request packet.
  886. Child - Supplies a pointer to the child device.
  887. Return Value:
  888. None. The routine completes the IRP if appropriate.
  889. --*/
  890. {
  891. KSTATUS Status;
  892. if (Irp->Direction == IrpDown) {
  893. switch (Irp->MinorCode) {
  894. case IrpMinorStartDevice:
  895. Child->OsDevice = Irp->Device;
  896. Status = PmInitialize(Irp->Device);
  897. if (!KSUCCESS(Status)) {
  898. IoCompleteIrp(AtaDriver, Irp, Status);
  899. break;
  900. }
  901. //
  902. // Publish the disk interface.
  903. //
  904. RtlCopyMemory(&(Child->DiskInterface),
  905. &AtaDiskInterfaceTemplate,
  906. sizeof(DISK_INTERFACE));
  907. Status = STATUS_SUCCESS;
  908. if (Child->DiskInterface.DiskToken == NULL) {
  909. Child->DiskInterface.DiskToken = Child;
  910. Child->DiskInterface.BlockCount = Child->TotalSectors;
  911. Status = IoCreateInterface(&AtaDiskInterfaceUuid,
  912. Irp->Device,
  913. &(Child->DiskInterface),
  914. sizeof(DISK_INTERFACE));
  915. if (!KSUCCESS(Status)) {
  916. Child->DiskInterface.DiskToken = NULL;
  917. }
  918. }
  919. IoCompleteIrp(AtaDriver, Irp, Status);
  920. break;
  921. case IrpMinorQueryResources:
  922. case IrpMinorQueryChildren:
  923. IoCompleteIrp(AtaDriver, Irp, STATUS_SUCCESS);
  924. break;
  925. case IrpMinorIdle:
  926. IoCompleteIrp(AtaDriver, Irp, STATUS_SUCCESS);
  927. break;
  928. case IrpMinorSuspend:
  929. IoCompleteIrp(AtaDriver, Irp, STATUS_SUCCESS);
  930. break;
  931. case IrpMinorResume:
  932. IoCompleteIrp(AtaDriver, Irp, STATUS_SUCCESS);
  933. break;
  934. default:
  935. break;
  936. }
  937. }
  938. return;
  939. }
  940. VOID
  941. AtapDispatchChildSystemControl (
  942. PIRP Irp,
  943. PATA_CHILD Device
  944. )
  945. /*++
  946. Routine Description:
  947. This routine handles System Control IRPs for an ATA child device.
  948. Arguments:
  949. Irp - Supplies a pointer to the I/O request packet.
  950. Device - Supplies a pointer to the device.
  951. Return Value:
  952. None.
  953. --*/
  954. {
  955. PVOID Context;
  956. PSYSTEM_CONTROL_FILE_OPERATION FileOperation;
  957. PSYSTEM_CONTROL_LOOKUP Lookup;
  958. PFILE_PROPERTIES Properties;
  959. ULONGLONG PropertiesFileSize;
  960. KSTATUS Status;
  961. Context = Irp->U.SystemControl.SystemContext;
  962. switch (Irp->MinorCode) {
  963. case IrpMinorSystemControlLookup:
  964. Lookup = (PSYSTEM_CONTROL_LOOKUP)Context;
  965. Status = STATUS_PATH_NOT_FOUND;
  966. if (Lookup->Root != FALSE) {
  967. //
  968. // Enable opening of the root as a single file.
  969. //
  970. Properties = Lookup->Properties;
  971. Properties->FileId = 0;
  972. Properties->Type = IoObjectBlockDevice;
  973. Properties->HardLinkCount = 1;
  974. Properties->BlockSize = ATA_SECTOR_SIZE;
  975. Properties->BlockCount = Device->TotalSectors;
  976. Properties->Size = Device->TotalSectors * ATA_SECTOR_SIZE;
  977. Status = STATUS_SUCCESS;
  978. }
  979. IoCompleteIrp(AtaDriver, Irp, Status);
  980. break;
  981. //
  982. // Writes to the disk's properties are not allowed. Fail if the data
  983. // has changed.
  984. //
  985. case IrpMinorSystemControlWriteFileProperties:
  986. FileOperation = (PSYSTEM_CONTROL_FILE_OPERATION)Context;
  987. Properties = FileOperation->FileProperties;
  988. PropertiesFileSize = Properties->Size;
  989. if ((Properties->FileId != 0) ||
  990. (Properties->Type != IoObjectBlockDevice) ||
  991. (Properties->HardLinkCount != 1) ||
  992. (Properties->BlockSize != ATA_SECTOR_SIZE) ||
  993. (Properties->BlockCount != Device->TotalSectors) ||
  994. (PropertiesFileSize != (Device->TotalSectors * ATA_SECTOR_SIZE))) {
  995. Status = STATUS_NOT_SUPPORTED;
  996. } else {
  997. Status = STATUS_SUCCESS;
  998. }
  999. IoCompleteIrp(AtaDriver, Irp, Status);
  1000. break;
  1001. //
  1002. // Do not support hard disk device truncation.
  1003. //
  1004. case IrpMinorSystemControlTruncate:
  1005. IoCompleteIrp(AtaDriver, Irp, STATUS_NOT_SUPPORTED);
  1006. break;
  1007. //
  1008. // Gather and return device information.
  1009. //
  1010. case IrpMinorSystemControlDeviceInformation:
  1011. break;
  1012. //
  1013. // Send a cache flush command to the device upon getting a synchronize
  1014. // request.
  1015. //
  1016. case IrpMinorSystemControlSynchronize:
  1017. Status = PmDeviceAddReference(Device->OsDevice);
  1018. if (!KSUCCESS(Status)) {
  1019. IoCompleteIrp(AtaDriver, Irp, Status);
  1020. break;
  1021. }
  1022. Status = AtapSynchronizeDevice(Device);
  1023. PmDeviceReleaseReference(Device->OsDevice);
  1024. IoCompleteIrp(AtaDriver, Irp, Status);
  1025. break;
  1026. //
  1027. // Ignore everything unrecognized.
  1028. //
  1029. default:
  1030. ASSERT(FALSE);
  1031. break;
  1032. }
  1033. return;
  1034. }
  1035. KSTATUS
  1036. AtapProcessResourceRequirements (
  1037. PIRP Irp,
  1038. PATA_CONTROLLER Controller
  1039. )
  1040. /*++
  1041. Routine Description:
  1042. This routine filters through the resource requirements presented by the
  1043. bus for an ATA controller. It adds an interrupt vector requirement for
  1044. any interrupt line requested.
  1045. Arguments:
  1046. Irp - Supplies a pointer to the I/O request packet.
  1047. Controller - Supplies a pointer to the ATA controller.
  1048. Return Value:
  1049. Status code.
  1050. --*/
  1051. {
  1052. ULONGLONG Interface;
  1053. RESOURCE_REQUIREMENT LegacyRequirement;
  1054. ULONGLONG LineCharacteristics;
  1055. PRESOURCE_REQUIREMENT NewRequirement;
  1056. BOOL PrimaryLegacy;
  1057. PRESOURCE_REQUIREMENT Requirement;
  1058. PRESOURCE_REQUIREMENT_LIST RequirementList;
  1059. PRESOURCE_CONFIGURATION_LIST Requirements;
  1060. BOOL SecondaryLegacy;
  1061. KSTATUS Status;
  1062. ULONGLONG VectorCharacteristics;
  1063. RESOURCE_REQUIREMENT VectorRequirement;
  1064. ASSERT((Irp->MajorCode == IrpMajorStateChange) &&
  1065. (Irp->MinorCode == IrpMinorQueryResources));
  1066. Requirements = Irp->U.QueryResources.ResourceRequirements;
  1067. if (Requirements == NULL) {
  1068. Status = STATUS_NOT_CONFIGURED;
  1069. goto ProcessResourceRequirementsEnd;
  1070. }
  1071. RequirementList = IoGetNextResourceConfiguration(Requirements, NULL);
  1072. //
  1073. // Start listening for a PCI config interface.
  1074. //
  1075. if (Controller->RegisteredForPciConfigInterfaces == FALSE) {
  1076. Status = IoRegisterForInterfaceNotifications(
  1077. &AtaPciConfigurationInterfaceUuid,
  1078. AtapProcessPciConfigInterfaceChangeNotification,
  1079. Irp->Device,
  1080. Controller,
  1081. TRUE);
  1082. if (!KSUCCESS(Status)) {
  1083. goto ProcessResourceRequirementsEnd;
  1084. }
  1085. Controller->RegisteredForPciConfigInterfaces = TRUE;
  1086. }
  1087. //
  1088. // Try to read the interface from PCI.
  1089. //
  1090. if (Controller->PciConfigInterfaceAvailable == FALSE) {
  1091. Status = STATUS_NOT_CONFIGURED;
  1092. goto ProcessResourceRequirementsEnd;
  1093. }
  1094. Status = Controller->PciConfigInterface.ReadPciConfig(
  1095. Controller->PciConfigInterface.DeviceToken,
  1096. IDE_INTERFACE_OFFSET,
  1097. IDE_INTERFACE_SIZE,
  1098. &Interface);
  1099. if (!KSUCCESS(Status)) {
  1100. goto ProcessResourceRequirementsEnd;
  1101. }
  1102. Controller->Interface = Interface;
  1103. //
  1104. // Look to see if the interface is in native or legacy mode.
  1105. //
  1106. PrimaryLegacy = TRUE;
  1107. SecondaryLegacy = TRUE;
  1108. if ((Interface & IDE_INTERFACE_PRIMARY_NATIVE_SUPPORTED) != 0) {
  1109. if ((Interface & IDE_INTERFACE_PRIMARY_NATIVE_ENABLED) != 0) {
  1110. PrimaryLegacy = FALSE;
  1111. }
  1112. }
  1113. if ((Interface & IDE_INTERFACE_SECONDARY_NATIVE_SUPPORTED) != 0) {
  1114. if ((Interface & IDE_INTERFACE_SECONDARY_NATIVE_ENABLED) != 0) {
  1115. SecondaryLegacy = FALSE;
  1116. }
  1117. }
  1118. //
  1119. // Add the primary legacy region if this controller is using that.
  1120. //
  1121. if (PrimaryLegacy != FALSE) {
  1122. RtlZeroMemory(&LegacyRequirement, sizeof(RESOURCE_REQUIREMENT));
  1123. LegacyRequirement.Type = ResourceTypeIoPort;
  1124. LegacyRequirement.Flags = RESOURCE_FLAG_NOT_SHAREABLE;
  1125. LegacyRequirement.Minimum = ATA_LEGACY_PRIMARY_IO_BASE;
  1126. LegacyRequirement.Length = ATA_LEGACY_IO_SIZE;
  1127. LegacyRequirement.Maximum = LegacyRequirement.Minimum +
  1128. LegacyRequirement.Length;
  1129. Status = IoCreateAndAddResourceRequirement(&LegacyRequirement,
  1130. RequirementList,
  1131. NULL);
  1132. if (!KSUCCESS(Status)) {
  1133. goto ProcessResourceRequirementsEnd;
  1134. }
  1135. LegacyRequirement.Minimum = ATA_LEGACY_PRIMARY_CONTROL_BASE;
  1136. LegacyRequirement.Length = ATA_LEGACY_CONTROL_SIZE;
  1137. LegacyRequirement.Maximum = LegacyRequirement.Minimum +
  1138. LegacyRequirement.Length;
  1139. Status = IoCreateAndAddResourceRequirement(&LegacyRequirement,
  1140. RequirementList,
  1141. NULL);
  1142. if (!KSUCCESS(Status)) {
  1143. goto ProcessResourceRequirementsEnd;
  1144. }
  1145. }
  1146. //
  1147. // Add the secondary legacy region if this controller is using that.
  1148. //
  1149. if (SecondaryLegacy != FALSE) {
  1150. RtlZeroMemory(&LegacyRequirement, sizeof(RESOURCE_REQUIREMENT));
  1151. LegacyRequirement.Type = ResourceTypeIoPort;
  1152. LegacyRequirement.Flags = RESOURCE_FLAG_NOT_SHAREABLE;
  1153. LegacyRequirement.Minimum = ATA_LEGACY_SECONDARY_IO_BASE;
  1154. LegacyRequirement.Length = ATA_LEGACY_IO_SIZE;
  1155. LegacyRequirement.Maximum = LegacyRequirement.Minimum +
  1156. LegacyRequirement.Length;
  1157. Status = IoCreateAndAddResourceRequirement(&LegacyRequirement,
  1158. RequirementList,
  1159. NULL);
  1160. if (!KSUCCESS(Status)) {
  1161. goto ProcessResourceRequirementsEnd;
  1162. }
  1163. LegacyRequirement.Minimum = ATA_LEGACY_SECONDARY_CONTROL_BASE;
  1164. LegacyRequirement.Length = ATA_LEGACY_CONTROL_SIZE;
  1165. LegacyRequirement.Maximum = LegacyRequirement.Minimum +
  1166. LegacyRequirement.Length;
  1167. Status = IoCreateAndAddResourceRequirement(&LegacyRequirement,
  1168. RequirementList,
  1169. NULL);
  1170. if (!KSUCCESS(Status)) {
  1171. goto ProcessResourceRequirementsEnd;
  1172. }
  1173. }
  1174. //
  1175. // Initialize a nice interrupt vector requirement in preparation.
  1176. //
  1177. RtlZeroMemory(&VectorRequirement, sizeof(RESOURCE_REQUIREMENT));
  1178. VectorRequirement.Type = ResourceTypeInterruptVector;
  1179. VectorRequirement.Minimum = 0;
  1180. VectorRequirement.Maximum = -1;
  1181. VectorRequirement.Length = 1;
  1182. //
  1183. // Loop through all configuration lists adding a vector for each line.
  1184. //
  1185. while (RequirementList != NULL) {
  1186. //
  1187. // Loop through every requirement in the list.
  1188. //
  1189. Requirement = IoGetNextResourceRequirement(RequirementList, NULL);
  1190. while (Requirement != NULL) {
  1191. //
  1192. // If the requirement is an interrupt line, then add a requirement
  1193. // for a vector as well. If legacy vectors are going to be added,
  1194. // then just remember there's an extra interrupt line there.
  1195. //
  1196. if (Requirement->Type == ResourceTypeInterruptLine) {
  1197. if ((PrimaryLegacy == FALSE) || (SecondaryLegacy == FALSE)) {
  1198. VectorCharacteristics = 0;
  1199. LineCharacteristics = Requirement->Characteristics;
  1200. if ((LineCharacteristics &
  1201. INTERRUPT_LINE_ACTIVE_LOW) != 0) {
  1202. VectorCharacteristics |= INTERRUPT_VECTOR_ACTIVE_LOW;
  1203. }
  1204. if ((LineCharacteristics &
  1205. INTERRUPT_LINE_EDGE_TRIGGERED) != 0) {
  1206. VectorCharacteristics |=
  1207. INTERRUPT_VECTOR_EDGE_TRIGGERED;
  1208. }
  1209. VectorRequirement.Characteristics = VectorCharacteristics;
  1210. VectorRequirement.OwningRequirement = Requirement;
  1211. Status = IoCreateAndAddResourceRequirement(
  1212. &VectorRequirement,
  1213. RequirementList,
  1214. NULL);
  1215. if (!KSUCCESS(Status)) {
  1216. goto ProcessResourceRequirementsEnd;
  1217. }
  1218. } else {
  1219. Controller->SkipFirstInterrupt = TRUE;
  1220. }
  1221. }
  1222. //
  1223. // Get the next resource requirement.
  1224. //
  1225. Requirement = IoGetNextResourceRequirement(RequirementList,
  1226. Requirement);
  1227. }
  1228. //
  1229. // Get the next possible resource configuration.
  1230. //
  1231. RequirementList = IoGetNextResourceConfiguration(Requirements,
  1232. RequirementList);
  1233. }
  1234. //
  1235. // If in legacy mode, add the legacy interrupts.
  1236. //
  1237. if ((SecondaryLegacy != FALSE) && (PrimaryLegacy != FALSE)) {
  1238. RequirementList = IoGetNextResourceConfiguration(Requirements, NULL);
  1239. ASSERT(RequirementList != NULL);
  1240. LegacyRequirement.Type = ResourceTypeInterruptLine;
  1241. LegacyRequirement.Minimum = ATA_LEGACY_PRIMARY_INTERRUPT;
  1242. LegacyRequirement.Maximum = LegacyRequirement.Minimum + 1;
  1243. LegacyRequirement.Length = 1;
  1244. LegacyRequirement.Characteristics =
  1245. ATA_LEGACY_INTERRUPT_CHARACTERISTICS;
  1246. LegacyRequirement.Flags = 0;
  1247. Status = IoCreateAndAddResourceRequirement(&LegacyRequirement,
  1248. RequirementList,
  1249. &NewRequirement);
  1250. if (!KSUCCESS(Status)) {
  1251. goto ProcessResourceRequirementsEnd;
  1252. }
  1253. VectorRequirement.Flags |= RESOURCE_FLAG_NOT_SHAREABLE;
  1254. VectorRequirement.Characteristics = ATA_LEGACY_VECTOR_CHARACTERISTICS;
  1255. VectorRequirement.OwningRequirement = NewRequirement;
  1256. Status = IoCreateAndAddResourceRequirement(&VectorRequirement,
  1257. RequirementList,
  1258. NULL);
  1259. if (!KSUCCESS(Status)) {
  1260. goto ProcessResourceRequirementsEnd;
  1261. }
  1262. LegacyRequirement.Minimum = ATA_LEGACY_SECONDARY_INTERRUPT;
  1263. LegacyRequirement.Maximum = LegacyRequirement.Minimum + 1;
  1264. Status = IoCreateAndAddResourceRequirement(&LegacyRequirement,
  1265. RequirementList,
  1266. &NewRequirement);
  1267. if (!KSUCCESS(Status)) {
  1268. goto ProcessResourceRequirementsEnd;
  1269. }
  1270. VectorRequirement.OwningRequirement = NewRequirement;
  1271. Status = IoCreateAndAddResourceRequirement(&VectorRequirement,
  1272. RequirementList,
  1273. NULL);
  1274. if (!KSUCCESS(Status)) {
  1275. goto ProcessResourceRequirementsEnd;
  1276. }
  1277. }
  1278. Status = STATUS_SUCCESS;
  1279. ProcessResourceRequirementsEnd:
  1280. return Status;
  1281. }
  1282. KSTATUS
  1283. AtapStartController (
  1284. PIRP Irp,
  1285. PATA_CONTROLLER Controller
  1286. )
  1287. /*++
  1288. Routine Description:
  1289. This routine starts an ATA controller device.
  1290. Arguments:
  1291. Irp - Supplies a pointer to the I/O request packet.
  1292. Controller - Supplies a pointer to the ATA controller.
  1293. Return Value:
  1294. Status code.
  1295. --*/
  1296. {
  1297. PRESOURCE_ALLOCATION Allocation;
  1298. PRESOURCE_ALLOCATION_LIST AllocationList;
  1299. IO_CONNECT_INTERRUPT_PARAMETERS Connect;
  1300. UINTN Index;
  1301. BOOL LineSkipped;
  1302. BOOL PrimaryInterruptConnected;
  1303. BOOL SecondaryInterruptConnected;
  1304. KSTATUS Status;
  1305. PRESOURCE_ALLOCATION VectorAllocation;
  1306. PrimaryInterruptConnected = Controller->PrimaryInterruptFound;
  1307. SecondaryInterruptConnected = Controller->SecondaryInterruptFound;
  1308. for (Index = 0; Index < ATA_CABLE_COUNT; Index += 1) {
  1309. Controller->Channel[Index].IoBase = -1;
  1310. Controller->Channel[Index].ControlBase = -1;
  1311. Controller->Channel[Index].BusMasterBase = -1;
  1312. }
  1313. Index = 0;
  1314. LineSkipped = FALSE;
  1315. Status = PmInitialize(Irp->Device);
  1316. if (!KSUCCESS(Status)) {
  1317. return Status;
  1318. }
  1319. Status = PmDeviceAddReference(Irp->Device);
  1320. if (!KSUCCESS(Status)) {
  1321. return Status;
  1322. }
  1323. //
  1324. // Loop through the allocated resources to get the controller base and the
  1325. // interrupt.
  1326. //
  1327. VectorAllocation = NULL;
  1328. AllocationList = Irp->U.StartDevice.ProcessorLocalResources;
  1329. Allocation = IoGetNextResourceAllocation(AllocationList, NULL);
  1330. while (Allocation != NULL) {
  1331. //
  1332. // If the resource is an interrupt line, search for the next interrupt
  1333. // vector.
  1334. //
  1335. if (Allocation->Type == ResourceTypeInterruptLine) {
  1336. if ((LineSkipped == FALSE) &&
  1337. (Controller->SkipFirstInterrupt != FALSE)) {
  1338. LineSkipped = TRUE;
  1339. } else {
  1340. VectorAllocation = IoGetNextResourceAllocation(
  1341. AllocationList,
  1342. VectorAllocation);
  1343. while (VectorAllocation != NULL) {
  1344. if (VectorAllocation->Type == ResourceTypeInterruptVector) {
  1345. ASSERT(VectorAllocation->OwningAllocation ==
  1346. Allocation);
  1347. if (Controller->PrimaryInterruptFound == FALSE) {
  1348. Controller->PrimaryInterruptLine =
  1349. Allocation->Allocation;
  1350. Controller->PrimaryInterruptVector =
  1351. VectorAllocation->Allocation;
  1352. Controller->PrimaryInterruptFound = TRUE;
  1353. } else if (Controller->SecondaryInterruptFound ==
  1354. FALSE) {
  1355. Controller->SecondaryInterruptLine =
  1356. Allocation->Allocation;
  1357. Controller->SecondaryInterruptVector =
  1358. VectorAllocation->Allocation;
  1359. Controller->SecondaryInterruptFound = TRUE;
  1360. } else {
  1361. //
  1362. // There shouldn't be more than two interrupts to
  1363. // connect.
  1364. //
  1365. ASSERT(FALSE);
  1366. }
  1367. break;
  1368. }
  1369. VectorAllocation = IoGetNextResourceAllocation(
  1370. AllocationList,
  1371. VectorAllocation);
  1372. }
  1373. }
  1374. } else if (Allocation->Type == ResourceTypeIoPort) {
  1375. ASSERT(Allocation->Allocation < MAX_USHORT);
  1376. switch (Index) {
  1377. case 0:
  1378. if (Allocation->Length >= 8) {
  1379. Controller->Channel[0].IoBase = Allocation->Allocation;
  1380. }
  1381. break;
  1382. case 1:
  1383. if (Allocation->Length >= 4) {
  1384. Controller->Channel[0].ControlBase =
  1385. Allocation->Allocation + 2;
  1386. }
  1387. break;
  1388. case 2:
  1389. if (Allocation->Length >= 8) {
  1390. Controller->Channel[1].IoBase = Allocation->Allocation;
  1391. }
  1392. break;
  1393. case 3:
  1394. if (Allocation->Length >= 4) {
  1395. Controller->Channel[1].ControlBase =
  1396. Allocation->Allocation + 2;
  1397. }
  1398. break;
  1399. case 4:
  1400. if (Allocation->Length >= 16) {
  1401. Controller->Channel[0].BusMasterBase =
  1402. Allocation->Allocation;
  1403. Controller->Channel[1].BusMasterBase =
  1404. Allocation->Allocation + 8;
  1405. }
  1406. break;
  1407. }
  1408. Index += 1;
  1409. } else if (Allocation->Type == ResourceTypePhysicalAddressSpace) {
  1410. Index += 1;
  1411. }
  1412. //
  1413. // Get the next allocation in the list.
  1414. //
  1415. Allocation = IoGetNextResourceAllocation(AllocationList, Allocation);
  1416. }
  1417. //
  1418. // Assign the legacy register locations if needed.
  1419. //
  1420. if ((Controller->Interface & IDE_INTERFACE_PRIMARY_NATIVE_ENABLED) == 0) {
  1421. Controller->Channel[0].IoBase = ATA_LEGACY_PRIMARY_IO_BASE;
  1422. Controller->Channel[0].ControlBase = ATA_LEGACY_PRIMARY_CONTROL_BASE;
  1423. }
  1424. if ((Controller->Interface & IDE_INTERFACE_SECONDARY_NATIVE_ENABLED) == 0) {
  1425. Controller->Channel[1].IoBase = ATA_LEGACY_SECONDARY_IO_BASE;
  1426. Controller->Channel[1].ControlBase = ATA_LEGACY_SECONDARY_CONTROL_BASE;
  1427. }
  1428. //
  1429. // Put the controller into a known state.
  1430. //
  1431. Status = AtapResetController(Controller);
  1432. if (!KSUCCESS(Status)) {
  1433. goto StartControllerEnd;
  1434. }
  1435. RtlZeroMemory(&Connect, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS));
  1436. Connect.Version = IO_CONNECT_INTERRUPT_PARAMETERS_VERSION;
  1437. Connect.Device = Irp->Device;
  1438. Connect.InterruptServiceRoutine = AtaInterruptService;
  1439. Connect.DispatchServiceRoutine = AtaInterruptServiceDpc;
  1440. Connect.Context = Controller;
  1441. if ((PrimaryInterruptConnected == FALSE) &&
  1442. (Controller->PrimaryInterruptFound != FALSE) &&
  1443. (Controller->Channel[0].BusMasterBase != (USHORT)-1)) {
  1444. Connect.LineNumber = Controller->PrimaryInterruptLine;
  1445. Connect.Vector = Controller->PrimaryInterruptVector;
  1446. Connect.Interrupt = &(Controller->PrimaryInterruptHandle);
  1447. Status = IoConnectInterrupt(&Connect);
  1448. if (!KSUCCESS(Status)) {
  1449. goto StartControllerEnd;
  1450. }
  1451. }
  1452. if ((SecondaryInterruptConnected == FALSE) &&
  1453. (Controller->SecondaryInterruptFound != FALSE) &&
  1454. (Controller->Channel[1].BusMasterBase != (USHORT)-1)) {
  1455. Connect.LineNumber = Controller->SecondaryInterruptLine;
  1456. Connect.Vector = Controller->SecondaryInterruptVector;
  1457. Connect.Interrupt = &(Controller->SecondaryInterruptHandle);
  1458. Status = IoConnectInterrupt(&Connect);
  1459. if (!KSUCCESS(Status)) {
  1460. goto StartControllerEnd;
  1461. }
  1462. }
  1463. Status = STATUS_SUCCESS;
  1464. StartControllerEnd:
  1465. PmDeviceReleaseReference(Irp->Device);
  1466. return Status;
  1467. }
  1468. KSTATUS
  1469. AtapResetController (
  1470. PATA_CONTROLLER Controller
  1471. )
  1472. /*++
  1473. Routine Description:
  1474. This routine resets an ATA controller device.
  1475. Arguments:
  1476. Controller - Supplies a pointer to the ATA controller.
  1477. Return Value:
  1478. Status code.
  1479. --*/
  1480. {
  1481. //
  1482. // Disable interrupts.
  1483. //
  1484. Controller->Channel[0].InterruptDisable = ATA_CONTROL_INTERRUPT_DISABLE;
  1485. Controller->Channel[1].InterruptDisable = ATA_CONTROL_INTERRUPT_DISABLE;
  1486. HlBusySpin(2 * MICROSECONDS_PER_MILLISECOND);
  1487. AtapWriteRegister(&(Controller->Channel[0]),
  1488. AtaRegisterControl,
  1489. Controller->Channel[0].InterruptDisable);
  1490. AtapReadRegister(&(Controller->Channel[0]), AtaRegisterStatus);
  1491. if (Controller->Channel[0].BusMasterBase != (USHORT)-1) {
  1492. AtapWriteRegister(&(Controller->Channel[0]),
  1493. AtaRegisterBusMasterStatus,
  1494. IDE_STATUS_INTERRUPT | IDE_STATUS_ERROR);
  1495. AtapWriteRegister(&(Controller->Channel[0]),
  1496. AtaRegisterBusMasterCommand,
  1497. 0);
  1498. }
  1499. if (Controller->Channel[1].IoBase != (USHORT)-1) {
  1500. HlBusySpin(2 * MICROSECONDS_PER_MILLISECOND);
  1501. AtapWriteRegister(&(Controller->Channel[1]),
  1502. AtaRegisterControl,
  1503. Controller->Channel[1].InterruptDisable);
  1504. AtapReadRegister(&(Controller->Channel[1]), AtaRegisterStatus);
  1505. if (Controller->Channel[1].BusMasterBase != (USHORT)-1) {
  1506. AtapWriteRegister(&(Controller->Channel[1]),
  1507. AtaRegisterBusMasterStatus,
  1508. IDE_STATUS_INTERRUPT | IDE_STATUS_ERROR);
  1509. AtapWriteRegister(&(Controller->Channel[1]),
  1510. AtaRegisterBusMasterCommand,
  1511. 0);
  1512. }
  1513. }
  1514. return STATUS_SUCCESS;
  1515. }
  1516. VOID
  1517. AtapEnumerateDrives (
  1518. PIRP Irp,
  1519. PATA_CONTROLLER Controller
  1520. )
  1521. /*++
  1522. Routine Description:
  1523. This routine enumerates all drives on an ATA controller.
  1524. Arguments:
  1525. Irp - Supplies a pointer to the query children IRP.
  1526. Controller - Supplies a pointer to the ATA controller.
  1527. Return Value:
  1528. None.
  1529. --*/
  1530. {
  1531. PATA_CHILD Child;
  1532. ULONG ChildCount;
  1533. UINTN ChildIndex;
  1534. PDEVICE Children[4];
  1535. KSTATUS Status;
  1536. Status = PmDeviceAddReference(Irp->Device);
  1537. if (!KSUCCESS(Status)) {
  1538. IoCompleteIrp(AtaDriver, Irp, Status);
  1539. return;
  1540. }
  1541. ChildCount = 0;
  1542. for (ChildIndex = 0; ChildIndex < ATA_CHILD_COUNT; ChildIndex += 1) {
  1543. Child = &(Controller->ChildContexts[ChildIndex]);
  1544. Status = AtapIdentifyDevice(Child);
  1545. if (!KSUCCESS(Status)) {
  1546. Controller->ChildDevices[ChildIndex] = NULL;
  1547. } else {
  1548. if (Controller->ChildDevices[ChildIndex] == NULL) {
  1549. Status = IoCreateDevice(
  1550. AtaDriver,
  1551. Child,
  1552. Irp->Device,
  1553. "Disk",
  1554. DISK_CLASS_ID,
  1555. NULL,
  1556. &(Controller->ChildDevices[ChildIndex]));
  1557. if (!KSUCCESS(Status)) {
  1558. Controller->ChildDevices[ChildIndex] = NULL;
  1559. }
  1560. }
  1561. }
  1562. if (Controller->ChildDevices[ChildIndex] != NULL) {
  1563. Children[ChildCount] = Controller->ChildDevices[ChildIndex];
  1564. ChildCount += 1;
  1565. }
  1566. }
  1567. if (ChildCount != 0) {
  1568. Status = IoMergeChildArrays(Irp,
  1569. Children,
  1570. ChildCount,
  1571. ATA_ALLOCATION_TAG);
  1572. if (!KSUCCESS(Status)) {
  1573. goto EnumerateDrivesEnd;
  1574. }
  1575. }
  1576. Status = STATUS_SUCCESS;
  1577. EnumerateDrivesEnd:
  1578. PmDeviceReleaseReference(Irp->Device);
  1579. IoCompleteIrp(AtaDriver, Irp, Status);
  1580. return;
  1581. }
  1582. KSTATUS
  1583. AtapIdentifyDevice (
  1584. PATA_CHILD Device
  1585. )
  1586. /*++
  1587. Routine Description:
  1588. This routine attempts to send the IDENTIFY packet command and process the
  1589. results.
  1590. Arguments:
  1591. Device - Supplies a pointer to the child device to query.
  1592. Return Value:
  1593. Status code.
  1594. --*/
  1595. {
  1596. ATA_IDENTIFY_PACKET Identify;
  1597. UCHAR Lba1;
  1598. UCHAR Lba2;
  1599. KSTATUS Status;
  1600. if (Device->Channel->IoBase == (USHORT)-1) {
  1601. return STATUS_NO_SUCH_DEVICE;
  1602. }
  1603. Device->DmaSupported = FALSE;
  1604. Status = AtapPioCommand(Device,
  1605. AtaCommandIdentify,
  1606. TRUE,
  1607. FALSE,
  1608. 0,
  1609. 0,
  1610. &Identify,
  1611. 0,
  1612. 0,
  1613. FALSE);
  1614. if (!KSUCCESS(Status)) {
  1615. //
  1616. // If the identify command failed, check out LBA1 and LBA2 to see if
  1617. // they're responding like an ATAPI device.
  1618. //
  1619. Lba1 = AtapReadRegister(Device->Channel, AtaRegisterLba1);
  1620. Lba2 = AtapReadRegister(Device->Channel, AtaRegisterLba2);
  1621. if (((Lba1 == ATA_PATAPI_LBA1) && (Lba2 == ATA_PATAPI_LBA2)) ||
  1622. ((Lba1 == ATA_PATAPI_LBA1) && (Lba2 == ATA_PATAPI_LBA2))) {
  1623. //
  1624. // TODO: ATAPI devices.
  1625. //
  1626. } else if ((Lba1 == ATA_SATA_LBA1) && (Lba2 == ATA_SATA_LBA2)) {
  1627. RtlDebugPrint("TODO: SATA\n");
  1628. }
  1629. goto IdentifyDeviceEnd;
  1630. }
  1631. //
  1632. // Get the total capacity of the disk.
  1633. //
  1634. if ((Identify.CommandSetSupported & ATA_SUPPORTED_COMMAND_LBA48) != 0) {
  1635. Device->TotalSectors = Identify.TotalSectorsLba48;
  1636. } else {
  1637. Device->TotalSectors = Identify.TotalSectors;
  1638. }
  1639. //
  1640. // Determine whether or not to do DMA to this device.
  1641. //
  1642. if (Device->Channel->BusMasterBase != (USHORT)-1) {
  1643. Device->DmaSupported = TRUE;
  1644. }
  1645. IdentifyDeviceEnd:
  1646. return Status;
  1647. }
  1648. KSTATUS
  1649. AtapPerformDmaIo (
  1650. PIRP Irp,
  1651. PATA_CHILD Device,
  1652. BOOL HaveDpcLock
  1653. )
  1654. /*++
  1655. Routine Description:
  1656. This routine starts a DMA-based I/O transfer. This routine assumes the
  1657. channel lock is already held.
  1658. Arguments:
  1659. Irp - Supplies a pointer to the I/O request packet.
  1660. Device - Supplies a pointer to the ATA child device.
  1661. HaveDpcLock - Supplies a boolean indicating if the caller already has the
  1662. DPC lock acquired.
  1663. Return Value:
  1664. Status code.
  1665. --*/
  1666. {
  1667. ULONGLONG BlockAddress;
  1668. UINTN BytesPreviouslyCompleted;
  1669. UINTN BytesToComplete;
  1670. ATA_COMMAND Command;
  1671. UCHAR DmaCommand;
  1672. PHYSICAL_ADDRESS EndBoundary;
  1673. ULONG EntrySize;
  1674. PIO_BUFFER_FRAGMENT Fragment;
  1675. UINTN FragmentIndex;
  1676. UINTN FragmentOffset;
  1677. PIO_BUFFER IoBuffer;
  1678. UINTN IoBufferOffset;
  1679. IO_OFFSET IoOffset;
  1680. BOOL Lba48;
  1681. UINTN MaxTransferSize;
  1682. RUNLEVEL OldRunLevel;
  1683. PHYSICAL_ADDRESS PhysicalAddress;
  1684. PATA_PRDT Prdt;
  1685. USHORT PrdtAddressRegister;
  1686. UINTN PrdtIndex;
  1687. UINTN SectorCount;
  1688. KSTATUS Status;
  1689. UINTN TransferSize;
  1690. UINTN TransferSizeRemaining;
  1691. BOOL Write;
  1692. ASSERT(Device->Channel->Irp == Irp);
  1693. ASSERT(Device->Channel->OwningChild == Device);
  1694. ASSERT(Irp->U.ReadWrite.IoBuffer != NULL);
  1695. IoBuffer = Irp->U.ReadWrite.IoBuffer;
  1696. BytesPreviouslyCompleted = Irp->U.ReadWrite.IoBytesCompleted;
  1697. BytesToComplete = Irp->U.ReadWrite.IoSizeInBytes;
  1698. IoOffset = Irp->U.ReadWrite.NewIoOffset;
  1699. ASSERT(BytesPreviouslyCompleted < BytesToComplete);
  1700. ASSERT(IoOffset == (Irp->U.ReadWrite.IoOffset + BytesPreviouslyCompleted));
  1701. ASSERT(Device->Channel->BusMasterBase != (USHORT)-1);
  1702. ASSERT(IS_ALIGNED(IoOffset, ATA_SECTOR_SIZE) != FALSE);
  1703. ASSERT(IS_ALIGNED(BytesToComplete, ATA_SECTOR_SIZE) != FALSE);
  1704. Write = FALSE;
  1705. if (Irp->MinorCode == IrpMinorIoWrite) {
  1706. Write = TRUE;
  1707. }
  1708. //
  1709. // Determine the bytes to complete this round.
  1710. //
  1711. MaxTransferSize = ATA_MAX_LBA48_SECTOR_COUNT * ATA_SECTOR_SIZE;
  1712. if (Device->Lba48Supported == FALSE) {
  1713. MaxTransferSize = ATA_MAX_LBA28_SECTOR_COUNT * ATA_SECTOR_SIZE;
  1714. }
  1715. TransferSize = BytesToComplete - BytesPreviouslyCompleted;
  1716. if (TransferSize > MaxTransferSize) {
  1717. TransferSize = MaxTransferSize;
  1718. }
  1719. //
  1720. // Get to the currect spot in the I/O buffer.
  1721. //
  1722. IoBufferOffset = MmGetIoBufferCurrentOffset(IoBuffer);
  1723. IoBufferOffset += BytesPreviouslyCompleted;
  1724. FragmentIndex = 0;
  1725. FragmentOffset = 0;
  1726. while (IoBufferOffset != 0) {
  1727. ASSERT(FragmentIndex < IoBuffer->FragmentCount);
  1728. Fragment = &(IoBuffer->Fragment[FragmentIndex]);
  1729. if (IoBufferOffset < Fragment->Size) {
  1730. FragmentOffset = IoBufferOffset;
  1731. break;
  1732. }
  1733. IoBufferOffset -= Fragment->Size;
  1734. FragmentIndex += 1;
  1735. }
  1736. //
  1737. // Loop over every fragment in the I/O buffer setting up PRDT entries.
  1738. //
  1739. Prdt = Device->Channel->Prdt;
  1740. PrdtIndex = 0;
  1741. TransferSizeRemaining = TransferSize;
  1742. while ((TransferSizeRemaining != 0) &&
  1743. (PrdtIndex < (ATA_PRDT_DISK_SIZE / sizeof(ATA_PRDT)))) {
  1744. ASSERT(FragmentIndex < IoBuffer->FragmentCount);
  1745. Fragment = &(IoBuffer->Fragment[FragmentIndex]);
  1746. ASSERT(IS_ALIGNED(Fragment->Size, ATA_SECTOR_SIZE) != FALSE);
  1747. ASSERT(IS_ALIGNED(FragmentOffset, ATA_SECTOR_SIZE) != FALSE);
  1748. //
  1749. // Determine the size of the PRDT entry.
  1750. //
  1751. EntrySize = TransferSizeRemaining;
  1752. if (EntrySize > (Fragment->Size - FragmentOffset)) {
  1753. EntrySize = Fragment->Size - FragmentOffset;
  1754. }
  1755. PhysicalAddress = Fragment->PhysicalAddress + FragmentOffset;
  1756. EndBoundary = ALIGN_RANGE_DOWN(PhysicalAddress + EntrySize - 1,
  1757. ATA_DMA_BOUNDARY);
  1758. if (ALIGN_RANGE_DOWN(PhysicalAddress, ATA_DMA_BOUNDARY) !=
  1759. EndBoundary) {
  1760. EntrySize =
  1761. ALIGN_RANGE_UP(PhysicalAddress + 1, ATA_DMA_BOUNDARY) -
  1762. PhysicalAddress;
  1763. }
  1764. TransferSizeRemaining -= EntrySize;
  1765. //
  1766. // ATA can only DMA to lower 4GB addresses.
  1767. //
  1768. ASSERT(IS_ALIGNED(PhysicalAddress, ATA_SECTOR_SIZE) != FALSE);
  1769. ASSERT(PhysicalAddress == (ULONG)PhysicalAddress);
  1770. ASSERT((PhysicalAddress + EntrySize) ==
  1771. (ULONG)(PhysicalAddress + EntrySize));
  1772. Prdt->PhysicalAddress = PhysicalAddress;
  1773. if (EntrySize == ATA_DMA_BOUNDARY) {
  1774. Prdt->Size = 0;
  1775. } else {
  1776. Prdt->Size = EntrySize;
  1777. }
  1778. Prdt->Flags = 0;
  1779. Prdt += 1;
  1780. PrdtIndex += 1;
  1781. FragmentOffset += EntrySize;
  1782. if (FragmentOffset >= Fragment->Size) {
  1783. FragmentIndex += 1;
  1784. FragmentOffset = 0;
  1785. }
  1786. }
  1787. ASSERT(PrdtIndex != 0);
  1788. Prdt -= 1;
  1789. Prdt->Flags |= ATA_DMA_LAST_DESCRIPTOR;
  1790. TransferSize -= TransferSizeRemaining;
  1791. BlockAddress = IoOffset / ATA_SECTOR_SIZE;
  1792. SectorCount = TransferSize / ATA_SECTOR_SIZE;
  1793. ASSERT(SectorCount == (ULONG)SectorCount);
  1794. //
  1795. // Use LBA48 if the block address is too high or the sector size is too
  1796. // large.
  1797. //
  1798. if ((BlockAddress > ATA_MAX_LBA28) ||
  1799. (SectorCount > ATA_MAX_LBA28_SECTOR_COUNT)) {
  1800. Lba48 = TRUE;
  1801. if (Write != FALSE) {
  1802. Command = AtaCommandWriteDma48;
  1803. } else {
  1804. Command = AtaCommandReadDma48;
  1805. }
  1806. } else {
  1807. Lba48 = FALSE;
  1808. if (Write != FALSE) {
  1809. Command = AtaCommandWriteDma28;
  1810. } else {
  1811. Command = AtaCommandReadDma28;
  1812. }
  1813. if (SectorCount == ATA_MAX_LBA28_SECTOR_COUNT) {
  1814. SectorCount = 0;
  1815. }
  1816. }
  1817. OldRunLevel = RunLevelCount;
  1818. if (HaveDpcLock == FALSE) {
  1819. OldRunLevel = KeRaiseRunLevel(RunLevelDispatch);
  1820. KeAcquireSpinLock(&(Device->Controller->DpcLock));
  1821. }
  1822. Status = AtapSelectDevice(Device, FALSE);
  1823. if (!KSUCCESS(Status)) {
  1824. goto PerformDmaIoEnd;
  1825. }
  1826. //
  1827. // Set up the usual registers for a command.
  1828. //
  1829. AtapSetupCommand(Device, Lba48, 0, (ULONG)SectorCount, BlockAddress, 0);
  1830. //
  1831. // Enable interrupts and start the command.
  1832. //
  1833. Device->Channel->IoSize = TransferSize;
  1834. Device->Channel->InterruptDisable = 0;
  1835. AtapWriteRegister(Device->Channel, AtaRegisterControl, 0);
  1836. AtapWriteRegister(Device->Channel, AtaRegisterCommand, Command);
  1837. //
  1838. // Write the PRDT base address.
  1839. //
  1840. PrdtAddressRegister = Device->Channel->BusMasterBase +
  1841. ATA_BUS_MASTER_TABLE_REGISTER;
  1842. HlIoPortOutLong(PrdtAddressRegister,
  1843. Device->Channel->PrdtPhysicalAddress);
  1844. //
  1845. // Start the DMA.
  1846. //
  1847. DmaCommand = ATA_BUS_MASTER_COMMAND_DMA_ENABLE;
  1848. if (Write == FALSE) {
  1849. DmaCommand |= ATA_BUS_MASTER_COMMAND_DMA_READ;
  1850. }
  1851. //
  1852. // If this is the first set of DMA for the IRP, pend it.
  1853. //
  1854. if (BytesPreviouslyCompleted == 0) {
  1855. IoPendIrp(AtaDriver, Irp);
  1856. }
  1857. AtapWriteRegister(Device->Channel,
  1858. AtaRegisterBusMasterStatus,
  1859. IDE_STATUS_INTERRUPT | IDE_STATUS_ERROR);
  1860. AtapWriteRegister(Device->Channel, AtaRegisterBusMasterCommand, DmaCommand);
  1861. Status = STATUS_SUCCESS;
  1862. PerformDmaIoEnd:
  1863. if (HaveDpcLock == FALSE) {
  1864. KeReleaseSpinLock(&(Device->Controller->DpcLock));
  1865. KeLowerRunLevel(OldRunLevel);
  1866. }
  1867. return Status;
  1868. }
  1869. KSTATUS
  1870. AtapPerformPolledIo (
  1871. PIRP_READ_WRITE IrpReadWrite,
  1872. PATA_CHILD Device,
  1873. BOOL Write,
  1874. BOOL CriticalMode
  1875. )
  1876. /*++
  1877. Routine Description:
  1878. This routine performs polled I/O data transfers.
  1879. Arguments:
  1880. IrpReadWrite - Supplies a pointer to the I/O request read/write packet.
  1881. Device - Supplies a pointer to the ATA child device.
  1882. Write - Supplies a boolean indicating if this is a read operation (TRUE) or
  1883. a write operation (FALSE).
  1884. CriticalMode - Supplies a boolean indicating if this I/O operation is in
  1885. a critical code path (TRUE), such as a crash dump I/O request, or in
  1886. the default code path.
  1887. Return Value:
  1888. Status code.
  1889. --*/
  1890. {
  1891. UINTN BlockCount;
  1892. ULONGLONG BlockOffset;
  1893. UINTN BytesRemaining;
  1894. UINTN BytesThisRound;
  1895. KSTATUS CompletionStatus;
  1896. PIO_BUFFER_FRAGMENT Fragment;
  1897. UINTN FragmentIndex;
  1898. UINTN FragmentOffset;
  1899. PIO_BUFFER IoBuffer;
  1900. UINTN IoBufferOffset;
  1901. ULONG IrpReadWriteFlags;
  1902. BOOL ReadWriteIrpPrepared;
  1903. KSTATUS Status;
  1904. PVOID VirtualAddress;
  1905. IrpReadWrite->IoBytesCompleted = 0;
  1906. ReadWriteIrpPrepared = FALSE;
  1907. //
  1908. // All requests should be block aligned.
  1909. //
  1910. ASSERT(IrpReadWrite->IoBuffer != NULL);
  1911. ASSERT(IS_ALIGNED(IrpReadWrite->IoSizeInBytes, ATA_SECTOR_SIZE) != FALSE);
  1912. ASSERT(IS_ALIGNED(IrpReadWrite->IoOffset, ATA_SECTOR_SIZE) != FALSE);
  1913. //
  1914. // Prepare the I/O buffer for the polled I/O operation.
  1915. //
  1916. IrpReadWriteFlags = IRP_READ_WRITE_FLAG_POLLED;
  1917. if (Write != FALSE) {
  1918. IrpReadWriteFlags |= IRP_READ_WRITE_FLAG_WRITE;
  1919. }
  1920. Status = IoPrepareReadWriteIrp(IrpReadWrite,
  1921. ATA_SECTOR_SIZE,
  1922. 0,
  1923. MAX_ULONGLONG,
  1924. IrpReadWriteFlags);
  1925. if (!KSUCCESS(Status)) {
  1926. goto PerformPolledIoEnd;
  1927. }
  1928. ReadWriteIrpPrepared = TRUE;
  1929. //
  1930. // Make sure the I/O buffer is mapped before use. ATA currently depends on
  1931. // the buffer being mapped.
  1932. //
  1933. IoBuffer = IrpReadWrite->IoBuffer;
  1934. Status = MmMapIoBuffer(IoBuffer, FALSE, FALSE, FALSE);
  1935. if (!KSUCCESS(Status)) {
  1936. goto PerformPolledIoEnd;
  1937. }
  1938. //
  1939. // Find the starting fragment based on the current offset.
  1940. //
  1941. IoBufferOffset = MmGetIoBufferCurrentOffset(IoBuffer);
  1942. FragmentIndex = 0;
  1943. FragmentOffset = 0;
  1944. while (IoBufferOffset != 0) {
  1945. ASSERT(FragmentIndex < IoBuffer->FragmentCount);
  1946. Fragment = &(IoBuffer->Fragment[FragmentIndex]);
  1947. if (IoBufferOffset < Fragment->Size) {
  1948. FragmentOffset = IoBufferOffset;
  1949. break;
  1950. }
  1951. IoBufferOffset -= Fragment->Size;
  1952. FragmentIndex += 1;
  1953. }
  1954. //
  1955. // Loop reading in or writing out each fragment in the I/O buffer.
  1956. //
  1957. BlockOffset = IrpReadWrite->IoOffset / ATA_SECTOR_SIZE;
  1958. BytesRemaining = IrpReadWrite->IoSizeInBytes;
  1959. while (BytesRemaining != 0) {
  1960. ASSERT(FragmentIndex < IoBuffer->FragmentCount);
  1961. Fragment = (PIO_BUFFER_FRAGMENT)&(IoBuffer->Fragment[FragmentIndex]);
  1962. VirtualAddress = Fragment->VirtualAddress + FragmentOffset;
  1963. BytesThisRound = Fragment->Size - FragmentOffset;
  1964. if (BytesRemaining < BytesThisRound) {
  1965. BytesThisRound = BytesRemaining;
  1966. }
  1967. ASSERT(IS_ALIGNED(BytesThisRound, ATA_SECTOR_SIZE) != FALSE);
  1968. BlockCount = BytesThisRound / ATA_SECTOR_SIZE;
  1969. //
  1970. // Make sure the system isn't trying to do I/O off the end of the disk.
  1971. //
  1972. ASSERT(BlockOffset < Device->TotalSectors);
  1973. ASSERT(BlockCount >= 1);
  1974. Status = AtapReadWriteSectorsPio(Device,
  1975. BlockOffset,
  1976. BlockCount,
  1977. VirtualAddress,
  1978. Write,
  1979. CriticalMode);
  1980. if (!KSUCCESS(Status)) {
  1981. goto PerformPolledIoEnd;
  1982. }
  1983. BlockOffset += BlockCount;
  1984. BytesRemaining -= BytesThisRound;
  1985. FragmentOffset += BytesThisRound;
  1986. IrpReadWrite->IoBytesCompleted += BytesThisRound;
  1987. if (FragmentOffset >= Fragment->Size) {
  1988. FragmentIndex += 1;
  1989. FragmentOffset = 0;
  1990. }
  1991. }
  1992. Status = STATUS_SUCCESS;
  1993. PerformPolledIoEnd:
  1994. if (ReadWriteIrpPrepared != FALSE) {
  1995. CompletionStatus = IoCompleteReadWriteIrp(IrpReadWrite,
  1996. IrpReadWriteFlags);
  1997. if (!KSUCCESS(CompletionStatus) && KSUCCESS(Status)) {
  1998. Status = CompletionStatus;
  1999. }
  2000. }
  2001. IrpReadWrite->NewIoOffset = IrpReadWrite->IoOffset +
  2002. IrpReadWrite->IoBytesCompleted;
  2003. return Status;
  2004. }
  2005. KSTATUS
  2006. AtapSynchronizeDevice (
  2007. PATA_CHILD Device
  2008. )
  2009. /*++
  2010. Routine Description:
  2011. This routine synchronizes the device by sending a cache flush command.
  2012. Arguments:
  2013. Device - Supplies a pointer to the device.
  2014. Return Value:
  2015. Status code.
  2016. --*/
  2017. {
  2018. RUNLEVEL OldRunLevel;
  2019. KSTATUS Status;
  2020. KeAcquireQueuedLock(Device->Channel->Lock);
  2021. OldRunLevel = KeRaiseRunLevel(RunLevelDispatch);
  2022. KeAcquireSpinLock(&(Device->Controller->DpcLock));
  2023. Status = AtapSelectDevice(Device, FALSE);
  2024. if (KSUCCESS(Status)) {
  2025. Status = AtapExecuteCacheFlush(Device, FALSE);
  2026. }
  2027. KeReleaseSpinLock(&(Device->Controller->DpcLock));
  2028. KeLowerRunLevel(OldRunLevel);
  2029. KeReleaseQueuedLock(Device->Channel->Lock);
  2030. return Status;
  2031. }
  2032. KSTATUS
  2033. AtapBlockRead (
  2034. PVOID DiskToken,
  2035. PIO_BUFFER IoBuffer,
  2036. ULONGLONG BlockAddress,
  2037. UINTN BlockCount,
  2038. PUINTN BlocksCompleted
  2039. )
  2040. /*++
  2041. Routine Description:
  2042. This routine reads the block contents from the disk into the given I/O
  2043. buffer using polled I/O. It does so without acquiring any locks or
  2044. allocating any resources, as this routine is used for crash dump support
  2045. when the system is in a very fragile state. This routine must be called at
  2046. high level.
  2047. Arguments:
  2048. DiskToken - Supplies an opaque token for the disk. The appropriate token is
  2049. retrieved by querying the disk device information.
  2050. IoBuffer - Supplies a pointer to the I/O buffer where the data will be read.
  2051. BlockAddress - Supplies the block index to read (for physical disk, this is
  2052. the LBA).
  2053. BlockCount - Supplies the number of blocks to read.
  2054. BlocksCompleted - Supplies a pointer that receives the total number of
  2055. blocks read.
  2056. Return Value:
  2057. Status code.
  2058. --*/
  2059. {
  2060. IRP_READ_WRITE IrpReadWrite;
  2061. KSTATUS Status;
  2062. ASSERT(KeGetRunLevel() == RunLevelHigh);
  2063. //
  2064. // As this read routine is meant for critical code paths (crash dump),
  2065. // indicate that the channel should not be locked when performing the I/O.
  2066. // It may be that some other thread holds the lock, which would cause a
  2067. // dead lock as all other processors and threads are likely frozen.
  2068. //
  2069. IrpReadWrite.IoBuffer = IoBuffer;
  2070. IrpReadWrite.IoOffset = BlockAddress * ATA_SECTOR_SIZE;
  2071. IrpReadWrite.IoSizeInBytes = BlockCount * ATA_SECTOR_SIZE;
  2072. Status = AtapPerformPolledIo(&IrpReadWrite, DiskToken, FALSE, TRUE);
  2073. *BlocksCompleted = IrpReadWrite.IoBytesCompleted / ATA_SECTOR_SIZE;
  2074. return Status;
  2075. }
  2076. KSTATUS
  2077. AtapBlockWrite (
  2078. PVOID DiskToken,
  2079. PIO_BUFFER IoBuffer,
  2080. ULONGLONG BlockAddress,
  2081. UINTN BlockCount,
  2082. PUINTN BlocksCompleted
  2083. )
  2084. /*++
  2085. Routine Description:
  2086. This routine writes the contents of the given I/O buffer to the disk using
  2087. polled I/O. It does so without acquiring any locks or allocating any
  2088. resources, as this routine is used for crash dump support when the system
  2089. is in a very fragile state. This routine must be called at high level.
  2090. Arguments:
  2091. DiskToken - Supplies an opaque token for the disk. The appropriate token is
  2092. retrieved by querying the disk device information.
  2093. IoBuffer - Supplies a pointer to the I/O buffer containing the data to
  2094. write.
  2095. BlockAddress - Supplies the block index to write to (for physical disk,
  2096. this is the LBA).
  2097. BlockCount - Supplies the number of blocks to write.
  2098. BlocksCompleted - Supplies a pointer that receives the total number of
  2099. blocks written.
  2100. Return Value:
  2101. Status code.
  2102. --*/
  2103. {
  2104. IRP_READ_WRITE IrpReadWrite;
  2105. KSTATUS Status;
  2106. ASSERT(KeGetRunLevel() == RunLevelHigh);
  2107. //
  2108. // As this write routine is meant for critical code paths (crash dump),
  2109. // indicate that the channel should not be locked when performing the I/O.
  2110. // It may be that some other thread holds the lock, which would cause a
  2111. // dead lock as all other processors and threads are likely frozen.
  2112. //
  2113. IrpReadWrite.IoBuffer = IoBuffer;
  2114. IrpReadWrite.IoOffset = BlockAddress * ATA_SECTOR_SIZE;
  2115. IrpReadWrite.IoSizeInBytes = BlockCount * ATA_SECTOR_SIZE;
  2116. Status = AtapPerformPolledIo(&IrpReadWrite, DiskToken, TRUE, TRUE);
  2117. *BlocksCompleted = IrpReadWrite.IoBytesCompleted / ATA_SECTOR_SIZE;
  2118. return Status;
  2119. }
  2120. KSTATUS
  2121. AtapReadWriteSectorsPio (
  2122. PATA_CHILD AtaDevice,
  2123. ULONGLONG BlockAddress,
  2124. UINTN SectorCount,
  2125. PVOID Buffer,
  2126. BOOL Write,
  2127. BOOL CriticalMode
  2128. )
  2129. /*++
  2130. Routine Description:
  2131. This routine reads or writes a given number of sectors from the ATA disk
  2132. using polled I/O.
  2133. Arguments:
  2134. AtaDevice - Supplies a pointer to the ATA disk's context.
  2135. BlockAddress - Supplies the block number to read from or write to (LBA).
  2136. SectorCount - Supplies the number of blocks (sectors) to read from or write
  2137. to the device.
  2138. Buffer - Supplies the data buffer where the data will be read or written.
  2139. Write - Supplies a boolean indicating if this is a read operation (FALSE)
  2140. or a write operation (TRUE).
  2141. CriticalMode - Supplies a boolean indicating if this I/O operation is in
  2142. a critical code path (TRUE), such as a crash dump I/O request, or in
  2143. the default code path.
  2144. Return Value:
  2145. Status code.
  2146. --*/
  2147. {
  2148. ATA_COMMAND Command;
  2149. BOOL Lba48;
  2150. UINTN SectorCountThisRound;
  2151. KSTATUS Status;
  2152. if (BlockAddress > ATA_MAX_LBA28) {
  2153. Lba48 = TRUE;
  2154. if (Write != FALSE) {
  2155. Command = AtaCommandWritePio48;
  2156. } else {
  2157. Command = AtaCommandReadPio48;
  2158. }
  2159. } else {
  2160. Lba48 = FALSE;
  2161. if (Write != FALSE) {
  2162. Command = AtaCommandWritePio28;
  2163. } else {
  2164. Command = AtaCommandReadPio28;
  2165. }
  2166. }
  2167. Status = STATUS_SUCCESS;
  2168. while (SectorCount != 0) {
  2169. SectorCountThisRound = SectorCount;
  2170. if (SectorCountThisRound > ATA_MAX_LBA28_SECTOR_COUNT) {
  2171. SectorCountThisRound = ATA_MAX_LBA28_SECTOR_COUNT;
  2172. }
  2173. ASSERT(SectorCountThisRound == (ULONG)SectorCountThisRound);
  2174. Status = AtapPioCommand(AtaDevice,
  2175. Command,
  2176. Lba48,
  2177. Write,
  2178. 0,
  2179. BlockAddress,
  2180. Buffer,
  2181. (ULONG)SectorCountThisRound,
  2182. 0,
  2183. CriticalMode);
  2184. if (!KSUCCESS(Status)) {
  2185. RtlDebugPrint("ATA: Failed IO: %x\n", Status);
  2186. goto ReadWriteSectorsPioEnd;
  2187. }
  2188. BlockAddress += SectorCountThisRound;
  2189. Buffer += SectorCountThisRound * ATA_SECTOR_SIZE;
  2190. SectorCount -= SectorCountThisRound;
  2191. }
  2192. ReadWriteSectorsPioEnd:
  2193. return Status;
  2194. }
  2195. KSTATUS
  2196. AtapPioCommand (
  2197. PATA_CHILD Device,
  2198. ATA_COMMAND Command,
  2199. BOOL Lba48,
  2200. BOOL Write,
  2201. ULONG Features,
  2202. ULONGLONG Lba,
  2203. PVOID Buffer,
  2204. ULONG SectorCount,
  2205. ULONG MultiCount,
  2206. BOOL CriticalMode
  2207. )
  2208. /*++
  2209. Routine Description:
  2210. This routine executes a data transfer using polled I/O.
  2211. Arguments:
  2212. Device - Supplies a pointer to the device to read from.
  2213. Command - Supplies the ATA command to execute.
  2214. Lba48 - Supplies a boolean indicating if LBA48 mode is in use.
  2215. Write - Supplies a boolean indicating if this is a read PIO command (FALSE)
  2216. or a write data PIO command (TRUE).
  2217. Features - Supplies the contents of the feature register.
  2218. Lba - Supplies the logical block address to read from.
  2219. Buffer - Supplies a pointer to the buffer where the data will be returned.
  2220. SectorCount - Supplies the sector count to program in to the command.
  2221. The IDENTIFY and PACKET IDENTIFY commands have a known sector count of
  2222. one, zero should be passed in for those.
  2223. MultiCount - Supplies the actual number of sectors.
  2224. CriticalMode - Supplies a boolean indicating if this I/O operation is in
  2225. a critical code path (TRUE), such as a crash dump I/O request, or in
  2226. the default code path.
  2227. Return Value:
  2228. STATUS_SUCCESS on success.
  2229. STATUS_DEVICE_IO_ERROR if the device is unresponsive or has a failure.
  2230. --*/
  2231. {
  2232. ULONG BusMasterStatus;
  2233. ULONG ByteCount;
  2234. ULONG BytesTransferred;
  2235. PATA_CHANNEL Channel;
  2236. PUSHORT CurrentBuffer;
  2237. UCHAR DeviceStatus;
  2238. RUNLEVEL OldRunLevel;
  2239. PATA_QUERY_TIME_COUNTER QueryTimeCounter;
  2240. KSTATUS Status;
  2241. ULONGLONG Timeout;
  2242. ASSERT(SectorCount <= ATA_MAX_LBA28_SECTOR_COUNT);
  2243. CurrentBuffer = (PUSHORT)Buffer;
  2244. Channel = Device->Channel;
  2245. //
  2246. // Lock the other device out.
  2247. //
  2248. QueryTimeCounter = ATA_GET_TIME_FUNCTION(CriticalMode);
  2249. OldRunLevel = RunLevelCount;
  2250. if (CriticalMode == FALSE) {
  2251. KeAcquireQueuedLock(Channel->Lock);
  2252. OldRunLevel = KeRaiseRunLevel(RunLevelDispatch);
  2253. KeAcquireSpinLock(&(Device->Controller->DpcLock));
  2254. }
  2255. //
  2256. // Clear the error bit of the bus master status.
  2257. //
  2258. if (Channel->BusMasterBase != -1) {
  2259. AtapWriteRegister(Channel,
  2260. AtaRegisterBusMasterStatus,
  2261. IDE_STATUS_ERROR);
  2262. }
  2263. //
  2264. // Select the device.
  2265. //
  2266. Status = AtapSelectDevice(Device, CriticalMode);
  2267. if (!KSUCCESS(Status)) {
  2268. goto PioCommandEnd;
  2269. }
  2270. //
  2271. // Set up all registers of the command except the command register itself.
  2272. //
  2273. AtapSetupCommand(Device,
  2274. Lba48,
  2275. Features,
  2276. SectorCount,
  2277. Lba,
  2278. 0);
  2279. //
  2280. // Disable interrupts.
  2281. //
  2282. AtapWriteRegister(Channel,
  2283. AtaRegisterControl,
  2284. ATA_CONTROL_INTERRUPT_DISABLE);
  2285. if ((Command == AtaCommandIdentify) ||
  2286. (Command == AtaCommandIdentifyPacket)) {
  2287. SectorCount = 1;
  2288. }
  2289. //
  2290. // Execute the command.
  2291. //
  2292. AtapWriteRegister(Channel, AtaRegisterCommand, (UCHAR)Command);
  2293. AtapStall(Channel);
  2294. //
  2295. // This is the main read loop. The primary status register must not be read
  2296. // more than once for each sector transferred, as reading the status
  2297. // register clears the IRQ status. The alternate status register can be
  2298. // read any number of times.
  2299. //
  2300. Timeout = QueryTimeCounter() +
  2301. (HlQueryTimeCounterFrequency() * ATA_TIMEOUT);
  2302. while (SectorCount != 0) {
  2303. //
  2304. // Read the status register once.
  2305. //
  2306. DeviceStatus = AtapReadRegister(Channel, AtaRegisterStatus);
  2307. if ((Command == AtaCommandIdentify) && (DeviceStatus == 0)) {
  2308. Status = STATUS_NO_SUCH_DEVICE;
  2309. goto PioCommandEnd;
  2310. }
  2311. //
  2312. // Fail if an error occurred.
  2313. //
  2314. if ((DeviceStatus & ATA_STATUS_ERROR_MASK) != 0) {
  2315. Status = STATUS_DEVICE_IO_ERROR;
  2316. goto PioCommandEnd;
  2317. }
  2318. if (((DeviceStatus & ATA_STATUS_BUSY) != 0) ||
  2319. ((DeviceStatus & ATA_STATUS_DATA_REQUEST) == 0)) {
  2320. if (QueryTimeCounter() > Timeout) {
  2321. Status = STATUS_TIMEOUT;
  2322. goto PioCommandEnd;
  2323. }
  2324. continue;
  2325. }
  2326. //
  2327. // If the device is ready, read or write the data.
  2328. //
  2329. if ((DeviceStatus & ATA_STATUS_BUSY_MASK) == ATA_STATUS_DATA_REQUEST) {
  2330. ByteCount = ATA_SECTOR_SIZE;
  2331. if (MultiCount != 0) {
  2332. ByteCount = MultiCount * ATA_SECTOR_SIZE;
  2333. }
  2334. if (Write != FALSE) {
  2335. for (BytesTransferred = 0;
  2336. BytesTransferred < ByteCount;
  2337. BytesTransferred += sizeof(USHORT)) {
  2338. HlIoPortOutShort(Channel->IoBase + AtaRegisterData,
  2339. *CurrentBuffer);
  2340. CurrentBuffer += 1;
  2341. }
  2342. } else {
  2343. for (BytesTransferred = 0;
  2344. BytesTransferred < ByteCount;
  2345. BytesTransferred += sizeof(USHORT)) {
  2346. *CurrentBuffer =
  2347. HlIoPortInShort(Channel->IoBase + AtaRegisterData);
  2348. CurrentBuffer += 1;
  2349. }
  2350. }
  2351. //
  2352. // Stall to give the device a chance to settle.
  2353. //
  2354. AtapStall(Channel);
  2355. if (MultiCount != 0) {
  2356. ASSERT(SectorCount >= MultiCount);
  2357. SectorCount -= MultiCount;
  2358. } else {
  2359. SectorCount -= 1;
  2360. }
  2361. }
  2362. //
  2363. // If this was the last sector, read the status register one more time.
  2364. // If the error bits or data request is set, fail.
  2365. //
  2366. if (SectorCount == 0) {
  2367. DeviceStatus = AtapReadRegister(Channel, AtaRegisterStatus);
  2368. DeviceStatus &= ATA_STATUS_ERROR_MASK | ATA_STATUS_DATA_REQUEST;
  2369. if (DeviceStatus != 0) {
  2370. Status = STATUS_DEVICE_IO_ERROR;
  2371. goto PioCommandEnd;
  2372. }
  2373. }
  2374. }
  2375. //
  2376. // Check the bus master status register.
  2377. //
  2378. if (Channel->BusMasterBase != -1) {
  2379. BusMasterStatus = AtapReadRegister(Channel, AtaRegisterBusMasterStatus);
  2380. if ((BusMasterStatus & IDE_STATUS_ERROR) != 0) {
  2381. Status = STATUS_DEVICE_IO_ERROR;
  2382. goto PioCommandEnd;
  2383. }
  2384. }
  2385. //
  2386. // Send a clean cache command if this was a polled I/O write.
  2387. //
  2388. Status = STATUS_SUCCESS;
  2389. if (Write != FALSE) {
  2390. Status = AtapExecuteCacheFlush(Device, CriticalMode);
  2391. }
  2392. PioCommandEnd:
  2393. if (CriticalMode == FALSE) {
  2394. KeReleaseSpinLock(&(Device->Controller->DpcLock));
  2395. KeLowerRunLevel(OldRunLevel);
  2396. KeReleaseQueuedLock(Channel->Lock);
  2397. }
  2398. return Status;
  2399. }
  2400. KSTATUS
  2401. AtapExecuteCacheFlush (
  2402. PATA_CHILD Child,
  2403. BOOL CriticalMode
  2404. )
  2405. /*++
  2406. Routine Description:
  2407. This routine sends a cache flush command to the device. This routine
  2408. assumes the lock is held and the device is selected.
  2409. Arguments:
  2410. Child - Supplies a pointer to the ATA child device.
  2411. CriticalMode - Supplies a boolean indicating that the operation is
  2412. operating in hostile conditions.
  2413. Return Value:
  2414. Status code.
  2415. --*/
  2416. {
  2417. PATA_CHANNEL Channel;
  2418. ATA_COMMAND Command;
  2419. PATA_QUERY_TIME_COUNTER QueryTimeCounter;
  2420. KSTATUS Status;
  2421. UCHAR StatusRegister;
  2422. ULONGLONG Timeout;
  2423. Channel = Child->Channel;
  2424. Command = AtaCommandCacheFlush28;
  2425. QueryTimeCounter = ATA_GET_TIME_FUNCTION(CriticalMode);
  2426. Timeout = QueryTimeCounter() +
  2427. (HlQueryTimeCounterFrequency() * ATA_TIMEOUT);
  2428. Status = STATUS_SUCCESS;
  2429. AtapWriteRegister(Channel, AtaRegisterCommand, Command);
  2430. AtapStall(Channel);
  2431. while (TRUE) {
  2432. StatusRegister = AtapReadRegister(Channel, AtaRegisterStatus);
  2433. if ((StatusRegister & ATA_STATUS_ERROR_MASK) != 0) {
  2434. Status = STATUS_DEVICE_IO_ERROR;
  2435. break;
  2436. }
  2437. if ((StatusRegister & ATA_STATUS_BUSY_MASK) == 0) {
  2438. break;
  2439. }
  2440. if (QueryTimeCounter() > Timeout) {
  2441. Status = STATUS_TIMEOUT;
  2442. break;
  2443. }
  2444. }
  2445. if (!KSUCCESS(Status)) {
  2446. RtlDebugPrint("ATA_CHILD 0x%x failed cache flush: %d\n", Child, Status);
  2447. }
  2448. return Status;
  2449. }
  2450. KSTATUS
  2451. AtapSelectDevice (
  2452. PATA_CHILD Device,
  2453. BOOL CriticalMode
  2454. )
  2455. /*++
  2456. Routine Description:
  2457. This routine selects the given ATA device in the hardware.
  2458. Arguments:
  2459. Device - Supplies a pointer to the device to select. The interface needs to
  2460. be valid.
  2461. CriticalMode - Supplies a boolean indicating if this I/O operation is in
  2462. a critical code path (TRUE), such as a crash dump I/O request, or in
  2463. the default code path.
  2464. Return Value:
  2465. Status code.
  2466. --*/
  2467. {
  2468. PATA_CHANNEL Channel;
  2469. UCHAR DeviceStatus;
  2470. PATA_QUERY_TIME_COUNTER QueryTimeCounter;
  2471. ULONGLONG Timeout;
  2472. ULONGLONG TimeoutDuration;
  2473. Channel = Device->Channel;
  2474. if (Channel->SelectedDevice == Device->Slave) {
  2475. return STATUS_SUCCESS;
  2476. }
  2477. //
  2478. // Clear the selected device in case this selection fails.
  2479. //
  2480. Channel->SelectedDevice = 0xFF;
  2481. //
  2482. // Get the appropriate time counter routine. The recent time counter
  2483. // requests do not work in critical mode, as interrupts are likely disabled.
  2484. //
  2485. if (CriticalMode != FALSE) {
  2486. QueryTimeCounter = HlQueryTimeCounter;
  2487. } else {
  2488. QueryTimeCounter = KeGetRecentTimeCounter;
  2489. }
  2490. TimeoutDuration = KeConvertMicrosecondsToTimeTicks(ATA_SELECT_TIMEOUT);
  2491. Timeout = QueryTimeCounter() + TimeoutDuration;
  2492. //
  2493. // Wait until whichever drive is currently selected to become not busy.
  2494. //
  2495. do {
  2496. DeviceStatus = AtapReadRegister(Channel, AtaRegisterStatus);
  2497. if ((DeviceStatus & ATA_STATUS_BUSY) == 0) {
  2498. break;
  2499. }
  2500. } while (QueryTimeCounter() <= Timeout);
  2501. if ((DeviceStatus & ATA_STATUS_BUSY) != 0) {
  2502. return STATUS_TIMEOUT;
  2503. }
  2504. //
  2505. // Select the device.
  2506. //
  2507. AtapWriteRegister(Channel, AtaRegisterDeviceSelect, Device->Slave);
  2508. //
  2509. // Wait for the device to become ready.
  2510. //
  2511. do {
  2512. DeviceStatus = AtapReadRegister(Channel, AtaRegisterStatus);
  2513. if (((DeviceStatus & ATA_STATUS_BUSY_MASK) == 0) &&
  2514. ((DeviceStatus & ATA_STATUS_DRIVE_READY) != 0)) {
  2515. break;
  2516. }
  2517. if ((DeviceStatus & ATA_STATUS_ERROR_MASK) != 0) {
  2518. return STATUS_DEVICE_IO_ERROR;
  2519. }
  2520. } while (QueryTimeCounter() <= Timeout);
  2521. if (((DeviceStatus & ATA_STATUS_BUSY_MASK) != 0) ||
  2522. ((DeviceStatus & ATA_STATUS_DRIVE_READY) == 0)) {
  2523. return STATUS_TIMEOUT;
  2524. }
  2525. Channel->SelectedDevice = Device->Slave;
  2526. return STATUS_SUCCESS;
  2527. }
  2528. VOID
  2529. AtapSetupCommand (
  2530. PATA_CHILD Device,
  2531. BOOL Lba48,
  2532. ULONG FeaturesRegister,
  2533. ULONG SectorCountRegister,
  2534. ULONGLONG Lba,
  2535. ULONG DeviceControl
  2536. )
  2537. /*++
  2538. Routine Description:
  2539. This routine writes all registers to the ATA interface, preparing it to
  2540. execute a command. It does not write the command register, so the command
  2541. is not executed.
  2542. Arguments:
  2543. Device - Supplies a pointer to the device.
  2544. Lba48 - Supplies a boolean indicating if LBA48 mode is to be used.
  2545. FeaturesRegister - Supplies the features register to write in.
  2546. SectorCountRegister - Supplies the sector count register value to write.
  2547. Lba - Supplies the logical block address value to write in the registers.
  2548. DeviceControl - Supplies the device control value to write.
  2549. Return Value:
  2550. None.
  2551. --*/
  2552. {
  2553. PATA_CHANNEL Channel;
  2554. UCHAR DeviceSelect;
  2555. Channel = Device->Channel;
  2556. DeviceSelect = Device->Slave | ATA_DRIVE_SELECT_LBA;
  2557. //
  2558. // Device control is written the same way in all cases. All other registers
  2559. // are written slightly differently depending on the LBA mode.
  2560. //
  2561. AtapWriteRegister(Channel, AtaRegisterControl, DeviceControl);
  2562. //
  2563. // Write LBA48 mode.
  2564. //
  2565. if (Lba48 != FALSE) {
  2566. //
  2567. // Gain access to the high order bytes. The register access functions
  2568. // will also do this when writing to registers like LBA3, etc, but
  2569. // doing this directly allows these registers to be written in a batch.
  2570. //
  2571. AtapWriteRegister(Channel,
  2572. AtaRegisterControl,
  2573. ATA_CONTROL_HIGH_ORDER | Channel->InterruptDisable);
  2574. AtapWriteRegister(Channel,
  2575. AtaRegisterSectorCountLow,
  2576. (UCHAR)(SectorCountRegister >> 8));
  2577. AtapWriteRegister(Channel,
  2578. AtaRegisterLba0,
  2579. (UCHAR)(Lba >> 24));
  2580. AtapWriteRegister(Channel,
  2581. AtaRegisterLba1,
  2582. (UCHAR)(Lba >> 32));
  2583. AtapWriteRegister(Channel,
  2584. AtaRegisterLba2,
  2585. (UCHAR)(Lba >> 40));
  2586. //
  2587. // Back to the low registers.
  2588. //
  2589. AtapWriteRegister(Channel,
  2590. AtaRegisterControl,
  2591. Channel->InterruptDisable);
  2592. //
  2593. // Use LBA28 mode.
  2594. //
  2595. } else {
  2596. DeviceSelect |= (UCHAR)((Lba >> 24) & 0x0F);
  2597. }
  2598. AtapWriteRegister(Channel, AtaRegisterFeatures, FeaturesRegister);
  2599. AtapWriteRegister(Channel,
  2600. AtaRegisterSectorCountLow,
  2601. (UCHAR)SectorCountRegister);
  2602. AtapWriteRegister(Channel,
  2603. AtaRegisterLba0,
  2604. (UCHAR)(Lba & 0xFF));
  2605. AtapWriteRegister(Channel,
  2606. AtaRegisterLba1,
  2607. (UCHAR)(Lba >> 8));
  2608. AtapWriteRegister(Channel,
  2609. AtaRegisterLba2,
  2610. (UCHAR)(Lba >> 16));
  2611. AtapWriteRegister(Channel,
  2612. AtaRegisterDeviceSelect,
  2613. DeviceSelect);
  2614. return;
  2615. }
  2616. VOID
  2617. AtapStall (
  2618. PATA_CHANNEL Channel
  2619. )
  2620. /*++
  2621. Routine Description:
  2622. This routine stalls to give the ATA device time to settle.
  2623. Arguments:
  2624. Channel - Supplies a pointer to the channel.
  2625. Return Value:
  2626. None.
  2627. --*/
  2628. {
  2629. AtapReadRegister(Channel, AtaRegisterAlternateStatus);
  2630. AtapReadRegister(Channel, AtaRegisterAlternateStatus);
  2631. AtapReadRegister(Channel, AtaRegisterAlternateStatus);
  2632. AtapReadRegister(Channel, AtaRegisterAlternateStatus);
  2633. return;
  2634. }
  2635. UCHAR
  2636. AtapReadRegister (
  2637. PATA_CHANNEL Channel,
  2638. ATA_REGISTER Register
  2639. )
  2640. /*++
  2641. Routine Description:
  2642. This routine reads an ATA register.
  2643. Arguments:
  2644. Channel - Supplies a pointer to the channel information.
  2645. Register - Supplies the register to read.
  2646. Return Value:
  2647. Returns the value at the given register.
  2648. --*/
  2649. {
  2650. UCHAR Result;
  2651. //
  2652. // If writing the high order bytes, flip into that mode.
  2653. //
  2654. if ((Register > AtaRegisterCommand) && (Register < AtaRegisterControl)) {
  2655. AtapWriteRegister(Channel,
  2656. AtaRegisterControl,
  2657. ATA_CONTROL_HIGH_ORDER | Channel->InterruptDisable);
  2658. }
  2659. if (Register < AtaRegisterSectorCountHigh) {
  2660. Result = HlIoPortInByte(Channel->IoBase + Register);
  2661. } else if (Register < AtaRegisterControl) {
  2662. Register -= ATA_HIGH_ADDRESSING_OFFSET;
  2663. Result = HlIoPortInByte(Channel->IoBase + Register);
  2664. } else if (Register < AtaRegisterBusMasterCommand) {
  2665. Register -= ATA_CONTROL_REGISTER_OFFSET;
  2666. Result = HlIoPortInByte(Channel->ControlBase + Register);
  2667. } else {
  2668. Register -= ATA_BUS_MASTER_REGISTER_OFFSET;
  2669. Result = HlIoPortInByte(Channel->BusMasterBase + Register);
  2670. }
  2671. if ((Register > AtaRegisterCommand) && (Register < AtaRegisterControl)) {
  2672. AtapWriteRegister(Channel,
  2673. AtaRegisterControl,
  2674. Channel->InterruptDisable);
  2675. }
  2676. return Result;
  2677. }
  2678. VOID
  2679. AtapWriteRegister (
  2680. PATA_CHANNEL Channel,
  2681. ATA_REGISTER Register,
  2682. UCHAR Value
  2683. )
  2684. /*++
  2685. Routine Description:
  2686. This routine writes an ATA register.
  2687. Arguments:
  2688. Channel - Supplies a pointer to the channel information.
  2689. Register - Supplies the register to write.
  2690. Value - Supplies the value to write.
  2691. Return Value:
  2692. None.
  2693. --*/
  2694. {
  2695. //
  2696. // If writing the high order bytes, flip into that mode.
  2697. //
  2698. if ((Register > AtaRegisterCommand) && (Register < AtaRegisterControl)) {
  2699. AtapWriteRegister(Channel,
  2700. AtaRegisterControl,
  2701. ATA_CONTROL_HIGH_ORDER | Channel->InterruptDisable);
  2702. }
  2703. if (Register < AtaRegisterSectorCountHigh) {
  2704. HlIoPortOutByte(Channel->IoBase + Register, Value);
  2705. } else if (Register < AtaRegisterControl) {
  2706. Register -= ATA_HIGH_ADDRESSING_OFFSET;
  2707. HlIoPortOutByte(Channel->IoBase + Register, Value);
  2708. } else if (Register < AtaRegisterBusMasterCommand) {
  2709. Register -= ATA_CONTROL_REGISTER_OFFSET;
  2710. HlIoPortOutByte(Channel->ControlBase + Register, Value);
  2711. } else {
  2712. Register -= ATA_BUS_MASTER_REGISTER_OFFSET;
  2713. HlIoPortOutByte(Channel->BusMasterBase + Register, Value);
  2714. }
  2715. if ((Register > AtaRegisterCommand) && (Register < AtaRegisterControl)) {
  2716. AtapWriteRegister(Channel,
  2717. AtaRegisterControl,
  2718. Channel->InterruptDisable);
  2719. }
  2720. return;
  2721. }
  2722. VOID
  2723. AtapProcessPciConfigInterfaceChangeNotification (
  2724. PVOID Context,
  2725. PDEVICE Device,
  2726. PVOID InterfaceBuffer,
  2727. ULONG InterfaceBufferSize,
  2728. BOOL Arrival
  2729. )
  2730. /*++
  2731. Routine Description:
  2732. This routine is called when a PCI configuration space access interface
  2733. changes in availability.
  2734. Arguments:
  2735. Context - Supplies the caller's context pointer, supplied when the caller
  2736. requested interface notifications.
  2737. Device - Supplies a pointer to the device exposing or deleting the
  2738. interface.
  2739. InterfaceBuffer - Supplies a pointer to the interface buffer of the
  2740. interface.
  2741. InterfaceBufferSize - Supplies the buffer size.
  2742. Arrival - Supplies TRUE if a new interface is arriving, or FALSE if an
  2743. interface is departing.
  2744. Return Value:
  2745. None.
  2746. --*/
  2747. {
  2748. PATA_CONTROLLER ControllerContext;
  2749. ControllerContext = (PATA_CONTROLLER)Context;
  2750. if (Arrival != FALSE) {
  2751. if (InterfaceBufferSize >= sizeof(INTERFACE_PCI_CONFIG_ACCESS)) {
  2752. ASSERT(ControllerContext->PciConfigInterfaceAvailable == FALSE);
  2753. RtlCopyMemory(&(ControllerContext->PciConfigInterface),
  2754. InterfaceBuffer,
  2755. sizeof(INTERFACE_PCI_CONFIG_ACCESS));
  2756. ControllerContext->PciConfigInterfaceAvailable = TRUE;
  2757. }
  2758. } else {
  2759. ControllerContext->PciConfigInterfaceAvailable = FALSE;
  2760. }
  2761. return;
  2762. }