ata.c 92 KB

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