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.

1385 lines
40 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. ixisasup.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. --*/
  15. #include "halp.h"
  16. #include "eisa.h"
  17. #include "pci.h"
  18. #include "pcip.h"
  19. //
  20. //Only take the prototype, don't instantiate
  21. //
  22. #include <wdmguid.h>
  23. #include "halpnpp.h"
  24. VOID
  25. HalpGrowMapBufferWorker(
  26. IN PVOID Context
  27. );
  28. #ifdef ALLOC_PRAGMA
  29. #pragma alloc_text(PAGE,HalGetAdapter)
  30. #pragma alloc_text(PAGE,HalpGetIsaIrqState)
  31. #endif
  32. //
  33. // The HalpNewAdapter event is used to serialize allocations
  34. // of new adapter objects, additions to the HalpEisaAdapter
  35. // array, and some global values (MasterAdapterObject) and some
  36. // adapter fields modified by HalpGrowMapBuffers.
  37. // (AdapterObject->NumberOfMapRegisters is assumed not to be
  38. // growable while this even is held)
  39. //
  40. // Note: We don't really need our own an event object for this.
  41. //
  42. KEVENT HalpNewAdapter;
  43. #define ACQUIRE_NEW_ADAPTER_LOCK() \
  44. { \
  45. KeWaitForSingleObject ( \
  46. &HalpNewAdapter, \
  47. WrExecutive, \
  48. KernelMode, \
  49. FALSE, \
  50. NULL \
  51. ); \
  52. }
  53. typedef struct _BUFFER_GROW_WORK_ITEM {
  54. WORK_QUEUE_ITEM WorkItem;
  55. PADAPTER_OBJECT AdapterObject;
  56. ULONG MapRegisterCount;
  57. } BUFFER_GROW_WORK_ITEM, *PBUFFER_GROW_WORK_ITEM;
  58. #define RELEASE_NEW_ADAPTER_LOCK() \
  59. KeSetEvent (&HalpNewAdapter, 0, FALSE)
  60. BOOLEAN NoMemoryAbove4Gb = FALSE;
  61. VOID
  62. HalpCopyBufferMap(
  63. IN PMDL Mdl,
  64. IN PTRANSLATION_ENTRY TranslationEntry,
  65. IN PVOID CurrentVa,
  66. IN ULONG Length,
  67. IN BOOLEAN WriteToDevice
  68. );
  69. PHYSICAL_ADDRESS
  70. HalpMapTransfer(
  71. IN PADAPTER_OBJECT AdapterObject,
  72. IN PMDL Mdl,
  73. IN PVOID MapRegisterBase,
  74. IN PVOID CurrentVa,
  75. IN OUT PULONG Length,
  76. IN BOOLEAN WriteToDevice
  77. );
  78. VOID
  79. HalpMapTransferHelper(
  80. IN PMDL Mdl,
  81. IN PVOID CurrentVa,
  82. IN ULONG TransferLength,
  83. IN PPFN_NUMBER PageFrame,
  84. IN OUT PULONG Length
  85. );
  86. NTSTATUS
  87. HalAllocateAdapterChannel(
  88. IN PADAPTER_OBJECT AdapterObject,
  89. IN PWAIT_CONTEXT_BLOCK Wcb,
  90. IN ULONG NumberOfMapRegisters,
  91. IN PDRIVER_CONTROL ExecutionRoutine
  92. )
  93. /*++
  94. Routine Description:
  95. This routine allocates the adapter channel specified by the adapter object.
  96. This is accomplished by placing the device object of the driver that wants
  97. to allocate the adapter on the adapter's queue. If the queue is already
  98. "busy", then the adapter has already been allocated, so the device object
  99. is simply placed onto the queue and waits until the adapter becomes free.
  100. Once the adapter becomes free (or if it already is), then the driver's
  101. execution routine is invoked.
  102. Also, a number of map registers may be allocated to the driver by specifying
  103. a non-zero value for NumberOfMapRegisters. Then the map register must be
  104. allocated from the master adapter. Once there are a sufficient number of
  105. map registers available, then the execution routine is called and the
  106. base address of the allocated map registers in the adapter is also passed
  107. to the driver's execution routine.
  108. Arguments:
  109. AdapterObject - Pointer to the adapter control object to allocate to the
  110. driver.
  111. Wcb - Supplies a wait context block for saving the allocation parameters.
  112. The DeviceObject, CurrentIrp and DeviceContext should be initalized.
  113. NumberOfMapRegisters - The number of map registers that are to be allocated
  114. from the channel, if any.
  115. ExecutionRoutine - The address of the driver's execution routine that is
  116. invoked once the adapter channel (and possibly map registers) have been
  117. allocated.
  118. Return Value:
  119. Returns STATUS_SUCESS unless too many map registers are requested.
  120. Notes:
  121. Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
  122. --*/
  123. {
  124. PADAPTER_OBJECT MasterAdapter;
  125. BOOLEAN Busy = FALSE;
  126. IO_ALLOCATION_ACTION Action;
  127. KIRQL Irql;
  128. ULONG MapRegisterNumber;
  129. //
  130. // Begin by obtaining a pointer to the master adapter associated with this
  131. // request.
  132. //
  133. MasterAdapter = AdapterObject->MasterAdapter;
  134. //
  135. // Initialize the device object's wait context block in case this device
  136. // must wait before being able to allocate the adapter.
  137. //
  138. Wcb->DeviceRoutine = ExecutionRoutine;
  139. Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
  140. //
  141. // Allocate the adapter object for this particular device. If the
  142. // adapter cannot be allocated because it has already been allocated
  143. // to another device, then return to the caller now; otherwise,
  144. // continue.
  145. //
  146. if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
  147. &Wcb->WaitQueueEntry )) {
  148. //
  149. // Save the parameters in case there are not enough map registers.
  150. //
  151. AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
  152. AdapterObject->CurrentWcb = Wcb;
  153. //
  154. // The adapter was not busy so it has been allocated. Now check
  155. // to see whether this driver wishes to allocate any map registers.
  156. // Ensure that this adapter has enough total map registers
  157. // to satisfy the request.
  158. //
  159. if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
  160. //
  161. // Lock the map register bit map and the adapter queue in the
  162. // master adapter object. The channel structure offset is used as
  163. // a hint for the register search.
  164. //
  165. if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
  166. AdapterObject->NumberOfMapRegisters = 0;
  167. IoFreeAdapterChannel(AdapterObject);
  168. return (STATUS_INSUFFICIENT_RESOURCES);
  169. }
  170. KeAcquireSpinLock (&MasterAdapter->SpinLock, &Irql);
  171. MapRegisterNumber = (ULONG)-1;
  172. if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
  173. HalDebugPrint((HAL_VERBOSE, "HAAC: FindClearBitsAndSet(%p,%d,0)\n",
  174. MasterAdapter->MapRegisters,
  175. NumberOfMapRegisters));
  176. MapRegisterNumber = RtlFindClearBitsAndSet(
  177. MasterAdapter->MapRegisters,
  178. NumberOfMapRegisters,
  179. 0
  180. );
  181. HalDebugPrint((HAL_VERBOSE, "HAAC: MapRegisterNumber = 0x%x\n",
  182. MapRegisterNumber));
  183. }
  184. if (MapRegisterNumber == -1) {
  185. PBUFFER_GROW_WORK_ITEM bufferWorkItem;
  186. //
  187. // There were not enough free map registers. Queue this request
  188. // on the master adapter where is will wait until some registers
  189. // are deallocated.
  190. //
  191. InsertTailList( &MasterAdapter->AdapterQueue,
  192. &AdapterObject->AdapterQueue
  193. );
  194. Busy = 1;
  195. //
  196. // Queue a work item to grow the map registers
  197. //
  198. bufferWorkItem = ExAllocatePool( NonPagedPool,
  199. sizeof(BUFFER_GROW_WORK_ITEM) );
  200. if (bufferWorkItem != NULL) {
  201. ExInitializeWorkItem( &bufferWorkItem->WorkItem,
  202. HalpGrowMapBufferWorker,
  203. bufferWorkItem );
  204. bufferWorkItem->AdapterObject = AdapterObject;
  205. bufferWorkItem->MapRegisterCount = NumberOfMapRegisters;
  206. ExQueueWorkItem( &bufferWorkItem->WorkItem,
  207. DelayedWorkQueue );
  208. }
  209. } else {
  210. //
  211. // Calculate the map register base from the allocated map
  212. // register and base of the master adapter object.
  213. //
  214. AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
  215. MasterAdapter->MapRegisterBase + MapRegisterNumber);
  216. //
  217. // Set the no scatter/gather flag if scatter/gather not
  218. // supported.
  219. //
  220. if (!AdapterObject->ScatterGather) {
  221. AdapterObject->MapRegisterBase = (PVOID)
  222. ((UINT_PTR) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
  223. }
  224. }
  225. KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
  226. } else {
  227. AdapterObject->MapRegisterBase = NULL;
  228. AdapterObject->NumberOfMapRegisters = 0;
  229. }
  230. //
  231. // If there were either enough map registers available or no map
  232. // registers needed to be allocated, invoke the driver's execution
  233. // routine now.
  234. //
  235. if (!Busy) {
  236. AdapterObject->CurrentWcb = Wcb;
  237. Action = ExecutionRoutine( Wcb->DeviceObject,
  238. Wcb->CurrentIrp,
  239. AdapterObject->MapRegisterBase,
  240. Wcb->DeviceContext );
  241. //
  242. // If the driver would like to have the adapter deallocated,
  243. // then release the adapter object.
  244. //
  245. if (Action == DeallocateObject) {
  246. IoFreeAdapterChannel( AdapterObject );
  247. } else if (Action == DeallocateObjectKeepRegisters) {
  248. //
  249. // Set the NumberOfMapRegisters = 0 in the adapter object.
  250. // This will keep IoFreeAdapterChannel from freeing the
  251. // registers. After this it is the driver's responsiblity to
  252. // keep track of the number of map registers.
  253. //
  254. AdapterObject->NumberOfMapRegisters = 0;
  255. IoFreeAdapterChannel(AdapterObject);
  256. }
  257. }
  258. }
  259. return (STATUS_SUCCESS);
  260. }
  261. NTSTATUS
  262. HalRealAllocateAdapterChannel(
  263. IN PADAPTER_OBJECT AdapterObject,
  264. IN PDEVICE_OBJECT DeviceObject,
  265. IN ULONG NumberOfMapRegisters,
  266. IN PDRIVER_CONTROL ExecutionRoutine,
  267. IN PVOID Context
  268. )
  269. /*++
  270. Routine Description:
  271. This routine allocates the adapter channel specified by the adapter object.
  272. This is accomplished by calling HalAllocateAdapterChannel which does all of
  273. the work.
  274. Arguments:
  275. AdapterObject - Pointer to the adapter control object to allocate to the
  276. driver.
  277. DeviceObject - Pointer to the driver's device object that represents the
  278. device allocating the adapter.
  279. NumberOfMapRegisters - The number of map registers that are to be allocated
  280. from the channel, if any.
  281. ExecutionRoutine - The address of the driver's execution routine that is
  282. invoked once the adapter channel (and possibly map registers) have been
  283. allocated.
  284. Context - An untyped longword context parameter passed to the driver's
  285. execution routine.
  286. Return Value:
  287. Returns STATUS_SUCESS unless too many map registers are requested.
  288. Notes:
  289. Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
  290. --*/
  291. {
  292. PWAIT_CONTEXT_BLOCK wcb;
  293. wcb = &DeviceObject->Queue.Wcb;
  294. wcb->DeviceObject = DeviceObject;
  295. wcb->CurrentIrp = DeviceObject->CurrentIrp;
  296. wcb->DeviceContext = Context;
  297. return( HalAllocateAdapterChannel( AdapterObject,
  298. wcb,
  299. NumberOfMapRegisters,
  300. ExecutionRoutine ) );
  301. }
  302. VOID
  303. HalpGrowMapBufferWorker(
  304. IN PVOID Context
  305. )
  306. /*++
  307. Routine Description:
  308. This routine is called in the context of a work item from
  309. HalAllocateAdapterChannel() when it queues a map register allocation
  310. because map regiers are not available.
  311. Its purpose is to attempt to grow the map buffers for the adapter and,
  312. if successful, process queued adapter allocations.
  313. Arguments:
  314. Context - Actually a pointer to a BUFFER_GROW_WORK_ITEM structure.
  315. Return Value:
  316. None.
  317. --*/
  318. {
  319. PBUFFER_GROW_WORK_ITEM growWorkItem;
  320. PADAPTER_OBJECT masterAdapter;
  321. BOOLEAN allocated;
  322. ULONG bytesToGrow;
  323. KIRQL oldIrql;
  324. growWorkItem = (PBUFFER_GROW_WORK_ITEM)Context;
  325. masterAdapter = growWorkItem->AdapterObject->MasterAdapter;
  326. //
  327. // HalpGrowMapBuffers() takes a byte count
  328. //
  329. bytesToGrow = growWorkItem->MapRegisterCount * PAGE_SIZE +
  330. INCREMENT_MAP_BUFFER_SIZE;
  331. ACQUIRE_NEW_ADAPTER_LOCK();
  332. allocated = HalpGrowMapBuffers( masterAdapter,
  333. bytesToGrow );
  334. RELEASE_NEW_ADAPTER_LOCK();
  335. if (allocated != FALSE) {
  336. KeRaiseIrql( DISPATCH_LEVEL, &oldIrql );
  337. //
  338. // The map buffers were grown. It is likely that someone is waiting
  339. // in the adapter queue, so try to get things started.
  340. //
  341. // The code in IoFreeMapRegisters() does this, and it turns out
  342. // we can safely get it to do this work for us by freeing 0
  343. // map registers at a bogus (but non-NULL) register base.
  344. //
  345. IoFreeMapRegisters( growWorkItem->AdapterObject,
  346. (PVOID)2,
  347. 0 );
  348. KeLowerIrql( oldIrql );
  349. }
  350. ExFreePool( growWorkItem );
  351. }
  352. PVOID
  353. HalAllocateCrashDumpRegisters(
  354. IN PADAPTER_OBJECT AdapterObject,
  355. IN PULONG NumberOfMapRegisters
  356. )
  357. /*++
  358. Routine Description:
  359. This routine is called during the crash dump disk driver's initialization
  360. to allocate a number map registers permanently.
  361. Arguments:
  362. AdapterObject - Pointer to the adapter control object to allocate to the
  363. driver.
  364. NumberOfMapRegisters - Number of map registers requested. This field
  365. will be updated to reflect the actual number of registers allocated
  366. when the number is less than what was requested.
  367. Return Value:
  368. Returns STATUS_SUCESS if map registers allocated.
  369. --*/
  370. {
  371. PADAPTER_OBJECT MasterAdapter;
  372. ULONG MapRegisterNumber;
  373. //
  374. // Begin by obtaining a pointer to the master adapter associated with this
  375. // request.
  376. //
  377. MasterAdapter = AdapterObject->MasterAdapter;
  378. //
  379. // Check to see whether this driver needs to allocate any map registers.
  380. //
  381. if (AdapterObject->NeedsMapRegisters) {
  382. //
  383. // Ensure that this adapter has enough total map registers to satisfy
  384. // the request.
  385. //
  386. if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
  387. AdapterObject->NumberOfMapRegisters = 0;
  388. return NULL;
  389. }
  390. //
  391. // Attempt to allocate the required number of map registers w/o
  392. // affecting those registers that were allocated when the system
  393. // crashed.
  394. //
  395. MapRegisterNumber = (ULONG)-1;
  396. MapRegisterNumber = RtlFindClearBitsAndSet(
  397. MasterAdapter->MapRegisters,
  398. *NumberOfMapRegisters,
  399. 0
  400. );
  401. if (MapRegisterNumber == (ULONG)-1) {
  402. //
  403. // Not enough free map registers were found, so they were busy
  404. // being used by the system when it crashed. Force the appropriate
  405. // number to be "allocated" at the base by simply overjamming the
  406. // bits and return the base map register as the start.
  407. //
  408. RtlSetBits(
  409. MasterAdapter->MapRegisters,
  410. 0,
  411. *NumberOfMapRegisters
  412. );
  413. MapRegisterNumber = 0;
  414. }
  415. //
  416. // Calculate the map register base from the allocated map
  417. // register and base of the master adapter object.
  418. //
  419. AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
  420. MasterAdapter->MapRegisterBase + MapRegisterNumber);
  421. //
  422. // Set the no scatter/gather flag if scatter/gather not
  423. // supported.
  424. //
  425. if (!AdapterObject->ScatterGather) {
  426. AdapterObject->MapRegisterBase = (PVOID)
  427. ((UINT_PTR) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
  428. }
  429. } else {
  430. AdapterObject->MapRegisterBase = NULL;
  431. AdapterObject->NumberOfMapRegisters = 0;
  432. }
  433. return AdapterObject->MapRegisterBase;
  434. }
  435. PADAPTER_OBJECT
  436. HalGetAdapter(
  437. IN PDEVICE_DESCRIPTION DeviceDescriptor,
  438. OUT PULONG NumberOfMapRegisters
  439. )
  440. /*++
  441. Routine Description:
  442. This function returns the appropriate adapter object for the device defined
  443. in the device description structure.
  444. Arguments:
  445. DeviceDescriptor - Supplies a description of the deivce.
  446. NumberOfMapRegisters - Returns the maximum number of map registers which
  447. may be allocated by the device driver.
  448. Return Value:
  449. A pointer to the requested adapter object or NULL if an adapter could not
  450. be created.
  451. --*/
  452. {
  453. PADAPTER_OBJECT adapterObject;
  454. PVOID adapterBaseVa;
  455. UCHAR adapterMode;
  456. ULONG numberOfMapRegisters;
  457. ULONG maximumLength;
  458. PAGED_CODE();
  459. HalDebugPrint((HAL_VERBOSE, "HGA: IN DeviceDescriptor %p\n",
  460. DeviceDescriptor));
  461. HalDebugPrint((HAL_VERBOSE, "HGA: IN NumberOfMapregisters %p\n",
  462. NumberOfMapRegisters));
  463. //
  464. // Make sure this is the correct version.
  465. //
  466. if (DeviceDescriptor->Version > DEVICE_DESCRIPTION_VERSION2) {
  467. return ( NULL );
  468. }
  469. #if DBG
  470. if (DeviceDescriptor->Version >= DEVICE_DESCRIPTION_VERSION1) {
  471. ASSERT (DeviceDescriptor->Reserved1 == FALSE);
  472. }
  473. #endif
  474. //
  475. // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
  476. // macro works correctly.
  477. //
  478. maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
  479. if (DeviceDescriptor->InterfaceType == PCIBus &&
  480. DeviceDescriptor->Master != FALSE &&
  481. DeviceDescriptor->ScatterGather != FALSE) {
  482. //
  483. // This device can handle 32 bits, even if the caller forgot to
  484. // set Dma32BitAddresses.
  485. //
  486. DeviceDescriptor->Dma32BitAddresses = TRUE;
  487. }
  488. //
  489. // Determine the number of map registers for this device.
  490. //
  491. if (DeviceDescriptor->ScatterGather &&
  492. (NoMemoryAbove4Gb ||
  493. DeviceDescriptor->Dma64BitAddresses)) {
  494. //
  495. // Since the device support scatter/Gather then map registers are not
  496. // required.
  497. //
  498. numberOfMapRegisters = 0;
  499. } else {
  500. //
  501. // Determine the number of map registers required based on the maximum
  502. // transfer length, up to a maximum number.
  503. //
  504. numberOfMapRegisters = BYTES_TO_PAGES(maximumLength) + 1;
  505. if (numberOfMapRegisters > MAXIMUM_PCI_MAP_REGISTER) {
  506. numberOfMapRegisters = MAXIMUM_PCI_MAP_REGISTER;
  507. }
  508. }
  509. HalDebugPrint((HAL_VERBOSE, "HGA: Number of map registers needed = %x\n",
  510. numberOfMapRegisters));
  511. adapterBaseVa = NULL;
  512. //
  513. // Serialize before allocating a new adapter
  514. //
  515. ACQUIRE_NEW_ADAPTER_LOCK();
  516. //
  517. // Allocate an adapter object.
  518. //
  519. adapterObject =
  520. (PADAPTER_OBJECT) HalpAllocateAdapter( numberOfMapRegisters,
  521. adapterBaseVa,
  522. NULL);
  523. if (adapterObject == NULL) {
  524. RELEASE_NEW_ADAPTER_LOCK();
  525. return (NULL);
  526. }
  527. //
  528. // Set the maximum number of map registers for this channel bus on
  529. // the number requested and the type of device.
  530. //
  531. if (numberOfMapRegisters) {
  532. //
  533. // The speicified number of registers are actually allowed to be
  534. // allocated.
  535. //
  536. adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
  537. //
  538. // Increase the commitment for the map registers.
  539. //
  540. // Master I/O devices use several sets of map registers double
  541. // their commitment.
  542. //
  543. MasterAdapterObject->CommittedMapRegisters += numberOfMapRegisters * 2;
  544. //
  545. // If the committed map registers is signicantly greater than the
  546. // number allocated then grow the map buffer.
  547. //
  548. if (MasterAdapterObject->CommittedMapRegisters >
  549. MasterAdapterObject->NumberOfMapRegisters ) {
  550. HalpGrowMapBuffers(
  551. MasterAdapterObject,
  552. INCREMENT_MAP_BUFFER_SIZE
  553. );
  554. }
  555. adapterObject->NeedsMapRegisters = TRUE;
  556. } else {
  557. //
  558. // No real map registers were allocated. If this is a master
  559. // device, then the device can have as may registers as it wants.
  560. //
  561. adapterObject->NeedsMapRegisters = FALSE;
  562. adapterObject->MapRegistersPerChannel =
  563. BYTES_TO_PAGES( maximumLength ) + 1;
  564. }
  565. RELEASE_NEW_ADAPTER_LOCK();
  566. adapterObject->IgnoreCount = FALSE;
  567. if (DeviceDescriptor->Version >= DEVICE_DESCRIPTION_VERSION1) {
  568. //
  569. // Move version 1 structure flags.
  570. // IgnoreCount is used on machines where the DMA Counter
  571. // is broken. (Namely PS/1 model 1000s). Setting this
  572. // bit informs the hal not to rely on the DmaCount to determine
  573. // how much data was DMAed.
  574. //
  575. adapterObject->IgnoreCount = DeviceDescriptor->IgnoreCount;
  576. }
  577. adapterObject->Dma32BitAddresses = DeviceDescriptor->Dma32BitAddresses;
  578. adapterObject->Dma64BitAddresses = DeviceDescriptor->Dma64BitAddresses;
  579. adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
  580. *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
  581. adapterObject->MasterDevice = TRUE;
  582. HalDebugPrint((HAL_VERBOSE, "HGA: OUT adapterObject = %p\n",
  583. adapterObject));
  584. HalDebugPrint((HAL_VERBOSE, "HGA: OUT NumberOfMapRegisters = %d\n",
  585. *NumberOfMapRegisters));
  586. return (adapterObject);
  587. }
  588. PHYSICAL_ADDRESS
  589. IoMapTransfer(
  590. IN PADAPTER_OBJECT AdapterObject,
  591. IN PMDL Mdl,
  592. IN PVOID MapRegisterBase,
  593. IN PVOID CurrentVa,
  594. IN OUT PULONG Length,
  595. IN BOOLEAN WriteToDevice
  596. )
  597. /*++
  598. Routine Description:
  599. This routine is invoked to set up the map registers in the DMA controller
  600. to allow a transfer to or from a device.
  601. Arguments:
  602. AdapterObject - Pointer to the adapter object representing the DMA
  603. controller channel that has been allocated.
  604. Mdl - Pointer to the MDL that describes the pages of memory that are
  605. being read or written.
  606. MapRegisterBase - The address of the base map register that has been
  607. allocated to the device driver for use in mapping the transfer.
  608. CurrentVa - Current virtual address in the buffer described by the MDL
  609. that the transfer is being done to or from.
  610. Length - Supplies the length of the transfer. This determines the
  611. number of map registers that need to be written to map the transfer.
  612. Returns the length of the transfer which was actually mapped.
  613. WriteToDevice - Boolean value that indicates whether this is a write
  614. to the device from memory (TRUE), or vice versa.
  615. Return Value:
  616. Returns the logical address that should be used bus master controllers.
  617. --*/
  618. {
  619. ULONG transferLength;
  620. PHYSICAL_ADDRESS returnAddress;
  621. PPFN_NUMBER pageFrame;
  622. ULONG pageOffset;
  623. //
  624. // If the adapter is a 32-bit bus master, take the fast path,
  625. // otherwise call HalpMapTransfer for the slow path
  626. //
  627. if (MapRegisterBase == NULL) {
  628. pageOffset = BYTE_OFFSET(CurrentVa);
  629. //
  630. // Calculate how much of the transfer is contiguous
  631. //
  632. transferLength = PAGE_SIZE - pageOffset;
  633. pageFrame = (PPFN_NUMBER)(Mdl+1);
  634. pageFrame += (((UINT_PTR) CurrentVa - (UINT_PTR) MmGetMdlBaseVa(Mdl)) >> PAGE_SHIFT);
  635. //
  636. // Compute the starting address of the transfer
  637. //
  638. returnAddress.QuadPart = (*pageFrame << PAGE_SHIFT) + pageOffset;
  639. //
  640. // If the transfer is not completely contained within
  641. // a page, call the helper to compute the appropriate
  642. // length.
  643. //
  644. if (transferLength < *Length) {
  645. HalpMapTransferHelper(Mdl, CurrentVa, transferLength, pageFrame, Length);
  646. }
  647. return (returnAddress);
  648. }
  649. return (HalpMapTransfer(AdapterObject,
  650. Mdl,
  651. MapRegisterBase,
  652. CurrentVa,
  653. Length,
  654. WriteToDevice));
  655. }
  656. VOID
  657. HalpMapTransferHelper(
  658. IN PMDL Mdl,
  659. IN PVOID CurrentVa,
  660. IN ULONG TransferLength,
  661. IN PPFN_NUMBER PageFrame,
  662. IN OUT PULONG Length
  663. )
  664. /*++
  665. Routine Description:
  666. Helper routine for bus master transfers that cross a page
  667. boundary. This routine is separated out from the IoMapTransfer
  668. fast path in order to minimize the total instruction path
  669. length taken for the common network case where the entire
  670. buffer being mapped is contained within one page.
  671. Arguments:
  672. Mdl - Pointer to the MDL that describes the pages of memory that are
  673. being read or written.
  674. CurrentVa - Current virtual address in the buffer described by the MDL
  675. that the transfer is being done to or from.
  676. TransferLength = Supplies the current transferLength
  677. PageFrame - Supplies a pointer to the starting page frame of the transfer
  678. Length - Supplies the length of the transfer. This determines the
  679. number of map registers that need to be written to map the transfer.
  680. Returns the length of the transfer which was actually mapped.
  681. Return Value:
  682. None. *Length will be updated
  683. --*/
  684. {
  685. PFN_NUMBER thisPageFrame;
  686. PFN_NUMBER nextPageFrame;
  687. do {
  688. thisPageFrame = *PageFrame;
  689. PageFrame += 1;
  690. nextPageFrame = *PageFrame;
  691. if ((thisPageFrame + 1) != nextPageFrame) {
  692. //
  693. // The next page frame is not contiguous with this one,
  694. // so break the transfer here.
  695. //
  696. break;
  697. }
  698. if (((thisPageFrame ^ nextPageFrame) & 0xFFFFFFFFFFF80000i64) != 0) {
  699. //
  700. // The next page frame is contiguous with this one,
  701. // but it crosses a 4GB boundary, another reason to
  702. // break the transfer.
  703. //
  704. break;
  705. }
  706. TransferLength += PAGE_SIZE;
  707. } while ( TransferLength < *Length );
  708. //
  709. // Limit the Length to the maximum TransferLength.
  710. //
  711. if (TransferLength < *Length) {
  712. *Length = TransferLength;
  713. }
  714. }
  715. PHYSICAL_ADDRESS
  716. HalpMapTransfer(
  717. IN PADAPTER_OBJECT AdapterObject,
  718. IN PMDL Mdl,
  719. IN PVOID MapRegisterBase,
  720. IN PVOID CurrentVa,
  721. IN OUT PULONG Length,
  722. IN BOOLEAN WriteToDevice
  723. )
  724. /*++
  725. Routine Description:
  726. This routine is invoked to set up the map registers in the DMA controller
  727. to allow a transfer to or from a device.
  728. Arguments:
  729. AdapterObject - Pointer to the adapter object representing the DMA
  730. controller channel that has been allocated.
  731. Mdl - Pointer to the MDL that describes the pages of memory that are
  732. being read or written.
  733. MapRegisterBase - The address of the base map register that has been
  734. allocated to the device driver for use in mapping the transfer.
  735. CurrentVa - Current virtual address in the buffer described by the MDL
  736. that the transfer is being done to or from.
  737. Length - Supplies the length of the transfer. This determines the
  738. number of map registers that need to be written to map the transfer.
  739. Returns the length of the transfer which was actually mapped.
  740. WriteToDevice - Boolean value that indicates whether this is a write
  741. to the device from memory (TRUE), or vice versa.
  742. Return Value:
  743. Returns the logical address that should be used bus master controllers.
  744. --*/
  745. {
  746. BOOLEAN useBuffer;
  747. ULONG transferLength;
  748. PHYSICAL_ADDRESS logicalAddress;
  749. PHYSICAL_ADDRESS returnAddress;
  750. ULONG index;
  751. PPFN_NUMBER pageFrame;
  752. PTRANSLATION_ENTRY translationEntry;
  753. ULONG pageOffset;
  754. PHYSICAL_ADDRESS maximumPhysicalAddress;
  755. pageOffset = BYTE_OFFSET(CurrentVa);
  756. //
  757. // Calculate how much of the transfer is contiguous.
  758. //
  759. transferLength = PAGE_SIZE - pageOffset;
  760. pageFrame = (PPFN_NUMBER)(Mdl+1);
  761. pageFrame += (((UINT_PTR)CurrentVa - (UINT_PTR) MmGetMdlBaseVa(Mdl)) >> PAGE_SHIFT);
  762. logicalAddress.QuadPart = (*pageFrame << PAGE_SHIFT) + pageOffset;
  763. // Find a run of contiguous pages in the buffer
  764. while ( transferLength < *Length ) {
  765. if (*pageFrame + 1 != *(pageFrame + 1)) {
  766. break;
  767. }
  768. transferLength += PAGE_SIZE;
  769. pageFrame++;
  770. }
  771. //
  772. // Limit the transferLength to the requested Length.
  773. //
  774. transferLength = transferLength > *Length ? *Length : transferLength;
  775. ASSERT(MapRegisterBase != NULL);
  776. //
  777. // Strip no scatter/gather flag.
  778. //
  779. translationEntry = (PTRANSLATION_ENTRY) ((UINT_PTR) MapRegisterBase & ~NO_SCATTER_GATHER);
  780. if ((UINT_PTR) MapRegisterBase & NO_SCATTER_GATHER
  781. && transferLength < *Length) {
  782. logicalAddress.QuadPart = translationEntry->PhysicalAddress + pageOffset;
  783. translationEntry->Index = COPY_BUFFER;
  784. index = 0;
  785. transferLength = *Length;
  786. useBuffer = TRUE;
  787. } else {
  788. //
  789. // If there are map registers, then update the index to indicate
  790. // how many have been used.
  791. //
  792. useBuffer = FALSE;
  793. index = translationEntry->Index;
  794. translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
  795. CurrentVa,
  796. transferLength
  797. );
  798. //
  799. // PeterJ added the following to catch drivers which don't call
  800. // IoFlushAdapterBuffers. Calling IoMapTransfer repeatedly
  801. // without calling IoFlushAdapterBuffers will run you out of
  802. // map registers,.... Some PCI device drivers think they can
  803. // get away with this because they do 32 bit direct transfers.
  804. // Try plugging one of these into a system with > 4GB and see
  805. // what happens to you.
  806. //
  807. //ASSERT(translationEntry->Index < AdapterObject->NumberOfMapRegisters);
  808. }
  809. //
  810. // It must require memory to be within the adapter's address range. If the
  811. // logical address is greater than that which the adapter can directly
  812. // access then map registers must be used
  813. //
  814. maximumPhysicalAddress =
  815. HalpGetAdapterMaximumPhysicalAddress( AdapterObject );
  816. if ((ULONGLONG)(logicalAddress.QuadPart + transferLength - 1) >
  817. (ULONGLONG)maximumPhysicalAddress.QuadPart) {
  818. logicalAddress.QuadPart = (translationEntry + index)->PhysicalAddress +
  819. pageOffset;
  820. useBuffer = TRUE;
  821. if ((UINT_PTR) MapRegisterBase & NO_SCATTER_GATHER) {
  822. translationEntry->Index = COPY_BUFFER;
  823. index = 0;
  824. }
  825. }
  826. //
  827. // Copy the data if necessary.
  828. //
  829. if (useBuffer && WriteToDevice) {
  830. HalpCopyBufferMap(
  831. Mdl,
  832. translationEntry + index,
  833. CurrentVa,
  834. transferLength,
  835. WriteToDevice
  836. );
  837. }
  838. //
  839. // Return the length.
  840. //
  841. *Length = transferLength;
  842. //
  843. // Return the logical address to transfer to.
  844. //
  845. returnAddress = logicalAddress;
  846. //
  847. // If no adapter was specificed then there is no more work to do so
  848. // return.
  849. //
  850. ASSERT(AdapterObject == NULL || AdapterObject->MasterDevice);
  851. return (returnAddress);
  852. }
  853. BOOLEAN
  854. IoFlushAdapterBuffers(
  855. IN PADAPTER_OBJECT AdapterObject,
  856. IN PMDL Mdl,
  857. IN PVOID MapRegisterBase,
  858. IN PVOID CurrentVa,
  859. IN ULONG Length,
  860. IN BOOLEAN WriteToDevice
  861. )
  862. /*++
  863. Routine Description:
  864. This routine flushes the DMA adapter object buffers. For the Jazz system
  865. its clears the enable flag which aborts the dma.
  866. Arguments:
  867. AdapterObject - Pointer to the adapter object representing the DMA
  868. controller channel.
  869. Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
  870. buffer to/from which the I/O occured.
  871. MapRegisterBase - A pointer to the base of the map registers in the adapter
  872. or DMA controller.
  873. CurrentVa - The current virtual address in the buffer described the the Mdl
  874. where the I/O operation occurred.
  875. Length - Supplies the length of the transfer.
  876. WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
  877. the data transfer was to the device.
  878. Return Value:
  879. TRUE - No errors are detected so the transfer must succeed.
  880. --*/
  881. {
  882. PTRANSLATION_ENTRY translationEntry;
  883. PPFN_NUMBER pageFrame;
  884. ULONG transferLength;
  885. ULONG partialLength;
  886. PHYSICAL_ADDRESS maximumPhysicalAddress;
  887. ULONGLONG maximumPhysicalPage;
  888. ASSERT(AdapterObject == NULL || AdapterObject->MasterDevice);
  889. if (MapRegisterBase == NULL) {
  890. return (TRUE);
  891. }
  892. //
  893. // Determine if the data needs to be copied to the orginal buffer.
  894. // This only occurs if the data tranfer is from the device, the
  895. // MapReisterBase is not NULL and the transfer spans a page.
  896. //
  897. if (!WriteToDevice) {
  898. //
  899. // Strip no scatter/gather flag.
  900. //
  901. translationEntry = (PTRANSLATION_ENTRY) ((UINT_PTR) MapRegisterBase & ~NO_SCATTER_GATHER);
  902. //
  903. // If this is not a master device, then just transfer the buffer.
  904. //
  905. if ((UINT_PTR) MapRegisterBase & NO_SCATTER_GATHER) {
  906. if (translationEntry->Index == COPY_BUFFER) {
  907. //
  908. // The adapter does not support scatter/gather copy the buffer.
  909. //
  910. HalpCopyBufferMap(
  911. Mdl,
  912. translationEntry,
  913. CurrentVa,
  914. Length,
  915. WriteToDevice
  916. );
  917. }
  918. } else {
  919. //
  920. // Cycle through the pages of the transfer to determine if there
  921. // are any which need to be copied back.
  922. //
  923. maximumPhysicalAddress =
  924. HalpGetAdapterMaximumPhysicalAddress( AdapterObject );
  925. maximumPhysicalPage = (maximumPhysicalAddress.QuadPart >> PAGE_SHIFT);
  926. transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
  927. partialLength = transferLength;
  928. pageFrame = (PPFN_NUMBER)(Mdl+1);
  929. pageFrame += (((UINT_PTR) CurrentVa - (UINT_PTR) MmGetMdlBaseVa(Mdl)) >> PAGE_SHIFT);
  930. while ( transferLength <= Length ) {
  931. if (*pageFrame > maximumPhysicalPage) {
  932. HalpCopyBufferMap(
  933. Mdl,
  934. translationEntry,
  935. CurrentVa,
  936. partialLength,
  937. WriteToDevice
  938. );
  939. }
  940. (PCCHAR) CurrentVa += partialLength;
  941. partialLength = PAGE_SIZE;
  942. //
  943. // Note that transferLength indicates the amount which will be
  944. // transfered after the next loop; thus, it is updated with the
  945. // new partial length.
  946. //
  947. transferLength += partialLength;
  948. pageFrame++;
  949. translationEntry++;
  950. }
  951. //
  952. // Process the any remaining residue.
  953. //
  954. partialLength = Length - transferLength + partialLength;
  955. if (partialLength && *pageFrame > maximumPhysicalPage) {
  956. HalpCopyBufferMap(
  957. Mdl,
  958. translationEntry,
  959. CurrentVa,
  960. partialLength,
  961. WriteToDevice
  962. );
  963. }
  964. }
  965. }
  966. //
  967. // Strip no scatter/gather flag.
  968. //
  969. translationEntry = (PTRANSLATION_ENTRY) ((UINT_PTR) MapRegisterBase & ~NO_SCATTER_GATHER);
  970. //
  971. // Clear index in map register.
  972. //
  973. translationEntry->Index = 0;
  974. return TRUE;
  975. }
  976. ULONG
  977. HalReadDmaCounter(
  978. IN PADAPTER_OBJECT AdapterObject
  979. )
  980. /*++
  981. Routine Description:
  982. This function reads the DMA counter and returns the number of bytes left
  983. to be transfered.
  984. Arguments:
  985. AdapterObject - Supplies a pointer to the adapter object to be read.
  986. Return Value:
  987. Returns the number of bytes still be be transfered.
  988. --*/
  989. {
  990. return(0);
  991. }