Leaked source code of windows server 2003
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.

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