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.

2044 lines
46 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
  4. contains copyrighted material. Use of this file is restricted
  5. by the provisions of a Motorola Software License Agreement.
  6. Copyright (c) 1993-1996 International Business Machines Corporation
  7. Module Name:
  8. pxfirsup.c
  9. Abstract:
  10. The module provides the support for the fire coral PCI-ISA bridge.
  11. Author:
  12. Jim Wooldridge (jimw@vnet.ibm.com)
  13. Revision History:
  14. --*/
  15. #include "halp.h"
  16. #include "eisa.h"
  17. #include "pxfirsup.h"
  18. #include <pxmemctl.h>
  19. #include "bugcodes.h"
  20. #include "pxidesup.h"
  21. extern UCHAR VectorToIrqlTable[];
  22. #define SioId 0x04848086
  23. PVOID HalpPciIsaBridgeConfigBase;
  24. extern PADAPTER_OBJECT MasterAdapterObject;
  25. extern ULONG HalpPciMaxSlots;
  26. extern ULONG HalpPhase0GetPciDataByOffset();
  27. extern ULONG HalpPhase0SetPciDataByOffset();
  28. //
  29. // Define the context structure for use by the interrupt routine.
  30. //
  31. typedef BOOLEAN (*PSECONDARY_DISPATCH)(
  32. PVOID InterruptRoutine,
  33. PVOID ServiceContext,
  34. PVOID TrapFrame
  35. );
  36. //
  37. // Declare the interupt structure for profile interrupt
  38. //
  39. KINTERRUPT HalpProfileInterrupt;
  40. //
  41. // The following is the interrupt object used for DMA controller interrupts.
  42. // DMA controller interrupts occur when a memory parity error occurs or a
  43. // programming error occurs to the DMA controller.
  44. //
  45. //
  46. // Declare the interupt structure for machine checks
  47. //
  48. KINTERRUPT HalpMachineCheckInterrupt;
  49. //
  50. // Declare the interupt structure for the clock interrupt
  51. //
  52. KINTERRUPT HalpDecrementerInterrupt;
  53. //
  54. // Add spurious and bogus interrupt counts
  55. //
  56. #if DBG
  57. ULONG HalpSpuriousInterruptCount = 0;
  58. ULONG HalpBogusInterruptCount = 0;
  59. #endif
  60. //
  61. // Define Isa bus interrupt affinity.
  62. //
  63. KAFFINITY HalpIsaBusAffinity;
  64. //
  65. // The following function is called when a IDE interrupt occurs.
  66. //
  67. BOOLEAN
  68. HalpHandleIdeInterrupt(
  69. IN PKINTERRUPT Interrupt,
  70. IN PVOID ServiceContext
  71. );
  72. //
  73. // The following function is called when a machine check occurs.
  74. //
  75. BOOLEAN
  76. HalpHandleMachineCheck(
  77. IN PKINTERRUPT Interrupt,
  78. IN PVOID ServiceContext
  79. );
  80. //
  81. // Define save area for ISA adapter objects.
  82. //
  83. PADAPTER_OBJECT HalpIsaAdapter[8];
  84. //
  85. // Define save area for ISA interrupt mask resiters and level\edge control
  86. // registers.
  87. //
  88. #define ISA_CONTROL ((PEISA_CONTROL) HalpIoControlBase)
  89. extern UCHAR HalpSioInterrupt1Mask;
  90. extern UCHAR HalpSioInterrupt2Mask;
  91. extern USHORT Halp8259MaskTable[];
  92. UCHAR HalpSioInterrupt1Mask = 0xff;
  93. UCHAR HalpSioInterrupt2Mask = 0xff;
  94. UCHAR HalpSioInterrupt1Level;
  95. UCHAR HalpSioInterrupt2Level;
  96. #if defined(SOFT_HDD_LAMP)
  97. //
  98. // On PowerPC machines the HDD lamp is software driven. We
  99. // turn it on any time we take an interrupt from a Mass Storage
  100. // Controller (assuming it isn't already on) and turn it off the 2nd
  101. // clock tick after we turn it on if we have not received
  102. // any more MSC interrupts since the first clock tick.
  103. //
  104. // N.B. Hardwired to cause any IDE interrupt to turn the light on.
  105. //
  106. HDD_LAMP_STATUS HalpHddLamp;
  107. ULONG HalpMassStorageControllerVectors = 1 << IDE_DISPATCH_VECTOR;
  108. #endif
  109. BOOLEAN
  110. HalpInitializeInterrupts (
  111. VOID
  112. )
  113. /*++
  114. Routine Description:
  115. This routine is called from phase 0 initialization, it initializes the
  116. 8259 interrupt controller ( currently it masks all 8259 interrupts).
  117. Arguments:
  118. None.
  119. Return Value:
  120. --*/
  121. {
  122. ULONG Vector;
  123. //
  124. // Mask all 8259 interrupts (except the cascade interrupt)
  125. //
  126. for (Vector=0;Vector<16;Vector++) {
  127. if (Vector == 2)
  128. continue;
  129. HalpDisableSioInterrupt(Vector + DEVICE_VECTORS);
  130. }
  131. //
  132. // Reserve the external interrupt vector for exclusive use by the HAL.
  133. //
  134. PCR->ReservedVectors |= (1 << EXTERNAL_INTERRUPT_VECTOR);
  135. return TRUE;
  136. }
  137. BOOLEAN
  138. HalpCreateSioStructures (
  139. VOID
  140. )
  141. /*++
  142. Routine Description:
  143. This routine initializes the structures necessary for SIO operations
  144. and connects the intermediate interrupt dispatcher. It also initializes the
  145. SIO interrupt controller.
  146. Arguments:
  147. None.
  148. Return Value:
  149. If the second level interrupt dispatcher is connected, then a value of
  150. TRUE is returned. Otherwise, a value of FALSE is returned.
  151. --*/
  152. {
  153. UCHAR DataByte;
  154. KIRQL oldIrql;
  155. //
  156. // Initialize the Machine Check interrupt handler
  157. //
  158. if (HalpEnableInterruptHandler(&HalpMachineCheckInterrupt,
  159. HalpHandleMachineCheck,
  160. NULL,
  161. NULL,
  162. MACHINE_CHECK_VECTOR,
  163. MACHINE_CHECK_LEVEL,
  164. MACHINE_CHECK_LEVEL,
  165. Latched,
  166. FALSE,
  167. 0,
  168. FALSE,
  169. InternalUsage,
  170. MACHINE_CHECK_VECTOR
  171. ) == FALSE) {
  172. KeBugCheck(HAL_INITIALIZATION_FAILED);
  173. }
  174. //
  175. // Enable NMI IOCHK# and PCI SERR#
  176. //
  177. DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus);
  178. WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus,
  179. DataByte & ~DISABLE_IOCHK_NMI & ~DISABLE_PCI_SERR_NMI);
  180. //
  181. // Clear the SIO NMI disable bit. This bit is the high order of the
  182. // NMI enable register.
  183. //
  184. DataByte = 0;
  185. WRITE_REGISTER_UCHAR(
  186. &((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
  187. DataByte
  188. );
  189. //
  190. // Connect the external interrupt handler
  191. //
  192. PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
  193. (PKINTERRUPT_ROUTINE)HalpHandleExternalInterrupt;
  194. //
  195. // All IDE interrupts come thru the IDE_DISPATCH_VECTOR. Install
  196. // a handler for that vector that will determine the actual IDE
  197. // device and dispatch appropriately.
  198. //
  199. PCR->InterruptRoutine[DEVICE_VECTORS + IDE_DISPATCH_VECTOR] =
  200. (PKINTERRUPT_ROUTINE)HalpHandleIdeInterrupt;
  201. //
  202. // register the interrupt vector
  203. //
  204. HalpRegisterVector(InternalUsage,
  205. EXTERNAL_INTERRUPT_VECTOR,
  206. EXTERNAL_INTERRUPT_VECTOR,
  207. HIGH_LEVEL);
  208. // Connect directly to the decrementer handler. This is done
  209. // directly rather than thru HalpEnableInterruptHandler due to
  210. // special handling required because the handler calls KdPollBreakIn().
  211. //
  212. PCR->InterruptRoutine[DECREMENT_VECTOR] =
  213. (PKINTERRUPT_ROUTINE)HalpHandleDecrementerInterrupt;
  214. //
  215. // Initialize and connect the Timer 1 interrupt (IRQ0)
  216. //
  217. if (HalpEnableInterruptHandler( &HalpProfileInterrupt,
  218. (PKSERVICE_ROUTINE) HalpHandleProfileInterrupt,
  219. (PVOID) NULL,
  220. (PKSPIN_LOCK)NULL,
  221. PROFILE_VECTOR,
  222. PROFILE_LEVEL,
  223. PROFILE_LEVEL,
  224. Latched,
  225. TRUE,
  226. 0,
  227. FALSE,
  228. DeviceUsage,
  229. PROFILE_VECTOR
  230. ) == FALSE) {
  231. KeBugCheck(HAL_INITIALIZATION_FAILED);
  232. }
  233. //
  234. // Disable Timer 1; only used by profiling
  235. //
  236. HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL);
  237. //
  238. // Set default profile rate
  239. //
  240. HalSetProfileInterval(5000);
  241. //
  242. // Raise the IRQL while the SIO interrupt controller is initalized.
  243. //
  244. KeRaiseIrql(CLOCK2_LEVEL, &oldIrql);
  245. //
  246. // Initialize any planar registers
  247. //
  248. HalpInitPlanar();
  249. //
  250. // Initialize the PCI/ISA bridge chip
  251. //
  252. HalpInitPciIsaBridge();
  253. //
  254. // Initialize the SIO interrupt controller. There are two cascaded
  255. // interrupt controllers, each of which must initialized with 4 initialize
  256. // control words.
  257. //
  258. DataByte = 0;
  259. ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
  260. ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
  261. WRITE_REGISTER_UCHAR(
  262. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
  263. DataByte
  264. );
  265. WRITE_REGISTER_UCHAR(
  266. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
  267. DataByte
  268. );
  269. //
  270. // The second intitialization control word sets the iterrupt vector to
  271. // 0-15.
  272. //
  273. DataByte = 0;
  274. WRITE_REGISTER_UCHAR(
  275. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
  276. DataByte
  277. );
  278. DataByte = 0x08;
  279. WRITE_REGISTER_UCHAR(
  280. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
  281. DataByte
  282. );
  283. //
  284. // The thrid initialization control word set the controls for slave mode.
  285. // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
  286. //
  287. DataByte = 1 << SLAVE_IRQL_LEVEL;
  288. WRITE_REGISTER_UCHAR(
  289. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
  290. DataByte
  291. );
  292. DataByte = SLAVE_IRQL_LEVEL;
  293. WRITE_REGISTER_UCHAR(
  294. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
  295. DataByte
  296. );
  297. //
  298. // The fourth initialization control word is used to specify normal
  299. // end-of-interrupt mode and not special-fully-nested mode.
  300. //
  301. DataByte = 0;
  302. ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
  303. WRITE_REGISTER_UCHAR(
  304. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
  305. DataByte
  306. );
  307. WRITE_REGISTER_UCHAR(
  308. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
  309. DataByte
  310. );
  311. //
  312. // Disable all of the interrupts except the slave.
  313. //
  314. HalpSioInterrupt1Mask = (UCHAR) ~(1 << SLAVE_IRQL_LEVEL);
  315. WRITE_REGISTER_UCHAR(
  316. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
  317. HalpSioInterrupt1Mask
  318. );
  319. HalpSioInterrupt2Mask = 0xFF;
  320. WRITE_REGISTER_UCHAR(
  321. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
  322. HalpSioInterrupt2Mask
  323. );
  324. //
  325. // Initialize the edge/level register masks to 0 which is the default
  326. // edge sensitive value.
  327. //
  328. HalpSioInterrupt1Level = 0;
  329. HalpSioInterrupt2Level = 0;
  330. //
  331. // Enable the clock interrupt
  332. //
  333. HalpUpdateDecrementer(1000); // Get those decrementer ticks going
  334. //
  335. // Set ISA bus interrupt affinity.
  336. //
  337. HalpIsaBusAffinity = PCR->SetMember;
  338. //
  339. // Restore IRQL level.
  340. //
  341. KeLowerIrql(oldIrql);
  342. //
  343. // DMA command - set assert level
  344. //
  345. DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus);
  346. WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus,
  347. DataByte & ~DACK_ASSERT_HIGH & ~DREQ_ASSERT_LOW);
  348. //
  349. // Initialize the DMA mode registers to a default value.
  350. // Disable all of the DMA channels except channel 4 which is that
  351. // cascade of channels 0-3.
  352. //
  353. WRITE_REGISTER_UCHAR(
  354. &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort.AllMask,
  355. 0x0F
  356. );
  357. WRITE_REGISTER_UCHAR(
  358. &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort.AllMask,
  359. 0x0E
  360. );
  361. return(TRUE);
  362. }
  363. BOOLEAN
  364. HalpInitPciIsaBridge (
  365. VOID
  366. )
  367. {
  368. UCHAR DataByte;
  369. BOOLEAN Found;
  370. ULONG SlotNumber;
  371. ULONG ChipId;
  372. ULONG BufferLength;
  373. Found = FALSE;
  374. SlotNumber = 0;
  375. while (!Found && SlotNumber < HalpPciMaxSlots) {
  376. BufferLength = HalpPhase0GetPciDataByOffset(0,
  377. SlotNumber,
  378. &ChipId,
  379. 0,
  380. sizeof(ChipId));
  381. if (ChipId == SioId)
  382. Found = TRUE;
  383. else
  384. SlotNumber++;
  385. }
  386. //
  387. // Make sure that we found a valid chip id
  388. //
  389. if (!Found)
  390. return FALSE;
  391. //
  392. // Define macros for reading and writing to the SIO config space
  393. //
  394. #define READ_SIO_CONFIG_UCHAR(offset,byte) \
  395. ( \
  396. HalpPhase0GetPciDataByOffset( \
  397. 0, \
  398. SlotNumber, \
  399. &byte, \
  400. FIELD_OFFSET(SIO_CONFIG,offset), \
  401. 1 \
  402. ) \
  403. )
  404. #define WRITE_SIO_CONFIG_UCHAR(offset,byte) \
  405. ( \
  406. HalpPhase0SetPciDataByOffset( \
  407. 0, \
  408. SlotNumber, \
  409. &byte, \
  410. FIELD_OFFSET(SIO_CONFIG,offset), \
  411. 1 \
  412. ) \
  413. )
  414. //
  415. // Enable ISA Master line buffering
  416. //
  417. READ_SIO_CONFIG_UCHAR(PciControl,DataByte);
  418. DataByte |= ENABLE_PCI_POSTED_WRITE_BUFFER
  419. | ENABLE_ISA_MASTER_LINE_BUFFER
  420. | EANBLE_DMA_LINE_BUFFER;
  421. WRITE_SIO_CONFIG_UCHAR(PciControl, DataByte );
  422. //
  423. // Disable Gauranteed Access Time Mode
  424. //
  425. READ_SIO_CONFIG_UCHAR(PciArbiterControl,DataByte);
  426. DataByte &= ~ENABLE_GAT;
  427. WRITE_SIO_CONFIG_UCHAR(PciArbiterControl, DataByte);
  428. //
  429. // Initialize SuperIO chip
  430. //
  431. if (!HalpInitSuperIo())
  432. return FALSE;
  433. //
  434. // Utility Bus A chip select
  435. //
  436. READ_SIO_CONFIG_UCHAR(UtilityBusEnableA,DataByte);
  437. DataByte |= ENABLE_RTC | ENABLE_KEYBOARD & ~ENABLE_IDE_DECODE;
  438. WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableA, DataByte);
  439. //
  440. // Utility Bus B chip select
  441. //
  442. READ_SIO_CONFIG_UCHAR(UtilityBusEnableB,DataByte);
  443. DataByte |= ENABLE_RAM_DECODE | ENABLE_PORT92 | DISABLE_PARALLEL_PORT
  444. | DISABLE_SERIAL_PORTA | DISABLE_SERIAL_PORTB;
  445. WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableB, DataByte);
  446. return TRUE;
  447. }
  448. BOOLEAN
  449. HalpMapIoControlSpace (
  450. VOID
  451. )
  452. /*++
  453. Routine Description:
  454. This routine maps the HAL SIO control space for a PowerPC system.
  455. Arguments:
  456. None.
  457. Return Value:
  458. If the initialization is successfully completed, than a value of TRUE
  459. is returned. Otherwise, a value of FALSE is returned.
  460. --*/
  461. {
  462. PHYSICAL_ADDRESS physicalAddress;
  463. //
  464. // Map SIO control space.
  465. //
  466. physicalAddress.HighPart = 0;
  467. physicalAddress.LowPart = IO_CONTROL_PHYSICAL_BASE;
  468. HalpIoControlBase = MmMapIoSpace(physicalAddress,
  469. PAGE_SIZE * 16,
  470. FALSE);
  471. if (HalpIoControlBase == NULL)
  472. return FALSE;
  473. else
  474. return TRUE;
  475. }
  476. BOOLEAN
  477. HalpHandleExternalInterrupt(
  478. IN PKINTERRUPT Interrupt,
  479. IN PVOID ServiceContext,
  480. IN PVOID TrapFrame
  481. )
  482. /*++
  483. Routine Description:
  484. This routine is entered as the result of an interrupt being generated
  485. via the vector that is connected to an interrupt object that describes
  486. the SIO device interrupts. Its function is to call the second
  487. level interrupt dispatch routine and acknowledge the interrupt at the SIO
  488. controller.
  489. N.B. This routine in entered and left with external interrupts disabled.
  490. Arguments:
  491. Interrupt - Supplies a pointer to the interrupt object.
  492. ServiceContext - Supplies a pointer to the SIO interrupt acknowledge
  493. register.
  494. None.
  495. Return Value:
  496. Returns the value returned from the second level routine.
  497. --*/
  498. {
  499. PSECONDARY_DISPATCH SioHandler;
  500. PKINTERRUPT SioInterrupt;
  501. USHORT interruptVector;
  502. BOOLEAN returnValue;
  503. UCHAR OldIrql;
  504. USHORT Isr;
  505. UCHAR Irql;
  506. PUCHAR PIC_Address;
  507. UCHAR PIC_Mask;
  508. //
  509. // Read the interrupt vector.
  510. //
  511. interruptVector = READ_REGISTER_UCHAR(HalpInterruptBase);
  512. //
  513. // check for spurious interrupt
  514. //
  515. if (interruptVector == SPURIOUS_VECTOR) {
  516. WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0,
  517. 0x0B);
  518. Isr = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0);
  519. if (!(Isr & 0x80)) {
  520. //
  521. // Spurious interrupt
  522. //
  523. #if DBG
  524. //DbgPrint("A spurious interrupt occurred. \n");
  525. HalpSpuriousInterruptCount++;
  526. #endif
  527. return(0);
  528. }
  529. }
  530. #if defined(SOFT_HDD_LAMP)
  531. if ( HalpMassStorageControllerVectors & (1 << interruptVector) ) {
  532. //
  533. // On any Mass Storage Controller interrupt, light the HDD lamp.
  534. // The system timer routines will turn it off again in a little
  535. // while.
  536. //
  537. if ( !HalpHddLamp.Count ) {
  538. *(PUCHAR)((PUCHAR)HalpIoControlBase + HDD_LAMP_PORT) = 1;
  539. }
  540. HalpHddLamp.Count = SOFT_HDD_TICK_COUNT;
  541. }
  542. #endif
  543. //
  544. // raise irql
  545. //
  546. Irql = VectorToIrqlTable[interruptVector];
  547. //
  548. // Raise Irql to appropriate device level
  549. //
  550. OldIrql = PCR->CurrentIrql;
  551. PCR->CurrentIrql = Irql;
  552. HalpEnableInterrupts();
  553. //
  554. // Dispatch to the secondary interrupt service routine.
  555. //
  556. SioHandler = (PSECONDARY_DISPATCH)
  557. PCR->InterruptRoutine[DEVICE_VECTORS + interruptVector];
  558. SioInterrupt = CONTAINING_RECORD(SioHandler,
  559. KINTERRUPT,
  560. DispatchCode[0]);
  561. returnValue = SioHandler(SioInterrupt,
  562. SioInterrupt->ServiceContext,
  563. TrapFrame
  564. );
  565. //
  566. // Dismiss the interrupt in the SIO interrupt controllers. We disable
  567. // interrupts first so we won't get multiple interrupts at this level
  568. // without popping the stack.
  569. //
  570. HalpDisableInterrupts();
  571. //
  572. // If this is a cascaded interrupt then the interrupt must be dismissed in
  573. // both controllers.
  574. //
  575. if (interruptVector & 0x08) {
  576. WRITE_REGISTER_UCHAR(
  577. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
  578. NONSPECIFIC_END_OF_INTERRUPT
  579. );
  580. }
  581. WRITE_REGISTER_UCHAR(
  582. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
  583. NONSPECIFIC_END_OF_INTERRUPT
  584. );
  585. //
  586. // Lower IRQL but leave external interrupts disabled.
  587. // Return to caller with interrupts disabled.
  588. //
  589. PCR->CurrentIrql = OldIrql;
  590. //
  591. // Partial lazy irql - if hardware irql mask isn't what is should be
  592. // set it and the interrupt controllers mask.
  593. //
  594. if (HALPCR->HardPriority > PCR->CurrentIrql) {
  595. HALPCR->HardPriority = OldIrql;
  596. PIC_Mask = HalpSioInterrupt1Mask | (Halp8259MaskTable[OldIrql] & 0x00FF);
  597. PIC_Address = &(ISA_CONTROL->Interrupt1ControlPort1);
  598. WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
  599. //
  600. // Get contoller 2 interrupt mask
  601. //
  602. PIC_Mask = HalpSioInterrupt2Mask | (Halp8259MaskTable[OldIrql] >> 8 );
  603. PIC_Address = &(ISA_CONTROL->Interrupt2ControlPort1);
  604. WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
  605. }
  606. return(returnValue);
  607. }
  608. VOID
  609. HalpDisableSioInterrupt(
  610. IN ULONG Vector
  611. )
  612. /*++
  613. Routine Description:
  614. This function Disables the SIO interrupt.
  615. Arguments:
  616. Vector - Supplies the vector of the ESIA interrupt that is Disabled.
  617. Return Value:
  618. None.
  619. --*/
  620. {
  621. //
  622. // Calculate the SIO interrupt vector.
  623. //
  624. Vector -= DEVICE_VECTORS;
  625. //
  626. // Determine if this vector is for interrupt controller 1 or 2.
  627. //
  628. if (Vector & 0x08) {
  629. //
  630. // The interrupt is in controller 2.
  631. //
  632. Vector &= 0x7;
  633. HalpSioInterrupt2Mask |= (UCHAR) 1 << Vector;
  634. WRITE_REGISTER_UCHAR(
  635. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
  636. HalpSioInterrupt2Mask
  637. );
  638. } else {
  639. //
  640. // The interrupt is in controller 1.
  641. //
  642. Vector &= 0x7;
  643. HalpSioInterrupt1Mask |= (ULONG) 1 << Vector;
  644. WRITE_REGISTER_UCHAR(
  645. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
  646. HalpSioInterrupt1Mask
  647. );
  648. }
  649. }
  650. VOID
  651. HalpIsaMapTransfer(
  652. IN PADAPTER_OBJECT AdapterObject,
  653. IN ULONG Offset,
  654. IN ULONG Length,
  655. IN BOOLEAN WriteToDevice
  656. )
  657. /*++
  658. Routine Description:
  659. This function programs the SIO DMA controller for a transfer.
  660. Arguments:
  661. Adapter - Supplies the DMA adapter object to be programed.
  662. Offset - Supplies the logical address to use for the transfer.
  663. Length - Supplies the length of the transfer in bytes.
  664. WriteToDevice - Indicates the direction of the transfer.
  665. Return Value:
  666. None.
  667. --*/
  668. {
  669. PUCHAR BytePtr;
  670. UCHAR adapterMode;
  671. UCHAR dataByte;
  672. KIRQL Irql;
  673. ASSERT(Offset >= IO_CONTROL_PHYSICAL_BASE);
  674. adapterMode = AdapterObject->AdapterMode;
  675. //
  676. // Check to see if this request is for a master I/O card.
  677. //
  678. if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
  679. //
  680. // Set the mode, Disable the request and return.
  681. //
  682. if (AdapterObject->AdapterNumber == 1) {
  683. //
  684. // This request is for DMA controller 1
  685. //
  686. PDMA1_CONTROL dmaControl;
  687. dmaControl = AdapterObject->AdapterBaseVa;
  688. WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
  689. //
  690. // Unmask the DMA channel.
  691. //
  692. WRITE_REGISTER_UCHAR(
  693. &dmaControl->SingleMask,
  694. (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
  695. );
  696. } else {
  697. //
  698. // This request is for DMA controller 1
  699. //
  700. PDMA2_CONTROL dmaControl;
  701. dmaControl = AdapterObject->AdapterBaseVa;
  702. WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
  703. //
  704. // Unmask the DMA channel.
  705. //
  706. WRITE_REGISTER_UCHAR(
  707. &dmaControl->SingleMask,
  708. (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
  709. );
  710. }
  711. return;
  712. }
  713. //
  714. // Determine the mode based on the transfer direction.
  715. //
  716. ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
  717. WRITE_TRANSFER : READ_TRANSFER);
  718. BytePtr = (PUCHAR) &Offset;
  719. if (AdapterObject->Width16Bits) {
  720. //
  721. // If this is a 16 bit transfer then adjust the length and the address
  722. // for the 16 bit DMA mode.
  723. //
  724. Length >>= 1;
  725. //
  726. // In 16 bit DMA mode the low 16 bits are shifted right one and the
  727. // page register value is unchanged. So save the page register value
  728. // and shift the logical address then restore the page value.
  729. //
  730. dataByte = BytePtr[2];
  731. Offset >>= 1;
  732. BytePtr[2] = dataByte;
  733. }
  734. //
  735. // grab the spinlock for the system DMA controller
  736. //
  737. KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
  738. //
  739. // Determine the controller number based on the Adapter number.
  740. //
  741. if (AdapterObject->AdapterNumber == 1) {
  742. //
  743. // This request is for DMA controller 1
  744. //
  745. PDMA1_CONTROL dmaControl;
  746. dmaControl = AdapterObject->AdapterBaseVa;
  747. WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
  748. WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
  749. WRITE_REGISTER_UCHAR(
  750. &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
  751. .DmaBaseAddress,
  752. BytePtr[0]
  753. );
  754. WRITE_REGISTER_UCHAR(
  755. &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
  756. .DmaBaseAddress,
  757. BytePtr[1]
  758. );
  759. WRITE_REGISTER_UCHAR(
  760. ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
  761. (ULONG)AdapterObject->PagePort,
  762. BytePtr[2]
  763. );
  764. WRITE_REGISTER_UCHAR(
  765. ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
  766. (ULONG)AdapterObject->PagePort,
  767. BytePtr[3]
  768. );
  769. //
  770. // Notify DMA chip of the length to transfer.
  771. //
  772. WRITE_REGISTER_UCHAR(
  773. &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
  774. .DmaBaseCount,
  775. (UCHAR) ((Length - 1) & 0xff)
  776. );
  777. WRITE_REGISTER_UCHAR(
  778. &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
  779. .DmaBaseCount,
  780. (UCHAR) ((Length - 1) >> 8)
  781. );
  782. //
  783. // Set the DMA chip to read or write mode; and unmask it.
  784. //
  785. WRITE_REGISTER_UCHAR(
  786. &dmaControl->SingleMask,
  787. (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
  788. );
  789. } else {
  790. //
  791. // This request is for DMA controller 2
  792. //
  793. PDMA2_CONTROL dmaControl;
  794. dmaControl = AdapterObject->AdapterBaseVa;
  795. WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
  796. WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
  797. WRITE_REGISTER_UCHAR(
  798. &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
  799. .DmaBaseAddress,
  800. BytePtr[0]
  801. );
  802. WRITE_REGISTER_UCHAR(
  803. &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
  804. .DmaBaseAddress,
  805. BytePtr[1]
  806. );
  807. WRITE_REGISTER_UCHAR(
  808. ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
  809. (ULONG)AdapterObject->PagePort,
  810. BytePtr[2]
  811. );
  812. WRITE_REGISTER_UCHAR(
  813. ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
  814. (ULONG)AdapterObject->PagePort,
  815. BytePtr[3]
  816. );
  817. //
  818. // Notify DMA chip of the length to transfer.
  819. //
  820. WRITE_REGISTER_UCHAR(
  821. &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
  822. .DmaBaseCount,
  823. (UCHAR) ((Length - 1) & 0xff)
  824. );
  825. WRITE_REGISTER_UCHAR(
  826. &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
  827. .DmaBaseCount,
  828. (UCHAR) ((Length - 1) >> 8)
  829. );
  830. //
  831. // Set the DMA chip to read or write mode; and unmask it.
  832. //
  833. WRITE_REGISTER_UCHAR(
  834. &dmaControl->SingleMask,
  835. (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
  836. );
  837. }
  838. KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
  839. }
  840. VOID
  841. HalpEnableSioInterrupt(
  842. IN ULONG Vector,
  843. IN KINTERRUPT_MODE InterruptMode
  844. )
  845. /*++
  846. Routine Description:
  847. This function enables the SIO interrupt and sets
  848. the level/edge register to the requested value.
  849. Arguments:
  850. Vector - Supplies the vector of the interrupt that is enabled.
  851. InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
  852. Latched.
  853. Return Value:
  854. None.
  855. --*/
  856. {
  857. //
  858. // Calculate the SIO interrupt vector.
  859. //
  860. Vector -= DEVICE_VECTORS;
  861. //
  862. // Determine if this vector is for interrupt controller 1 or 2.
  863. //
  864. if (Vector & 0x08) {
  865. //
  866. // The interrupt is in controller 2.
  867. //
  868. Vector &= 0x7;
  869. HalpSioInterrupt2Mask &= (UCHAR) ~(1 << Vector);
  870. WRITE_REGISTER_UCHAR(
  871. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
  872. HalpSioInterrupt2Mask
  873. );
  874. //
  875. // Set the level/edge control register.
  876. //
  877. if (InterruptMode == LevelSensitive) {
  878. HalpSioInterrupt2Level |= (UCHAR) (1 << Vector);
  879. } else {
  880. HalpSioInterrupt2Level &= (UCHAR) ~(1 << Vector);
  881. }
  882. WRITE_REGISTER_UCHAR(
  883. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2EdgeLevel,
  884. HalpSioInterrupt2Level
  885. );
  886. } else {
  887. //
  888. // The interrupt is in controller 1.
  889. //
  890. Vector &= 0x7;
  891. HalpSioInterrupt1Mask &= (UCHAR) ~(1 << Vector);
  892. WRITE_REGISTER_UCHAR(
  893. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
  894. HalpSioInterrupt1Mask
  895. );
  896. //
  897. // Set the level/edge control register.
  898. //
  899. if (InterruptMode == LevelSensitive) {
  900. HalpSioInterrupt1Level |= (UCHAR) (1 << Vector);
  901. } else {
  902. HalpSioInterrupt1Level &= (UCHAR) ~(1 << Vector);
  903. }
  904. WRITE_REGISTER_UCHAR(
  905. &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1EdgeLevel,
  906. HalpSioInterrupt1Level
  907. );
  908. }
  909. }
  910. PADAPTER_OBJECT
  911. HalpAllocateIsaAdapter(
  912. IN PDEVICE_DESCRIPTION DeviceDescriptor,
  913. OUT PULONG NumberOfMapRegisters
  914. )
  915. /*++
  916. Routine Description:
  917. This function allocates an ISA adapter object according to the
  918. specification supplied in the device description. The necessary device
  919. descriptor information is saved. If there is
  920. no existing adapter object for this channel then a new one is allocated.
  921. The saved information in the adapter object is used to set the various DMA
  922. modes when the channel is allocated or a map transfer is done.
  923. Arguments:
  924. DeviceDescription - Supplies the description of the device which want to
  925. use the DMA adapter.
  926. NumberofMapRegisters - number of map registers required for the adapter
  927. object created
  928. Return Value:
  929. Returns a pointer to the newly created adapter object or NULL if one
  930. cannot be created.
  931. --*/
  932. {
  933. PADAPTER_OBJECT adapterObject;
  934. PVOID adapterBaseVa;
  935. ULONG channelNumber;
  936. ULONG numberOfMapRegisters;
  937. ULONG controllerNumber;
  938. DMA_EXTENDED_MODE extendedMode;
  939. UCHAR adapterMode;
  940. BOOLEAN useChannel;
  941. ULONG maximumLength;
  942. //
  943. // Determine if the the channel number is important. Master cards
  944. // do not use a channel number.
  945. //
  946. if ((DeviceDescriptor->Master) && (DeviceDescriptor->InterfaceType != Isa)) {
  947. useChannel = FALSE;
  948. } else {
  949. useChannel = TRUE;
  950. }
  951. //
  952. // Channel 4 cannot be used since it is used for chaining. Return null if
  953. // it is requested.
  954. //
  955. if ((DeviceDescriptor->DmaChannel == 4 ||
  956. DeviceDescriptor->DmaChannel > 7) && useChannel) {
  957. return(NULL);
  958. }
  959. //
  960. // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
  961. // macro works correctly.
  962. //
  963. maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
  964. //
  965. // Determine the number of map registers for this device.
  966. //
  967. if (DeviceDescriptor->ScatterGather &&
  968. !(DeviceDescriptor->InterfaceType == Isa &&
  969. DeviceDescriptor->Master)) {
  970. //
  971. // Scatter gather not supported in SIO
  972. //
  973. if (!DeviceDescriptor->Master)
  974. //
  975. // one map register will be required when the the SIO supports this
  976. //
  977. // numberOfMapRegisters = 1;
  978. return NULL;
  979. //
  980. // Since the device support scatter/Gather then map registers are not
  981. // required.
  982. //
  983. numberOfMapRegisters = 0;
  984. } else {
  985. //
  986. // Determine the number of map registers required based on the maximum
  987. // transfer length, up to a maximum number.
  988. //
  989. numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
  990. + 1;
  991. numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
  992. MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
  993. //
  994. // If the device is not a master then it only needs one map register
  995. // and does scatter/Gather.
  996. //
  997. if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
  998. numberOfMapRegisters = 1;
  999. }
  1000. }
  1001. //
  1002. // Set the channel number number.
  1003. //
  1004. channelNumber = DeviceDescriptor->DmaChannel & 0x03;
  1005. //
  1006. // Set the adapter base address to the Base address register and controller
  1007. // number.
  1008. //
  1009. if (!(DeviceDescriptor->DmaChannel & 0x04)) {
  1010. controllerNumber = 1;
  1011. adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort;
  1012. } else {
  1013. controllerNumber = 2;
  1014. adapterBaseVa = &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort;
  1015. }
  1016. //
  1017. // Determine if a new adapter object is necessary. If so then allocate it.
  1018. //
  1019. if (useChannel && HalpIsaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
  1020. adapterObject = HalpIsaAdapter[DeviceDescriptor->DmaChannel];
  1021. if (adapterObject->NeedsMapRegisters) {
  1022. if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
  1023. adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
  1024. }
  1025. }
  1026. } else {
  1027. //
  1028. // Allocate an adapter object.
  1029. //
  1030. adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
  1031. numberOfMapRegisters,
  1032. adapterBaseVa,
  1033. NULL
  1034. );
  1035. if (adapterObject == NULL) {
  1036. return(NULL);
  1037. }
  1038. if (useChannel) {
  1039. HalpIsaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
  1040. }
  1041. //
  1042. // Set the maximum number of map registers for this channel bus on
  1043. // the number requested and the type of device.
  1044. //
  1045. if (numberOfMapRegisters) {
  1046. //
  1047. // The speicified number of registers are actually allowed to be
  1048. // allocated.
  1049. //
  1050. adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
  1051. //
  1052. // Increase the commitment for the map registers.
  1053. //
  1054. if (DeviceDescriptor->Master) {
  1055. //
  1056. // Master I/O devices use several sets of map registers double
  1057. // their commitment.
  1058. //
  1059. MasterAdapterObject->CommittedMapRegisters +=
  1060. numberOfMapRegisters * 2;
  1061. } else {
  1062. MasterAdapterObject->CommittedMapRegisters +=
  1063. numberOfMapRegisters;
  1064. }
  1065. //
  1066. // If the committed map registers is signicantly greater than the
  1067. // number allocated then grow the map buffer.
  1068. //
  1069. if (MasterAdapterObject->CommittedMapRegisters >
  1070. MasterAdapterObject->NumberOfMapRegisters &&
  1071. MasterAdapterObject->CommittedMapRegisters -
  1072. MasterAdapterObject->NumberOfMapRegisters >
  1073. MAXIMUM_ISA_MAP_REGISTER ) {
  1074. HalpGrowMapBuffers(
  1075. MasterAdapterObject,
  1076. INCREMENT_MAP_BUFFER_SIZE
  1077. );
  1078. }
  1079. adapterObject->NeedsMapRegisters = TRUE;
  1080. } else {
  1081. //
  1082. // No real map registers were allocated. If this is a master
  1083. // device, then the device can have as may registers as it wants.
  1084. //
  1085. adapterObject->NeedsMapRegisters = FALSE;
  1086. if (DeviceDescriptor->Master) {
  1087. adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
  1088. maximumLength
  1089. )
  1090. + 1;
  1091. } else {
  1092. //
  1093. // The device only gets one register. It must call
  1094. // IoMapTransfer repeatedly to do a large transfer.
  1095. //
  1096. adapterObject->MapRegistersPerChannel = 1;
  1097. }
  1098. }
  1099. }
  1100. adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
  1101. if (DeviceDescriptor->Master) {
  1102. adapterObject->MasterDevice = TRUE;
  1103. } else {
  1104. adapterObject->MasterDevice = FALSE;
  1105. }
  1106. if (DeviceDescriptor->Master && (DeviceDescriptor->InterfaceType == Isa)) {
  1107. adapterObject->IsaBusMaster = TRUE;
  1108. } else {
  1109. adapterObject->IsaBusMaster = FALSE;
  1110. }
  1111. //
  1112. // If the channel number is not used then we are finished. The rest of
  1113. // the work deals with channels.
  1114. //
  1115. *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
  1116. if (!useChannel) {
  1117. adapterObject->PagePort = (PVOID) (~0x0);
  1118. ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
  1119. return(adapterObject);
  1120. }
  1121. //
  1122. // Setup the pointers to all the random registers.
  1123. //
  1124. adapterObject->ChannelNumber = (UCHAR) channelNumber;
  1125. if (controllerNumber == 1) {
  1126. switch ((UCHAR)channelNumber) {
  1127. case 0:
  1128. adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
  1129. break;
  1130. case 1:
  1131. adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
  1132. break;
  1133. case 2:
  1134. adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
  1135. break;
  1136. case 3:
  1137. adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
  1138. break;
  1139. }
  1140. //
  1141. // Set the adapter number.
  1142. //
  1143. adapterObject->AdapterNumber = 1;
  1144. //
  1145. // Save the extended mode register address.
  1146. //
  1147. adapterBaseVa =
  1148. &((PEISA_CONTROL) HalpIoControlBase)->Dma1ExtendedModePort;
  1149. } else {
  1150. switch (channelNumber) {
  1151. case 1:
  1152. adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
  1153. break;
  1154. case 2:
  1155. adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
  1156. break;
  1157. case 3:
  1158. adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
  1159. break;
  1160. }
  1161. //
  1162. // Set the adapter number.
  1163. //
  1164. adapterObject->AdapterNumber = 2;
  1165. //
  1166. // Save the extended mode register address.
  1167. //
  1168. adapterBaseVa =
  1169. &((PEISA_CONTROL) HalpIoControlBase)->Dma2ExtendedModePort;
  1170. }
  1171. adapterObject->Width16Bits = FALSE;
  1172. //
  1173. // Initialzie the extended mode port.
  1174. //
  1175. *((PUCHAR) &extendedMode) = 0;
  1176. extendedMode.ChannelNumber = (UCHAR) channelNumber;
  1177. switch (DeviceDescriptor->DmaSpeed) {
  1178. case Compatible:
  1179. extendedMode.TimingMode = COMPATIBLITY_TIMING;
  1180. break;
  1181. case TypeA:
  1182. extendedMode.TimingMode = TYPE_A_TIMING;
  1183. break;
  1184. case TypeB:
  1185. extendedMode.TimingMode = TYPE_B_TIMING;
  1186. break;
  1187. case TypeC:
  1188. extendedMode.TimingMode = BURST_TIMING;
  1189. break;
  1190. default:
  1191. ObDereferenceObject( adapterObject );
  1192. return(NULL);
  1193. }
  1194. switch (DeviceDescriptor->DmaWidth) {
  1195. case Width8Bits:
  1196. extendedMode.TransferSize = BY_BYTE_8_BITS;
  1197. break;
  1198. case Width16Bits:
  1199. extendedMode.TransferSize = BY_BYTE_16_BITS;
  1200. //
  1201. // Note Width16bits should not be set here because there is no need
  1202. // to shift the address and the transfer count.
  1203. //
  1204. break;
  1205. default:
  1206. ObDereferenceObject( adapterObject );
  1207. return(NULL);
  1208. }
  1209. //
  1210. // bit 2 in the extended mode register must be set to 1 for ISA busmastering to work
  1211. // correctly on Firecoral
  1212. //
  1213. if (DeviceDescriptor->Master) {
  1214. extendedMode.TransferSize |= 1;
  1215. }
  1216. WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
  1217. //
  1218. // Initialize the adapter mode register value to the correct parameters,
  1219. // and save them in the adapter object.
  1220. //
  1221. adapterMode = 0;
  1222. ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
  1223. if (DeviceDescriptor->Master) {
  1224. ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
  1225. //
  1226. // Set the mode, and enable the request.
  1227. //
  1228. if (adapterObject->AdapterNumber == 1) {
  1229. //
  1230. // This request is for DMA controller 1
  1231. //
  1232. PDMA1_CONTROL dmaControl;
  1233. dmaControl = adapterObject->AdapterBaseVa;
  1234. WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
  1235. //
  1236. // DMA high page must be set to 0x80 for ISA bus masters to work on
  1237. // FireCoral.
  1238. //
  1239. WRITE_REGISTER_UCHAR(
  1240. ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
  1241. (ULONG)adapterObject->PagePort,
  1242. 0x80
  1243. );
  1244. //
  1245. // Unmask the DMA channel.
  1246. //
  1247. WRITE_REGISTER_UCHAR(
  1248. &dmaControl->SingleMask,
  1249. (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
  1250. );
  1251. } else {
  1252. //
  1253. // This request is for DMA controller 1
  1254. //
  1255. PDMA2_CONTROL dmaControl;
  1256. dmaControl = adapterObject->AdapterBaseVa;
  1257. WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
  1258. //
  1259. // DMA high page must be set to 0x80 for ISA bus masters to work on
  1260. // FireCoral.
  1261. //
  1262. WRITE_REGISTER_UCHAR(
  1263. ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
  1264. (ULONG)adapterObject->PagePort,
  1265. 0x80
  1266. );
  1267. //
  1268. // Unmask the DMA channel.
  1269. //
  1270. WRITE_REGISTER_UCHAR(
  1271. &dmaControl->SingleMask,
  1272. (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
  1273. );
  1274. }
  1275. } else if (DeviceDescriptor->DemandMode) {
  1276. ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
  1277. } else {
  1278. ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
  1279. }
  1280. if (DeviceDescriptor->AutoInitialize) {
  1281. ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
  1282. }
  1283. adapterObject->AdapterMode = adapterMode;
  1284. return(adapterObject);
  1285. }
  1286. ULONG
  1287. HalReadDmaCounter(
  1288. IN PADAPTER_OBJECT AdapterObject
  1289. )
  1290. /*++
  1291. Routine Description:
  1292. This function reads the DMA counter and returns the number of bytes left
  1293. to be transfered.
  1294. Arguments:
  1295. AdapterObject - Supplies a pointer to the adapter object to be read.
  1296. Return Value:
  1297. Returns the number of bytes still be be transfered.
  1298. --*/
  1299. {
  1300. ULONG count;
  1301. ULONG high;
  1302. //
  1303. // Determine the controller number based on the Adapter number.
  1304. //
  1305. if (AdapterObject->AdapterNumber == 1) {
  1306. //
  1307. // This request is for DMA controller 1
  1308. //
  1309. PDMA1_CONTROL dmaControl;
  1310. dmaControl = AdapterObject->AdapterBaseVa;
  1311. //
  1312. // Initialize count to a value which will not match.
  1313. //
  1314. count = 0xFFFF00;
  1315. //
  1316. // Loop until the same high byte is read twice.
  1317. //
  1318. do {
  1319. high = count;
  1320. WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
  1321. //
  1322. // Read the current DMA count.
  1323. //
  1324. count = READ_REGISTER_UCHAR(
  1325. &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
  1326. .DmaBaseCount
  1327. );
  1328. count |= READ_REGISTER_UCHAR(
  1329. &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
  1330. .DmaBaseCount
  1331. ) << 8;
  1332. } while ((count & 0xFFFF00) != (high & 0xFFFF00));
  1333. } else {
  1334. //
  1335. // This request is for DMA controller 2
  1336. //
  1337. PDMA2_CONTROL dmaControl;
  1338. dmaControl = AdapterObject->AdapterBaseVa;
  1339. //
  1340. // Initialize count to a value which will not match.
  1341. //
  1342. count = 0xFFFF00;
  1343. //
  1344. // Loop until the same high byte is read twice.
  1345. //
  1346. do {
  1347. high = count;
  1348. WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
  1349. //
  1350. // Read the current DMA count.
  1351. //
  1352. count = READ_REGISTER_UCHAR(
  1353. &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
  1354. .DmaBaseCount
  1355. );
  1356. count |= READ_REGISTER_UCHAR(
  1357. &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
  1358. .DmaBaseCount
  1359. ) << 8;
  1360. } while ((count & 0xFFFF00) != (high & 0xFFFF00));
  1361. }
  1362. //
  1363. // The DMA counter has a bias of one and can only be 16 bit long.
  1364. //
  1365. count = (count + 1) & 0xFFFF;
  1366. return(count);
  1367. }
  1368. VOID
  1369. HalpHandleIoError (
  1370. VOID
  1371. )
  1372. {
  1373. UCHAR StatusByte;
  1374. //
  1375. // Read NMI status
  1376. //
  1377. StatusByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiStatus);
  1378. //
  1379. // Test for PCI bus error
  1380. //
  1381. if (StatusByte & 0x40) {
  1382. HalDisplayString ("NMI: IOCHK\n");
  1383. }
  1384. //
  1385. // Test for ISA IOCHK
  1386. //
  1387. if (StatusByte & 0x80) {
  1388. HalDisplayString ("NMI: PCI System Error\n");
  1389. }
  1390. }