Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

797 lines
22 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: bm.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "pciidex.h"
  11. NTSTATUS
  12. BmSetupOnePage (
  13. IN PVOID PdoExtension,
  14. IN PVOID DataVirtualPageAddress,
  15. IN ULONG TransferByteCount,
  16. IN PMDL Mdl,
  17. IN BOOLEAN DataIn,
  18. IN PVOID RegionDescriptorTablePage
  19. );
  20. #ifdef ALLOC_PRAGMA
  21. #pragma alloc_text(PAGE, BusMasterInitialize)
  22. #pragma alloc_text(PAGE, BmQueryInterface)
  23. #pragma alloc_text(NONPAGE, BmSetup)
  24. #pragma alloc_text(NONPAGE, BmReceiveScatterGatherList)
  25. #pragma alloc_text(NONPAGE, BmRebuildScatterGatherList)
  26. #pragma alloc_text(NONPAGE, BmPrepareController)
  27. #pragma alloc_text(NONPAGE, BmSetupOnePage)
  28. #pragma alloc_text(NONPAGE, BmArm)
  29. #pragma alloc_text(NONPAGE, BmDisarm)
  30. #pragma alloc_text(NONPAGE, BmFlush)
  31. #pragma alloc_text(NONPAGE, BmStatus)
  32. #pragma alloc_text(NONPAGE, BmTimingSetup)
  33. #endif // ALLOC_PRAGMA
  34. NTSTATUS
  35. BusMasterInitialize (
  36. PCHANPDO_EXTENSION PdoExtension
  37. )
  38. {
  39. NTSTATUS status;
  40. ULONG numberOfMapRegisters;
  41. ULONG scatterListSize;
  42. BOOLEAN noBmRegister;
  43. PAGED_CODE();
  44. if (PdoExtension->ParentDeviceExtension->TranslatedBusMasterBaseAddress == NULL) {
  45. status = STATUS_INSUFFICIENT_RESOURCES;
  46. noBmRegister = TRUE;
  47. } else {
  48. if (PdoExtension->ChannelNumber == 0) {
  49. PdoExtension->BmRegister =
  50. PdoExtension->ParentDeviceExtension->TranslatedBusMasterBaseAddress;
  51. } else if (PdoExtension->ChannelNumber == 1) {
  52. PdoExtension->BmRegister =
  53. (PIDE_BUS_MASTER_REGISTERS)
  54. (((PUCHAR) PdoExtension->ParentDeviceExtension->TranslatedBusMasterBaseAddress) + 8);
  55. } else {
  56. ASSERT (FALSE);
  57. }
  58. if (READ_PORT_UCHAR (&PdoExtension->BmRegister->Status) & BUSMASTER_ZERO_BITS) {
  59. //
  60. // The must-be-zero bits are not zero
  61. //
  62. DebugPrint ((0, "BusMasterInitialize: bad busmaster status register value (0x%x). will never do busmastering ide\n"));
  63. PdoExtension->BmRegister = NULL;
  64. status = STATUS_INSUFFICIENT_RESOURCES;
  65. noBmRegister = TRUE;
  66. } else {
  67. status = STATUS_SUCCESS;
  68. noBmRegister = FALSE;
  69. }
  70. }
  71. //
  72. // Allocate Adapter Object
  73. //
  74. if (status == STATUS_SUCCESS) {
  75. DEVICE_DESCRIPTION deviceDescription;
  76. RtlZeroMemory(&deviceDescription, sizeof(deviceDescription));
  77. deviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
  78. deviceDescription.Master = TRUE;
  79. deviceDescription.ScatterGather = TRUE;
  80. deviceDescription.DemandMode = FALSE;
  81. deviceDescription.AutoInitialize = FALSE;
  82. deviceDescription.Dma32BitAddresses = TRUE;
  83. deviceDescription.IgnoreCount = FALSE;
  84. deviceDescription.BusNumber = PdoExtension->ParentDeviceExtension->BmResourceList->List[0].BusNumber,
  85. deviceDescription.InterfaceType = PCIBus;
  86. //
  87. // make sure MAX_TRANSFER_SIZE_PER_SRB is never larger than what
  88. // the ide bus master controller can handle
  89. //
  90. ASSERT (MAX_TRANSFER_SIZE_PER_SRB <= (PAGE_SIZE * (PAGE_SIZE / sizeof(PHYSICAL_REGION_DESCRIPTOR))));
  91. deviceDescription.MaximumLength = MAX_TRANSFER_SIZE_PER_SRB;
  92. PdoExtension->DmaAdapterObject = IoGetDmaAdapter(
  93. PdoExtension->ParentDeviceExtension->AttacheePdo,
  94. &deviceDescription,
  95. &numberOfMapRegisters
  96. );
  97. ASSERT(PdoExtension->DmaAdapterObject);
  98. PdoExtension->MaximumPhysicalPages = numberOfMapRegisters;
  99. if (!PdoExtension->DmaAdapterObject) {
  100. status = STATUS_INSUFFICIENT_RESOURCES;
  101. }
  102. }
  103. if (status == STATUS_SUCCESS) {
  104. scatterListSize = PdoExtension->MaximumPhysicalPages *
  105. sizeof (PHYSICAL_REGION_DESCRIPTOR);
  106. PdoExtension->RegionDescriptorTable =
  107. PdoExtension->DmaAdapterObject->DmaOperations->AllocateCommonBuffer(
  108. PdoExtension->DmaAdapterObject,
  109. scatterListSize,
  110. &PdoExtension->PhysicalRegionDescriptorTable,
  111. FALSE
  112. );
  113. ASSERT (PdoExtension->RegionDescriptorTable);
  114. ASSERT (PdoExtension->PhysicalRegionDescriptorTable.QuadPart);
  115. if (PdoExtension->RegionDescriptorTable) {
  116. RtlZeroMemory (
  117. PdoExtension->RegionDescriptorTable,
  118. scatterListSize
  119. );
  120. } else {
  121. status = STATUS_INSUFFICIENT_RESOURCES;
  122. }
  123. }
  124. if (status != STATUS_SUCCESS) {
  125. //
  126. // free resources
  127. //
  128. if (PdoExtension->RegionDescriptorTable) {
  129. PdoExtension->DmaAdapterObject->DmaOperations->FreeCommonBuffer(
  130. PdoExtension->DmaAdapterObject,
  131. scatterListSize,
  132. PdoExtension->PhysicalRegionDescriptorTable,
  133. PdoExtension->RegionDescriptorTable,
  134. FALSE
  135. );
  136. PdoExtension->PhysicalRegionDescriptorTable.QuadPart = 0;
  137. PdoExtension->RegionDescriptorTable = NULL;
  138. }
  139. if (PdoExtension->DmaAdapterObject) {
  140. KIRQL currentIrql;
  141. KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
  142. PdoExtension->DmaAdapterObject->DmaOperations->PutDmaAdapter (
  143. PdoExtension->DmaAdapterObject
  144. );
  145. KeLowerIrql(currentIrql);
  146. PdoExtension->DmaAdapterObject = NULL;
  147. }
  148. }
  149. //
  150. // init. is still ok if we just not a bm controller
  151. //
  152. if (noBmRegister) {
  153. status = STATUS_SUCCESS;
  154. }
  155. return status;
  156. } // BusMasterInitialize
  157. NTSTATUS
  158. BusMasterUninitialize (
  159. PCHANPDO_EXTENSION PdoExtension
  160. )
  161. {
  162. ULONG scatterListSize;
  163. KIRQL currentIrql;
  164. ASSERT (PdoExtension->BmState == BmIdle);
  165. if (PdoExtension->DmaAdapterObject) {
  166. scatterListSize = PdoExtension->MaximumPhysicalPages *
  167. sizeof (PHYSICAL_REGION_DESCRIPTOR);
  168. if (PdoExtension->PhysicalRegionDescriptorTable.QuadPart) {
  169. PdoExtension->DmaAdapterObject->DmaOperations->FreeCommonBuffer(
  170. PdoExtension->DmaAdapterObject,
  171. scatterListSize,
  172. PdoExtension->PhysicalRegionDescriptorTable,
  173. PdoExtension->RegionDescriptorTable,
  174. FALSE
  175. );
  176. PdoExtension->RegionDescriptorTable = NULL;
  177. PdoExtension->PhysicalRegionDescriptorTable.QuadPart = 0;
  178. }
  179. KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
  180. PdoExtension->DmaAdapterObject->DmaOperations->PutDmaAdapter (
  181. PdoExtension->DmaAdapterObject
  182. );
  183. KeLowerIrql(currentIrql);
  184. PdoExtension->DmaAdapterObject = NULL;
  185. }
  186. return STATUS_SUCCESS;
  187. }
  188. NTSTATUS
  189. BmSetup (
  190. IN PVOID PdoExtension,
  191. IN PVOID DataVirtualAddress,
  192. IN ULONG TransferByteCount,
  193. IN PMDL Mdl,
  194. IN BOOLEAN DataIn,
  195. IN VOID (* BmCallback) (PVOID Context),
  196. IN PVOID CallbackContext
  197. )
  198. {
  199. PCHANPDO_EXTENSION pdoExtension = PdoExtension;
  200. NTSTATUS status;
  201. PIDE_BUS_MASTER_REGISTERS bmRegister;
  202. ASSERT (pdoExtension->BmState == BmIdle);
  203. bmRegister = pdoExtension->BmRegister;
  204. pdoExtension->DataVirtualAddress = DataVirtualAddress;
  205. pdoExtension->TransferLength = TransferByteCount;
  206. pdoExtension->Mdl = Mdl;
  207. pdoExtension->DataIn = DataIn;
  208. pdoExtension->BmCallback = BmCallback;
  209. pdoExtension->BmCallbackContext = CallbackContext;
  210. status = (*pdoExtension->DmaAdapterObject->DmaOperations->GetScatterGatherList)(
  211. pdoExtension->DmaAdapterObject,
  212. pdoExtension->DeviceObject,
  213. pdoExtension->Mdl,
  214. pdoExtension->DataVirtualAddress,
  215. pdoExtension->TransferLength,
  216. BmReceiveScatterGatherList,
  217. pdoExtension,
  218. (BOOLEAN) !pdoExtension->DataIn
  219. );
  220. return status;
  221. } // BmSetup
  222. VOID
  223. BmReceiveScatterGatherList(
  224. IN PDEVICE_OBJECT DeviceObject,
  225. IN PIRP Irp,
  226. IN PSCATTER_GATHER_LIST ScatterGather,
  227. IN PVOID Context
  228. )
  229. {
  230. PCHANPDO_EXTENSION pdoExtension = Context;
  231. ASSERT (pdoExtension);
  232. BmRebuildScatterGatherList (pdoExtension, ScatterGather);
  233. BmPrepareController (pdoExtension);
  234. //
  235. // Call the FDO back
  236. //
  237. pdoExtension->BmCallback (pdoExtension->BmCallbackContext);
  238. return;
  239. } // BmReceiveScatterGatherList
  240. VOID
  241. BmRebuildScatterGatherList(
  242. IN PCHANPDO_EXTENSION PdoExtension,
  243. IN PSCATTER_GATHER_LIST ScatterGather
  244. )
  245. {
  246. ULONG bytesToMap;
  247. ULONG i, j;
  248. ASSERT (ScatterGather);
  249. ASSERT (PdoExtension);
  250. ASSERT (PdoExtension->TransferLength);
  251. ASSERT (PdoExtension->Mdl);
  252. DebugPrint ((3, "PciIdeX: BmReceiveScatterGatherList() DataBuffer 0x%x, length 0x%x\n", PdoExtension->DataVirtualAddress, PdoExtension->TransferLength));
  253. //
  254. // save the original list
  255. //
  256. PdoExtension->HalScatterGatherList = ScatterGather;
  257. for (i=j=0; j<ScatterGather->NumberOfElements; j++) {
  258. ULONG physicalAddress;
  259. PSCATTER_GATHER_ELEMENT sgElements;
  260. sgElements = ScatterGather->Elements + j;
  261. //
  262. // get the next block physical address
  263. //
  264. physicalAddress = sgElements->Address.LowPart;
  265. ASSERT (!(physicalAddress & 0x1));
  266. ASSERT (!sgElements->Address.HighPart);
  267. //
  268. // get the next block byte size
  269. //
  270. bytesToMap = sgElements->Length;
  271. while (bytesToMap) {
  272. ULONG bytesLeftInCurrent64KPage;
  273. ASSERT (i < PdoExtension->MaximumPhysicalPages);
  274. PdoExtension->RegionDescriptorTable[i].PhysicalAddress = physicalAddress;
  275. bytesLeftInCurrent64KPage = 0x10000 - (physicalAddress & 0xffff);
  276. if (bytesLeftInCurrent64KPage < bytesToMap) {
  277. PdoExtension->RegionDescriptorTable[i].ByteCount = bytesLeftInCurrent64KPage;
  278. physicalAddress += bytesLeftInCurrent64KPage;
  279. bytesToMap -= bytesLeftInCurrent64KPage;
  280. } else if (bytesToMap <= 0x10000) {
  281. //
  282. // got a perfect page, map all of it
  283. //
  284. PdoExtension->RegionDescriptorTable[i].ByteCount = bytesToMap & 0xfffe;
  285. physicalAddress += bytesToMap & 0xfffe;
  286. bytesToMap = 0;
  287. } else {
  288. //
  289. // got a perfectly aligned 64k page, map all of it but the count
  290. // need to be 0
  291. //
  292. PdoExtension->RegionDescriptorTable[i].ByteCount = 0; // 64K
  293. physicalAddress += 0x10000;
  294. bytesToMap -= 0x10000;
  295. }
  296. PdoExtension->RegionDescriptorTable[i].EndOfTable = 0;
  297. i++;
  298. }
  299. }
  300. //
  301. // the bus master circutry need to know it hits the end of the PRDT
  302. //
  303. PdoExtension->RegionDescriptorTable[i - 1].EndOfTable = 1; // end of table
  304. return;
  305. } // BmReceiveScatterGatherList
  306. VOID
  307. BmPrepareController (
  308. PCHANPDO_EXTENSION PdoExtension
  309. )
  310. {
  311. PCHANPDO_EXTENSION pdoExtension = PdoExtension;
  312. PIDE_BUS_MASTER_REGISTERS bmRegister;
  313. KeFlushIoBuffers(pdoExtension->Mdl,
  314. (BOOLEAN) (pdoExtension->DataIn),
  315. TRUE);
  316. bmRegister = pdoExtension->BmRegister;
  317. //
  318. // Init bus master contoller, but keep it disabled
  319. //
  320. //
  321. // Disable Controller
  322. //
  323. WRITE_PORT_UCHAR (
  324. &bmRegister->Command,
  325. 0
  326. );
  327. //
  328. // Clear Errors
  329. //
  330. WRITE_PORT_UCHAR (
  331. &bmRegister->Status,
  332. BUSMASTER_INTERRUPT | BUSMASTER_ERROR
  333. );
  334. //
  335. // Init. Scatter Gather List Register
  336. //
  337. WRITE_PORT_ULONG (
  338. &bmRegister->DescriptionTable,
  339. PdoExtension->PhysicalRegionDescriptorTable.LowPart
  340. );
  341. pdoExtension->BmState = BmSet;
  342. return;
  343. } // BmPrepareController
  344. NTSTATUS
  345. BmSetupOnePage (
  346. IN PVOID PdoExtension,
  347. IN PVOID DataVirtualPageAddress,
  348. IN ULONG TransferByteCount,
  349. IN PMDL Mdl,
  350. IN BOOLEAN DataIn,
  351. IN PVOID RegionDescriptorTablePage
  352. )
  353. /*++
  354. Routine Description:
  355. Does the same thing as BmSetup except that it sets up DMA controller
  356. for one page only and therefore it simple and straightforward and
  357. does not use any of kernel services unlike BmSetup.
  358. Arguments:
  359. PdoExtension - context pointer
  360. DataVirtualPageAddress- address of IO page
  361. TransferByteCount - size of IO (IO region shall not cross page boundary)
  362. Mdl - MDL descriptor containing DataVirtualAddress
  363. DataIn - TRUE if input, FALSE if output
  364. RegionDescriptorTable - memory to store 1 entry of RegionDescriptor (shall be page-aligned)
  365. Attention! Obviousely, it's caller responsibility to retain the values addressed
  366. by DataMemoryAddress and RegionDescriptor table until completion of DMA transfer
  367. Return Value:
  368. STATUS_SUCCESS if all conditions listed above were met,
  369. STATUS_UNSUCCESSFUL otherwise
  370. Environment:
  371. Kernel mode. Currently used by only by ATAPI during hibernation.
  372. --*/
  373. {
  374. PCHANPDO_EXTENSION pdoExtension = PdoExtension;
  375. PPHYSICAL_REGION_DESCRIPTOR RegionDescriptorTable = RegionDescriptorTablePage;
  376. PHYSICAL_ADDRESS OldPhysicalRegionDescriptorTable;
  377. PPHYSICAL_REGION_DESCRIPTOR OldRegionDescriptorTable;
  378. PHYSICAL_ADDRESS DataPhysicalPageAddress;
  379. ULONG Size;
  380. //
  381. // Check alignment of addresses and transfer size
  382. //
  383. Size = PAGE_SIZE - ((ULONG) (((ULONG_PTR) DataVirtualPageAddress) & (PAGE_SIZE-1)));
  384. if (
  385. TransferByteCount == 0 ||
  386. TransferByteCount > Size ||
  387. ((ULONG) ((ULONG_PTR)DataVirtualPageAddress | TransferByteCount) & 3) != 0 ||
  388. ((ULONG) (((ULONG_PTR)RegionDescriptorTablePage) & (PAGE_SIZE-1)))
  389. )
  390. {
  391. // Necessary requirements was not met, failure
  392. return (STATUS_UNSUCCESSFUL);
  393. }
  394. //
  395. // Initialize descriptor table
  396. //
  397. DataPhysicalPageAddress =(*pdoExtension->DmaAdapterObject->DmaOperations->MapTransfer)(
  398. (pdoExtension->DmaAdapterObject),
  399. Mdl,
  400. pdoExtension->MapRegisterBase,
  401. DataVirtualPageAddress,
  402. &TransferByteCount,
  403. !DataIn
  404. );
  405. //DataPhysicalPageAddress = MmGetPhysicalAddress (DataVirtualPageAddress);
  406. RegionDescriptorTable[0].PhysicalAddress = DataPhysicalPageAddress.LowPart;
  407. RegionDescriptorTable[0].ByteCount = TransferByteCount;
  408. RegionDescriptorTable[0].EndOfTable = 1;
  409. //
  410. // Preserve existing data table from context
  411. //
  412. OldPhysicalRegionDescriptorTable = pdoExtension->PhysicalRegionDescriptorTable;
  413. OldRegionDescriptorTable = pdoExtension->RegionDescriptorTable;
  414. //
  415. // Set up IO request parameters
  416. //
  417. pdoExtension->PhysicalRegionDescriptorTable = MmGetPhysicalAddress (RegionDescriptorTable);
  418. pdoExtension->RegionDescriptorTable = RegionDescriptorTable;
  419. pdoExtension->Mdl = Mdl;
  420. pdoExtension->DataIn = DataIn;
  421. //
  422. // Setup controller
  423. //
  424. BmPrepareController (pdoExtension);
  425. //
  426. // Restore original table values
  427. //
  428. pdoExtension->PhysicalRegionDescriptorTable = OldPhysicalRegionDescriptorTable;
  429. pdoExtension->RegionDescriptorTable = OldRegionDescriptorTable;
  430. //
  431. // Done
  432. //
  433. return (STATUS_SUCCESS);
  434. }
  435. NTSTATUS
  436. BmArm (
  437. IN PVOID PdoExtension
  438. )
  439. {
  440. PCHANPDO_EXTENSION pdoExtension = PdoExtension;
  441. PIDE_BUS_MASTER_REGISTERS bmRegister;
  442. UCHAR bmStatus;
  443. ASSERT ((pdoExtension->BmState == BmSet) || (pdoExtension->BmState == BmDisarmed));
  444. bmRegister = pdoExtension->BmRegister;
  445. // if (Device == 0)
  446. // bmStatus = BUSMASTER_DEVICE0_DMA_OK;
  447. // else
  448. // bmStatus = BUSMASTER_DEVICE1_DMA_OK;
  449. //
  450. // clear the status bit
  451. //
  452. bmStatus = BUSMASTER_INTERRUPT | BUSMASTER_ERROR;
  453. WRITE_PORT_UCHAR (&bmRegister->Status, bmStatus);
  454. //
  455. // on your mark...get set...go!!
  456. //
  457. #if !defined (FAKE_BAD_IDE_DMA_DEVICE)
  458. if (pdoExtension->DataIn) {
  459. WRITE_PORT_UCHAR (&bmRegister->Command, 0x09); // enable BM read
  460. } else {
  461. WRITE_PORT_UCHAR (&bmRegister->Command, 0x01); // enable BM write
  462. }
  463. #endif // !FAKE_BAD_IDE_DMA_DEVICE
  464. pdoExtension->BmState = BmArmed;
  465. DebugPrint ((3, "PciIde: BmArm()\n"));
  466. return STATUS_SUCCESS;
  467. } // BmArm
  468. BMSTATUS
  469. BmDisarm (
  470. IN PVOID PdoExtension
  471. )
  472. {
  473. PCHANPDO_EXTENSION pdoExtension = PdoExtension;
  474. PIDE_BUS_MASTER_REGISTERS bmRegister = pdoExtension->BmRegister;
  475. BMSTATUS bmStatus;
  476. bmStatus = BmStatus (PdoExtension);
  477. WRITE_PORT_UCHAR (&bmRegister->Command, 0x0); // disable BM
  478. WRITE_PORT_UCHAR (&bmRegister->Status, BUSMASTER_INTERRUPT); // clear interrupt BM
  479. if (pdoExtension->BmState != BmIdle) {
  480. pdoExtension->BmState = BmDisarmed;
  481. }
  482. if (bmStatus) {
  483. DebugPrint ((1, "PciIdeX: BM 0x%x status = 0x%x\n", bmRegister, bmStatus));
  484. }
  485. return bmStatus;
  486. } // BmDisarm
  487. BMSTATUS
  488. BmFlush (
  489. IN PVOID PdoExtension
  490. )
  491. {
  492. PCHANPDO_EXTENSION pdoExtension = PdoExtension;
  493. ASSERT (pdoExtension->BmState != BmArmed);
  494. (*pdoExtension->DmaAdapterObject->DmaOperations->PutScatterGatherList)(
  495. pdoExtension->DmaAdapterObject,
  496. pdoExtension->HalScatterGatherList,
  497. (BOOLEAN)(!pdoExtension->DataIn));
  498. pdoExtension->HalScatterGatherList = NULL;
  499. pdoExtension->DataVirtualAddress = NULL;
  500. pdoExtension->TransferLength = 0;
  501. pdoExtension->Mdl = NULL;
  502. pdoExtension->BmState = BmIdle;
  503. DebugPrint ((3, "PciIde: BmFlush()\n"));
  504. return STATUS_SUCCESS;
  505. } // BmFlush
  506. BMSTATUS
  507. BmStatus (
  508. IN PVOID PdoExtension
  509. )
  510. {
  511. PCHANPDO_EXTENSION pdoExtension = PdoExtension;
  512. PIDE_BUS_MASTER_REGISTERS bmRegister;
  513. BMSTATUS bmStatus;
  514. UCHAR bmRawStatus;
  515. bmRegister = pdoExtension->BmRegister;
  516. bmRawStatus = READ_PORT_UCHAR (&bmRegister->Status);
  517. bmStatus = 0;
  518. //
  519. // if we get back 0xff from the port, then the decodes
  520. // are probably not enabled (or the device is powered down). return 0.
  521. //
  522. if (bmRawStatus == 0xff) {
  523. return bmStatus;
  524. }
  525. if (bmRawStatus & BUSMASTER_ACTIVE) {
  526. bmStatus |= BMSTATUS_NOT_REACH_END_OF_TRANSFER;
  527. }
  528. if (bmRawStatus & BUSMASTER_ERROR) {
  529. bmStatus |= BMSTATUS_ERROR_TRANSFER;
  530. }
  531. if (bmRawStatus & BUSMASTER_INTERRUPT) {
  532. bmStatus |= BMSTATUS_INTERRUPT;
  533. }
  534. return bmStatus;
  535. } // BmStatus
  536. NTSTATUS
  537. BmTimingSetup (
  538. IN PVOID PdoExtension
  539. )
  540. {
  541. return STATUS_SUCCESS;
  542. } // BmTimingSetup
  543. NTSTATUS
  544. BmCrashDumpInitialize (
  545. IN PVOID PdoExtension
  546. )
  547. {
  548. PCHANPDO_EXTENSION pdoExtension = PdoExtension;
  549. ULONG nMapRegisters = pdoExtension->MaximumPhysicalPages-1;
  550. if (pdoExtension->DmaAdapterObject != NULL) {
  551. pdoExtension->MapRegisterBase = HalAllocateCrashDumpRegisters((PADAPTER_OBJECT)pdoExtension->DmaAdapterObject,
  552. &nMapRegisters
  553. );
  554. }
  555. return STATUS_SUCCESS;
  556. }
  557. NTSTATUS
  558. BmQueryInterface (
  559. IN PCHANPDO_EXTENSION PdoExtension,
  560. IN OUT PPCIIDE_BUSMASTER_INTERFACE BusMasterInterface
  561. )
  562. {
  563. PCTRLFDO_EXTENSION fdoExtension = PdoExtension->ParentDeviceExtension;
  564. PAGED_CODE();
  565. if (PdoExtension->BmRegister) {
  566. BusMasterInterface->Size = sizeof(PCIIDE_BUSMASTER_INTERFACE);
  567. BusMasterInterface->SupportedTransferMode[0] =
  568. fdoExtension->ControllerProperties.SupportedTransferMode[PdoExtension->ChannelNumber][0];
  569. BusMasterInterface->SupportedTransferMode[1] =
  570. fdoExtension->ControllerProperties.SupportedTransferMode[PdoExtension->ChannelNumber][1];
  571. BusMasterInterface->MaxTransferByteSize = (PdoExtension->MaximumPhysicalPages - 1) * PAGE_SIZE;
  572. BusMasterInterface->Context = PdoExtension;
  573. BusMasterInterface->ContextSize = sizeof (*PdoExtension);
  574. BusMasterInterface->BmSetup = BmSetup;
  575. BusMasterInterface->BmArm = BmArm;
  576. BusMasterInterface->BmDisarm = BmDisarm;
  577. BusMasterInterface->BmFlush = BmFlush;
  578. BusMasterInterface->BmStatus = BmStatus;
  579. BusMasterInterface->BmTimingSetup = BmTimingSetup;
  580. BusMasterInterface->BmSetupOnePage= BmSetupOnePage;
  581. BusMasterInterface->BmCrashDumpInitialize= BmCrashDumpInitialize;
  582. BusMasterInterface->BmFlushAdapterBuffers= BmFlushAdapterBuffers;
  583. BusMasterInterface->IgnoreActiveBitForAtaDevice =
  584. fdoExtension->ControllerProperties.IgnoreActiveBitForAtaDevice;
  585. BusMasterInterface->AlwaysClearBusMasterInterrupt =
  586. (fdoExtension->ControllerProperties.AlwaysClearBusMasterInterrupt ||
  587. IsNativeMode(fdoExtension));
  588. return STATUS_SUCCESS;
  589. } else {
  590. return STATUS_NOT_IMPLEMENTED;
  591. }
  592. } // BmQueryInterface
  593. NTSTATUS
  594. BmFlushAdapterBuffers (
  595. IN PVOID PdoExtension,
  596. IN PVOID DataVirtualPageAddress,
  597. IN ULONG TransferByteCount,
  598. IN PMDL Mdl,
  599. IN BOOLEAN DataIn
  600. )
  601. /*++
  602. --*/
  603. {
  604. PCHANPDO_EXTENSION pdoExtension = PdoExtension;
  605. ASSERT (pdoExtension->BmState != BmArmed);
  606. (pdoExtension->DmaAdapterObject->DmaOperations->FlushAdapterBuffers)(
  607. (pdoExtension->DmaAdapterObject),
  608. Mdl,
  609. pdoExtension->MapRegisterBase,
  610. DataVirtualPageAddress,
  611. TransferByteCount,
  612. !DataIn
  613. );
  614. pdoExtension->BmState = BmIdle;
  615. return STATUS_SUCCESS;
  616. }