Windows NT 4.0 source code leak
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.

1344 lines
35 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. ixmcasup.c
  5. Abstract:
  6. This module contains the IoXxx routines for the NT I/O system that
  7. are hardware dependent. Were these routines not hardware dependent,
  8. they would reside in the iosubs.c module.
  9. Author:
  10. Darryl E. Havens (darrylh) 11-Apr-1990
  11. Environment:
  12. Kernel mode
  13. Revision History:
  14. Modified for MCA support - Bill Parry (o-billp) 22-Jul-1991
  15. --*/
  16. #define MCA 1
  17. #include "halp.h"
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text(PAGE,HalGetAdapter)
  20. #endif
  21. //
  22. // The HalpNewAdapter event is used to serialize allocations
  23. // of new adapter objects, additions to the HalpMCAAdapter
  24. // array, and some global values (MasterAdapterObject) and some
  25. // adapter fields modified by HalpGrowMapBuffers.
  26. // (AdapterObject->NumberOfMapRegisters is assumed not to be
  27. // growable while this even is held)
  28. //
  29. // Note: We don't really need our own an event object for this.
  30. //
  31. #define HalpNewAdapter HalpBusDatabaseEvent
  32. extern KEVENT HalpNewAdapter;
  33. //
  34. // Define save area for MCA adapter objects. Allocate 1 extra slot for
  35. // bus masters (MAX_DMA_CHANNEL_NUMBER is zero-based).
  36. //
  37. PADAPTER_OBJECT HalpMCAAdapter[MAX_MCA_DMA_CHANNEL_NUMBER + 1 + 1];
  38. VOID
  39. HalpCopyBufferMap(
  40. IN PMDL Mdl,
  41. IN PTRANSLATION_ENTRY TranslationEntry,
  42. IN PVOID CurrentVa,
  43. IN ULONG Length,
  44. IN BOOLEAN WriteToDevice
  45. );
  46. NTSTATUS
  47. HalAllocateAdapterChannel(
  48. IN PADAPTER_OBJECT AdapterObject,
  49. IN PWAIT_CONTEXT_BLOCK Wcb,
  50. IN ULONG NumberOfMapRegisters,
  51. IN PDRIVER_CONTROL ExecutionRoutine
  52. )
  53. /*++
  54. Routine Description:
  55. This routine allocates the adapter channel specified by the adapter object.
  56. This is accomplished by placing the device object of the driver that wants
  57. to allocate the adapter on the adapter's queue. If the queue is already
  58. "busy", then the adapter has already been allocated, so the device object
  59. is simply placed onto the queue and waits until the adapter becomes free.
  60. Once the adapter becomes free (or if it already is), then the driver's
  61. execution routine is invoked.
  62. Also, a number of map registers may be allocated to the driver by specifying
  63. a non-zero value for NumberOfMapRegisters. Then the map register must be
  64. allocated from the master adapter. Once there are a sufficient number of
  65. map registers available, then the execution routine is called and the
  66. base address of the allocated map registers in the adapter is also passed
  67. to the driver's execution routine.
  68. Arguments:
  69. AdapterObject - Pointer to the adapter control object to allocate to the
  70. driver.
  71. Wcb - Supplies a wait context block for saving the allocation parameters.
  72. The DeviceObject, CurrentIrp and DeviceContext should be initalized.
  73. NumberOfMapRegisters - The number of map registers that are to be allocated
  74. from the channel, if any.
  75. ExecutionRoutine - The address of the driver's execution routine that is
  76. invoked once the adapter channel (and possibly map registers) have been
  77. allocated.
  78. Return Value:
  79. Returns STATUS_SUCESS unless too many map registers are requested.
  80. Notes:
  81. Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
  82. --*/
  83. {
  84. PADAPTER_OBJECT MasterAdapter;
  85. BOOLEAN Busy = FALSE;
  86. IO_ALLOCATION_ACTION Action;
  87. KIRQL Irql;
  88. LONG MapRegisterNumber;
  89. //
  90. // Begin by obtaining a pointer to the master adapter associated with this
  91. // request.
  92. //
  93. MasterAdapter = AdapterObject->MasterAdapter;
  94. //
  95. // Initialize the device object's wait context block in case this device
  96. // must wait before being able to allocate the adapter.
  97. //
  98. Wcb->DeviceRoutine = ExecutionRoutine;
  99. Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
  100. //
  101. // Allocate the adapter object for this particular device. If the
  102. // adapter cannot be allocated because it has already been allocated
  103. // to another device, then return to the caller now; otherwise,
  104. // continue.
  105. //
  106. if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
  107. &Wcb->WaitQueueEntry )) {
  108. //
  109. // Save the parameters in case there are not enough map registers.
  110. //
  111. AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
  112. AdapterObject->CurrentWcb = Wcb;
  113. //
  114. // The adapter was not busy so it has been allocated. Now check
  115. // to see whether this driver wishes to allocate any map registers.
  116. // Ensure that this adapter has enough total map registers
  117. // to satisfy the request.
  118. //
  119. if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
  120. //
  121. // Lock the map register bit map and the adapter queue in the
  122. // master adapter object. The channel structure offset is used as
  123. // a hint for the register search.
  124. //
  125. if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
  126. AdapterObject->NumberOfMapRegisters = 0;
  127. IoFreeAdapterChannel(AdapterObject);
  128. return(STATUS_INSUFFICIENT_RESOURCES);
  129. }
  130. Irql = KfAcquireSpinLock( &MasterAdapter->SpinLock );
  131. MapRegisterNumber = -1;
  132. if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
  133. MapRegisterNumber = RtlFindClearBitsAndSet(
  134. MasterAdapter->MapRegisters,
  135. NumberOfMapRegisters,
  136. 0
  137. );
  138. }
  139. if (MapRegisterNumber == -1) {
  140. //
  141. // There were not enough free map registers. Queue this request
  142. // on the master adapter where is will wait until some registers
  143. // are deallocated.
  144. //
  145. InsertTailList( &MasterAdapter->AdapterQueue,
  146. &AdapterObject->AdapterQueue
  147. );
  148. Busy = 1;
  149. } else {
  150. //
  151. // Calculate the map register base from the allocated map
  152. // register and base of the master adapter object.
  153. //
  154. AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
  155. MasterAdapter->MapRegisterBase + MapRegisterNumber);
  156. //
  157. // Set the no scatter/gather flag if scatter/gather not
  158. // supported.
  159. //
  160. if (!AdapterObject->ScatterGather) {
  161. AdapterObject->MapRegisterBase = (PVOID)
  162. ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
  163. }
  164. }
  165. KfReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
  166. } else {
  167. AdapterObject->MapRegisterBase = NULL;
  168. AdapterObject->NumberOfMapRegisters = 0;
  169. }
  170. //
  171. // If there were either enough map registers available or no map
  172. // registers needed to be allocated, invoke the driver's execution
  173. // routine now.
  174. //
  175. if (!Busy) {
  176. AdapterObject->CurrentWcb = Wcb;
  177. Action = ExecutionRoutine( Wcb->DeviceObject,
  178. Wcb->CurrentIrp,
  179. AdapterObject->MapRegisterBase,
  180. Wcb->DeviceContext );
  181. //
  182. // If the driver would like to have the adapter deallocated,
  183. // then release the adapter object.
  184. //
  185. if (Action == DeallocateObject) {
  186. IoFreeAdapterChannel( AdapterObject );
  187. } else if (Action == DeallocateObjectKeepRegisters) {
  188. //
  189. // Set the NumberOfMapRegisters = 0 in the adapter object.
  190. // This will keep IoFreeAdapterChannel from freeing the
  191. // registers. After this it is the driver's responsiblity to
  192. // keep track of the number of map registers.
  193. //
  194. AdapterObject->NumberOfMapRegisters = 0;
  195. IoFreeAdapterChannel(AdapterObject);
  196. }
  197. }
  198. }
  199. return(STATUS_SUCCESS);
  200. }
  201. PVOID
  202. HalAllocateCrashDumpRegisters(
  203. IN PADAPTER_OBJECT AdapterObject,
  204. IN PULONG NumberOfMapRegisters
  205. )
  206. /*++
  207. Routine Description:
  208. This routine is called during the crash dump disk driver's initialization
  209. to allocate a number map registers permanently.
  210. Arguments:
  211. AdapterObject - Pointer to the adapter control object to allocate to the
  212. driver.
  213. NumberOfMapRegisters - Input the number of registers requests and output
  214. the number allocated.
  215. Return Value:
  216. Returns STATUS_SUCESS if map registers allocated.
  217. --*/
  218. {
  219. PADAPTER_OBJECT MasterAdapter;
  220. ULONG MapRegisterNumber;
  221. //
  222. // Begin by obtaining a pointer to the master adapter associated with this
  223. // request.
  224. //
  225. MasterAdapter = AdapterObject->MasterAdapter;
  226. //
  227. // Check to see whether this driver needs to allocate any map registers.
  228. //
  229. if (AdapterObject->NeedsMapRegisters) {
  230. //
  231. // Ensure that this adapter has enough total map registers to satisfy
  232. // the request.
  233. //
  234. if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
  235. AdapterObject->NumberOfMapRegisters = 0;
  236. return NULL;
  237. }
  238. //
  239. // Attempt to allocate the required number of map registers w/o
  240. // affecting those registers that were allocated when the system
  241. // crashed.
  242. //
  243. MapRegisterNumber = (ULONG)-1;
  244. MapRegisterNumber = RtlFindClearBitsAndSet(
  245. MasterAdapter->MapRegisters,
  246. *NumberOfMapRegisters,
  247. 0
  248. );
  249. if (MapRegisterNumber == (ULONG)-1) {
  250. //
  251. // Not enough free map registers were found, so they were busy
  252. // being used by the system when it crashed. Force the appropriate
  253. // number to be "allocated" at the base by simply overjamming the
  254. // bits and return the base map register as the start.
  255. //
  256. RtlSetBits(
  257. MasterAdapter->MapRegisters,
  258. 0,
  259. *NumberOfMapRegisters
  260. );
  261. MapRegisterNumber = 0;
  262. }
  263. //
  264. // Calculate the map register base from the allocated map
  265. // register and base of the master adapter object.
  266. //
  267. AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
  268. MasterAdapter->MapRegisterBase + MapRegisterNumber);
  269. //
  270. // Set the no scatter/gather flag if scatter/gather not
  271. // supported.
  272. //
  273. if (!AdapterObject->ScatterGather) {
  274. AdapterObject->MapRegisterBase = (PVOID)
  275. ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
  276. }
  277. } else {
  278. AdapterObject->MapRegisterBase = NULL;
  279. AdapterObject->NumberOfMapRegisters = 0;
  280. }
  281. return AdapterObject->MapRegisterBase;
  282. }
  283. PADAPTER_OBJECT
  284. HalGetAdapter(
  285. IN PDEVICE_DESCRIPTION DeviceDescriptor,
  286. OUT PULONG NumberOfMapRegisters
  287. )
  288. /*++
  289. Routine Description:
  290. This function returns the appropriate adapter object for the device defined
  291. in the device description structure. This code works for MCA systems.
  292. Arguments:
  293. DeviceDescriptor - Supplies a description of the deivce.
  294. NumberOfMapRegisters - Returns the maximum number of map registers which
  295. may be allocated by the device driver.
  296. Return Value:
  297. A pointer to the requested adpater object or NULL if an adapter could not
  298. be created.
  299. --*/
  300. {
  301. PADAPTER_OBJECT adapterObject;
  302. ULONG channelNumber;
  303. ULONG numberOfMapRegisters;
  304. PAGED_CODE();
  305. //
  306. // Determine the number of map registers for this device.
  307. //
  308. if (DeviceDescriptor->ScatterGather && (LessThan16Mb ||
  309. DeviceDescriptor->Dma32BitAddresses ||
  310. DeviceDescriptor->InterfaceType == PCIBus)) {
  311. //
  312. // Since the device support scatter/Gather then map registers are not
  313. // required.
  314. //
  315. numberOfMapRegisters = 0;
  316. } else {
  317. //
  318. // Determine the number of map registers required based on the maximum
  319. // transfer length, up to a maximum number.
  320. //
  321. numberOfMapRegisters = BYTES_TO_PAGES(DeviceDescriptor->MaximumLength)
  322. + 1;
  323. numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_MCA_MAP_REGISTER ?
  324. MAXIMUM_MCA_MAP_REGISTER : numberOfMapRegisters;
  325. //
  326. // If the device is not a master and does scatter/gather then it only
  327. // needs one map register.
  328. //
  329. if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
  330. numberOfMapRegisters = 1;
  331. }
  332. }
  333. channelNumber = DeviceDescriptor->DmaChannel;
  334. //
  335. // Determine if a new adapter object is necessary. If so then allocate it.
  336. //
  337. if (!DeviceDescriptor->Master && HalpMCAAdapter[channelNumber] != NULL) {
  338. adapterObject = HalpMCAAdapter[ channelNumber];
  339. } else {
  340. //
  341. // Serialize before allocating a new adapter
  342. //
  343. KeWaitForSingleObject (
  344. &HalpNewAdapter,
  345. WrExecutive,
  346. KernelMode,
  347. FALSE,
  348. NULL
  349. );
  350. //
  351. // Determine if a new adapter object has already been allocated.
  352. // If so use it, otherwise allocate a new adapter object
  353. //
  354. if (!DeviceDescriptor->Master && HalpMCAAdapter[channelNumber] != NULL) {
  355. adapterObject = HalpMCAAdapter[ channelNumber];
  356. } else {
  357. //
  358. // Allocate an adapter object.
  359. //
  360. //
  361. // bugbug- need to pass in MCA base address instead of 0.
  362. //
  363. adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
  364. numberOfMapRegisters,
  365. (PVOID) 0,
  366. NULL
  367. );
  368. if (adapterObject == NULL) {
  369. KeSetEvent (&HalpNewAdapter, 0, FALSE);
  370. return(NULL);
  371. }
  372. if (!DeviceDescriptor->Master) {
  373. HalpMCAAdapter[channelNumber] = adapterObject;
  374. }
  375. //
  376. // Set the maximum number of map registers for this channel bus on
  377. // the number requested and the type of device.
  378. //
  379. if (numberOfMapRegisters) {
  380. //
  381. // The specified number of registers are actually allowed to be
  382. // allocated.
  383. //
  384. adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
  385. //
  386. // Increase the commitment for the map registers.
  387. //
  388. if (DeviceDescriptor->Master) {
  389. //
  390. // Master I/O devices use several sets of map registers double
  391. // their commitment.
  392. //
  393. MasterAdapterObject->CommittedMapRegisters +=
  394. numberOfMapRegisters * 2;
  395. } else {
  396. MasterAdapterObject->CommittedMapRegisters +=
  397. numberOfMapRegisters;
  398. }
  399. //
  400. // If the committed map registers is signicantly greater than the
  401. // number allocated then grow the map buffer.
  402. //
  403. if (MasterAdapterObject->CommittedMapRegisters >
  404. MasterAdapterObject->NumberOfMapRegisters &&
  405. MasterAdapterObject->CommittedMapRegisters -
  406. MasterAdapterObject->NumberOfMapRegisters >
  407. MAXIMUM_MCA_MAP_REGISTER ) {
  408. HalpGrowMapBuffers(
  409. MasterAdapterObject,
  410. INCREMENT_MAP_BUFFER_SIZE
  411. );
  412. }
  413. adapterObject->NeedsMapRegisters = TRUE;
  414. } else {
  415. //
  416. // No real map registers were allocated. If this is a master
  417. // device, then the device can have as may registers as it wants.
  418. //
  419. adapterObject->NeedsMapRegisters = FALSE;
  420. if (DeviceDescriptor->Master) {
  421. adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
  422. DeviceDescriptor->MaximumLength
  423. )
  424. + 1;
  425. } else {
  426. //
  427. // The device only gets one register. It must call
  428. // IoMapTransfer repeatedly to do a large transfer.
  429. //
  430. adapterObject->MapRegistersPerChannel = 1;
  431. }
  432. }
  433. }
  434. KeSetEvent (&HalpNewAdapter, 0, FALSE);
  435. }
  436. adapterObject->Dma32BitAddresses = DeviceDescriptor->Dma32BitAddresses;
  437. adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
  438. *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
  439. //
  440. // set up channel number.
  441. //
  442. adapterObject->ChannelNumber = (UCHAR) channelNumber;
  443. //
  444. // initialize MCA Extended DMA Mode flags.
  445. //
  446. *((PUCHAR) &adapterObject->ExtendedModeFlags) = 0;
  447. //
  448. // set up auto-initialize if necessary.
  449. //
  450. if ( DeviceDescriptor->AutoInitialize) {
  451. adapterObject->ExtendedModeFlags.AutoInitialize = 1;
  452. }
  453. //
  454. // set up PIO address if necessary.
  455. //
  456. if ( DeviceDescriptor->DmaPort) {
  457. adapterObject->ExtendedModeFlags.ProgrammedIo = DMA_EXT_USE_PIO;
  458. adapterObject->DmaPortAddress = (USHORT) DeviceDescriptor->DmaPort;
  459. } else {
  460. adapterObject->ExtendedModeFlags.ProgrammedIo = DMA_EXT_NO_PIO;
  461. }
  462. //
  463. // indicate data transfer operation for DMA.
  464. //
  465. adapterObject->ExtendedModeFlags.DmaOpcode = DMA_EXT_DATA_XFER;
  466. switch (DeviceDescriptor->DmaWidth) {
  467. case Width8Bits:
  468. adapterObject->ExtendedModeFlags.DmaWidth = DMA_EXT_WIDTH_8_BIT;
  469. break;
  470. case Width16Bits:
  471. adapterObject->ExtendedModeFlags.DmaWidth = DMA_EXT_WIDTH_16_BIT;
  472. break;
  473. case Width32Bits:
  474. //
  475. // If it's a master, it doesn't need DmaWidth filled in
  476. //
  477. if (!DeviceDescriptor->Master) {
  478. ObDereferenceObject( adapterObject );
  479. return(NULL);
  480. }
  481. break;
  482. default:
  483. ObDereferenceObject( adapterObject );
  484. return(NULL);
  485. } // switch
  486. if (DeviceDescriptor->Master) {
  487. adapterObject->MasterDevice = TRUE;
  488. } else {
  489. adapterObject->MasterDevice = FALSE;
  490. } // if
  491. return(adapterObject);
  492. }
  493. PHYSICAL_ADDRESS
  494. IoMapTransfer(
  495. IN PADAPTER_OBJECT AdapterObject,
  496. IN PMDL Mdl,
  497. IN PVOID MapRegisterBase,
  498. IN PVOID CurrentVa,
  499. IN OUT PULONG Length,
  500. IN BOOLEAN WriteToDevice
  501. )
  502. /*++
  503. Routine Description:
  504. This routine is invoked to set up the map registers in the DMA controller
  505. to allow a transfer to or from a device.
  506. Arguments:
  507. AdapterObject - Pointer to the adapter object representing the DMA
  508. controller channel that has been allocated.
  509. Mdl - Pointer to the MDL that describes the pages of memory that are
  510. being read or written.
  511. MapRegisterBase - The address of the base map register that has been
  512. allocated to the device driver for use in mapping the transfer.
  513. CurrentVa - Current virtual address in the buffer described by the MDL
  514. that the transfer is being done to or from.
  515. Length - Supplies the length of the transfer. This determines the
  516. number of map registers that need to be written to map the transfer.
  517. Returns the length of the transfer which was actually mapped.
  518. WriteToDevice - Boolean value that indicates whether this is a write
  519. to the device from memory (TRUE), or vice versa.
  520. Return Value:
  521. Returns the logical address that should be used bus master controllers.
  522. --*/
  523. {
  524. BOOLEAN useBuffer;
  525. ULONG transferLength;
  526. ULONG logicalAddress;
  527. PHYSICAL_ADDRESS returnAddress;
  528. ULONG index;
  529. PULONG pageFrame;
  530. PTRANSLATION_ENTRY translationEntry;
  531. PMCA_DMA_CONTROLLER dmaControl;
  532. UCHAR channelNumber;
  533. KIRQL Irql;
  534. KIRQL Irql2;
  535. ULONG pageOffset;
  536. pageOffset = BYTE_OFFSET(CurrentVa);
  537. //
  538. // Calculate how must of the transfer is contiguous.
  539. //
  540. transferLength = PAGE_SIZE - pageOffset;
  541. pageFrame = (PULONG)(Mdl+1);
  542. pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) / PAGE_SIZE;
  543. logicalAddress = (*pageFrame << PAGE_SHIFT) + pageOffset;
  544. //
  545. // If the buffer is contigous then just extend the buffer.
  546. //
  547. while( transferLength < *Length ){
  548. if (*pageFrame + 1 != *(pageFrame + 1)) {
  549. break;
  550. }
  551. transferLength += PAGE_SIZE;
  552. pageFrame++;
  553. }
  554. transferLength = transferLength > *Length ? *Length : transferLength;
  555. //
  556. // Determine if the data transfer needs to use the map buffer.
  557. //
  558. if (MapRegisterBase != NULL) {
  559. //
  560. // Strip no scatter/gather flag.
  561. //
  562. translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
  563. if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
  564. && transferLength < *Length) {
  565. logicalAddress = translationEntry->PhysicalAddress + pageOffset;
  566. translationEntry->Index = COPY_BUFFER;
  567. index = 0;
  568. transferLength = *Length;
  569. useBuffer = TRUE;
  570. } else {
  571. //
  572. // If there are map registers, then update the index to indicate
  573. // how many have been used.
  574. //
  575. useBuffer = FALSE;
  576. index = translationEntry->Index;
  577. translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
  578. CurrentVa,
  579. transferLength
  580. );
  581. }
  582. //
  583. // It must require memory to be at less than 16 MB. If the
  584. // logical address is greater than 16MB then map registers must be used
  585. //
  586. if (logicalAddress+transferLength >= MAXIMUM_PHYSICAL_ADDRESS) {
  587. logicalAddress = (translationEntry + index)->PhysicalAddress +
  588. pageOffset;
  589. useBuffer = TRUE;
  590. if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
  591. translationEntry->Index = COPY_BUFFER;
  592. index = 0;
  593. }
  594. }
  595. //
  596. // Copy the data if necessary.
  597. //
  598. if (useBuffer && WriteToDevice) {
  599. HalpCopyBufferMap(
  600. Mdl,
  601. translationEntry + index,
  602. CurrentVa,
  603. *Length,
  604. WriteToDevice
  605. );
  606. }
  607. }
  608. //
  609. // Return the length.
  610. //
  611. *Length = transferLength;
  612. //
  613. // We only support 32 bits, but the return is 64. Just
  614. // zero extend
  615. //
  616. returnAddress.LowPart = logicalAddress;
  617. returnAddress.HighPart = 0;
  618. //
  619. // If no adapter was specificed, or device is bus master, then there
  620. // is no more work to do so return.
  621. //
  622. if (AdapterObject == NULL || AdapterObject->MasterDevice) {
  623. return(returnAddress);
  624. }
  625. //
  626. // grab the spinlock for the Microchannel system DMA controller
  627. //
  628. Irql = KfAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock );
  629. //
  630. // Raise to high level. On systems with ABIOS disks
  631. // the ABIOS can reprogram the DMA from its interrupt. Raising to high
  632. // prevents the ABIOS from running while the DMA controller is being
  633. // maniulated. Note this will not work on MP systems, however there are
  634. // no know MP systems with non-SCSI ABIOS disks.
  635. //
  636. Irql2 = KfRaiseIrql(HIGH_LEVEL);
  637. //
  638. // Set up the Microchannel system DMA controller
  639. //
  640. dmaControl = (PMCA_DMA_CONTROLLER)
  641. &( (PMCA_CONTROL) (AdapterObject->AdapterBaseVa))->
  642. ExtendedDmaBasePort[0];
  643. channelNumber = AdapterObject->ChannelNumber;
  644. //
  645. // set the mask bit
  646. //
  647. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
  648. (UCHAR) ( SET_MASK_BIT | channelNumber));
  649. //
  650. // set mode register
  651. //
  652. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
  653. (UCHAR) ( WRITE_MODE | channelNumber));
  654. //
  655. // Set up for read or write, appropriately
  656. //
  657. if ( WriteToDevice) {
  658. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
  659. (UCHAR) (*((PUCHAR) &AdapterObject->
  660. ExtendedModeFlags)
  661. | (UCHAR) DMA_MODE_READ));
  662. } else {
  663. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
  664. (UCHAR) ( *((PUCHAR) &AdapterObject->
  665. ExtendedModeFlags)
  666. | DMA_MODE_WRITE));
  667. }
  668. //
  669. // if there is a DMA Programmed I/O address, set it up
  670. //
  671. if ( AdapterObject->ExtendedModeFlags.ProgrammedIo) {
  672. //
  673. // set up I/O base address
  674. //
  675. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
  676. (UCHAR) ( WRITE_IO_ADDRESS | channelNumber));
  677. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
  678. (UCHAR) AdapterObject->DmaPortAddress);
  679. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
  680. (UCHAR) ( AdapterObject->DmaPortAddress >> 8));
  681. }
  682. //
  683. // set the DMA transfer count
  684. //
  685. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
  686. (UCHAR) ( WRITE_TRANSFER_COUNT | channelNumber));
  687. //
  688. // adjust transfer count for 16-bit transfers as required.
  689. //
  690. if ( AdapterObject->ExtendedModeFlags.DmaWidth == DMA_EXT_WIDTH_16_BIT ) {
  691. //
  692. // Round up on odd byte transfers and divide by 2.
  693. //
  694. transferLength++;
  695. transferLength >>= 1;
  696. }
  697. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
  698. (UCHAR) ( transferLength - 1));
  699. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
  700. (UCHAR) ( ( transferLength - 1) >> 8));
  701. //
  702. // set the DMA transfer start address
  703. //
  704. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
  705. (UCHAR) ( WRITE_MEMORY_ADDRESS | channelNumber));
  706. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
  707. (UCHAR) logicalAddress);
  708. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
  709. (UCHAR) (logicalAddress >> 8));
  710. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
  711. (UCHAR) (logicalAddress >> 16));
  712. //
  713. // clear the mask bit
  714. //
  715. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
  716. (UCHAR) ( CLEAR_MASK_BIT | channelNumber));
  717. KfLowerIrql(Irql2);
  718. //
  719. // release the spinlock for the Microchannel system DMA controller
  720. //
  721. KfReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
  722. return(returnAddress);
  723. }
  724. BOOLEAN
  725. IoFlushAdapterBuffers(
  726. IN PADAPTER_OBJECT AdapterObject,
  727. IN PMDL Mdl,
  728. IN PVOID MapRegisterBase,
  729. IN PVOID CurrentVa,
  730. IN ULONG Length,
  731. IN BOOLEAN WriteToDevice
  732. )
  733. /*++
  734. Routine Description:
  735. This routine flushes the DMA adpater object buffers.
  736. Arguments:
  737. AdapterObject - Pointer to the adapter object representing the DMA
  738. controller channel.
  739. Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
  740. buffer to/from which the I/O occured.
  741. MapRegisterBase - A pointer to the base of the map registers in the adapter
  742. or DMA controller.
  743. CurrentVa - The current virtual address in the buffer described the the Mdl
  744. where the I/O operation occurred.
  745. Length - Supplies the length of the transfer.
  746. WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
  747. the data transfer was to the device.
  748. Return Value:
  749. TRUE - No errors are detected so the transfer must succeed.
  750. --*/
  751. {
  752. PMCA_DMA_CONTROLLER dmaControl;
  753. KIRQL Irql;
  754. KIRQL Irql2;
  755. PTRANSLATION_ENTRY translationEntry;
  756. PULONG pageFrame;
  757. ULONG transferLength;
  758. ULONG partialLength;
  759. BOOLEAN masterDevice;
  760. masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
  761. TRUE : FALSE;
  762. //
  763. // If this is a slave device then stop the DMA controller be flushing
  764. // the data.
  765. //
  766. if (!masterDevice) {
  767. //
  768. // grab the spinlock for the Microchannel system DMA controller
  769. //
  770. Irql = KfAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock );
  771. //
  772. // Raise to high level. On systems with ABIOS disks
  773. // the ABIOS can reprogram the DMA from its interrupt. Raising to high
  774. // prevents the ABIOS from running while the DMA controller is being
  775. // maniulated. Note this will not work on MP systems, however there are
  776. // no know MP systems with non-SCSI ABIOS disks.
  777. //
  778. Irql2 = KfRaiseIrql(HIGH_LEVEL);
  779. //
  780. // Set up the Microchannel system DMA controller
  781. //
  782. dmaControl = (PMCA_DMA_CONTROLLER)
  783. &( (PMCA_CONTROL) (AdapterObject->AdapterBaseVa))->
  784. ExtendedDmaBasePort[0];
  785. //
  786. // clear the mask bit
  787. //
  788. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
  789. (UCHAR) ( SET_MASK_BIT | AdapterObject->ChannelNumber));
  790. //
  791. // release the spinlock for the Microchannel system DMA controller
  792. //
  793. KfLowerIrql(Irql2);
  794. KfReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
  795. }
  796. if (MapRegisterBase == NULL) {
  797. return(TRUE);
  798. }
  799. //
  800. // Determine if the data needs to be copied to the orginal buffer.
  801. // This only occurs if the data tranfer is from the device, the
  802. // MapReisterBase is not NULL and the transfer spans a page.
  803. //
  804. if (!WriteToDevice) {
  805. //
  806. // Strip no scatter/gather flag.
  807. //
  808. translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
  809. //
  810. // If this is not a master device, then just transfer the buffer.
  811. //
  812. if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
  813. if (translationEntry->Index == COPY_BUFFER) {
  814. if (!masterDevice) {
  815. //
  816. // Copy only the bytes that have actually been transfered.
  817. //
  818. Length -= HalReadDmaCounter(AdapterObject);
  819. }
  820. //
  821. // The adapter does not support scatter/gather copy the buffer.
  822. //
  823. HalpCopyBufferMap(
  824. Mdl,
  825. translationEntry,
  826. CurrentVa,
  827. Length,
  828. WriteToDevice
  829. );
  830. }
  831. } else {
  832. //
  833. // Cycle through the pages of the transfer to determine if there
  834. // are any which need to be copied back.
  835. //
  836. transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
  837. partialLength = transferLength;
  838. pageFrame = (PULONG)(Mdl+1);
  839. pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) / PAGE_SIZE;
  840. while( transferLength <= Length ){
  841. if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
  842. HalpCopyBufferMap(
  843. Mdl,
  844. translationEntry,
  845. CurrentVa,
  846. partialLength,
  847. WriteToDevice
  848. );
  849. }
  850. (PCCHAR) CurrentVa += partialLength;
  851. partialLength = PAGE_SIZE;
  852. //
  853. // Note that transferLength indicates the amount which will be
  854. // transfered after the next loop; thus, it is updated with the
  855. // new partial length.
  856. //
  857. transferLength += partialLength;
  858. pageFrame++;
  859. translationEntry++;
  860. }
  861. //
  862. // Process the any remaining residue.
  863. //
  864. partialLength = Length - transferLength + partialLength;
  865. if (partialLength && *pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
  866. HalpCopyBufferMap(
  867. Mdl,
  868. translationEntry,
  869. CurrentVa,
  870. partialLength,
  871. WriteToDevice
  872. );
  873. }
  874. }
  875. }
  876. //
  877. // Strip no scatter/gather flag.
  878. //
  879. translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
  880. //
  881. // Clear the index of used buffers.
  882. //
  883. if (translationEntry) {
  884. translationEntry->Index = 0;
  885. }
  886. return TRUE;
  887. }
  888. ULONG
  889. HalReadDmaCounter(
  890. IN PADAPTER_OBJECT AdapterObject
  891. )
  892. /*++
  893. Routine Description:
  894. This function reads the DMA counter and returns the number of bytes left
  895. to be transfered.
  896. Arguments:
  897. AdapterObject - Supplies a pointer to the adapter object to be read.
  898. Return Value:
  899. Returns the number of bytes still be be transfered.
  900. --*/
  901. {
  902. ULONG count;
  903. ULONG high;
  904. PMCA_DMA_CONTROLLER dmaControl;
  905. UCHAR channelNumber;
  906. KIRQL Irql;
  907. KIRQL Irql2;
  908. //
  909. // grab the spinlock for the Microchannel system DMA controller
  910. //
  911. Irql = KfAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock );
  912. //
  913. // Raise to high level. On systems with ABIOS disks
  914. // the ABIOS can reprogram the DMA from its interrupt. Raising to high
  915. // prevents the ABIOS from running while the DMA controller is being
  916. // maniulated. Note this will not work on MP systems, however there are
  917. // no know MP systems with non-SCSI ABIOS disks.
  918. //
  919. Irql2 = KfRaiseIrql(HIGH_LEVEL);
  920. //
  921. // Set up the Microchannel system DMA controller
  922. //
  923. dmaControl = (PMCA_DMA_CONTROLLER)
  924. &( (PMCA_CONTROL) (AdapterObject->AdapterBaseVa))->
  925. ExtendedDmaBasePort[0];
  926. channelNumber = AdapterObject->ChannelNumber;
  927. count = 0XFFFF00;
  928. //
  929. // Loop until the high byte matches.
  930. //
  931. do {
  932. high = count;
  933. //
  934. // read the DMA transfer count
  935. //
  936. WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
  937. (UCHAR) ( READ_TRANSFER_COUNT | channelNumber));
  938. count = READ_PORT_UCHAR( &dmaControl->DmaFunctionData);
  939. count |= READ_PORT_UCHAR( &dmaControl->DmaFunctionData) << 8;
  940. } while ((count & 0xFFFF00) != (high & 0xFFFF00));
  941. //
  942. // The DMA counter has a bias of one and can only be 16 bit long.
  943. //
  944. count = (count + 1) & 0xFFFF;
  945. //
  946. // adjust transfer count for 16-bit transfers as required.
  947. //
  948. if ( AdapterObject->ExtendedModeFlags.DmaWidth == DMA_EXT_WIDTH_16_BIT ) {
  949. count <<= 1;
  950. }
  951. KfLowerIrql(Irql2);
  952. //
  953. // release the spinlock for the Microchannel system DMA controller
  954. //
  955. KfReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
  956. return(count);
  957. }