diff options
Diffstat (limited to 'private/ntos/nthals/halr98mp/mips/jxebsup.c')
-rw-r--r-- | private/ntos/nthals/halr98mp/mips/jxebsup.c | 1275 |
1 files changed, 1275 insertions, 0 deletions
diff --git a/private/ntos/nthals/halr98mp/mips/jxebsup.c b/private/ntos/nthals/halr98mp/mips/jxebsup.c new file mode 100644 index 000000000..464a35673 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/jxebsup.c @@ -0,0 +1,1275 @@ +#ident "@(#) NEC jxebsup.c 1.13 95/06/19 11:10:34" +/*++ + +Copyright (c) 1990-1994 Microsoft Corporation + +Module Name: + + jxebsup.c + +Abstract: + + The module provides the EISA bus support for JAZZ systems. + +--*/ + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * S001 94.03/25 T.Samezima + * + * HalpCreateEisaStructure + * + * Del #ifdef of Duo + * Disable NMI Interrupt + * + * Change Parameter of initialize interrupt + * Irql Level + * + *********************************************************************** + * + * S002 94.04/19 T.Samezima + * + * HalpEisaDispatch + * + * Del #ifdef of Duo + * K001 94/5/31 (Tue) N.Kugimoto + * Add SpinLock HalpEisaMapTransfer() + * + *********************************************************************** + * + * S003 94.06/01 T.Samezima + * + * HalHandleNMI + * + * Del display interrupt information + * + *********************************************************************** + * + * S004 94.6/13 T.Samezima + * + * Del Compile err + * + *********************************************************************** + * + * S005 94.7/5 T.Samezima + * + * Chg base i/o address to kseg1_base + * + * + *********************************************************************** + * + * S006 94.8/22 T.Samezima on SNES + * + * Add Move EISA NMI enable logic from HalpInitializeInterrupts() + * + *********************************************************************** + * + * S007 94.8/23 T.Samezima + * + * Chg Register read size from long to short + * + * + * K001 94/9/13 N.Kugimoto + * Add For a spurious interrupt PIC IR7 + * K002 94/9/13 N.Kugimoto + * Chg Interrupt Ack reg non USHORT.must UCHAR!!. + * + * S008 94.10/13 T.Samezima + * Fix Version Up at build807 + * S009 94.11/21 T.Samezima + * Chg Disable EISA NMI + * Disable ASSERT(). because. senseless ASSERT on r98 + * + * K003 95/04/24 N.Kugimoto + * Add DUMMDMA + * LR4360 workaround. can't TLB flush while dma. + * So ESC DMAC channel2 use. + * A002 1995/6/17 ataka@oa2.kb.nec.co.jp + * - resolve compile wornings. + */ + +#include "halp.h" +#include "eisa.h" +#include "bugcodes.h" + +// +// Define the context structure for use by the interrupt routine. +// + +// Start S008 +typedef +BOOLEAN +(*PSECONDARY_DISPATCH)( + PKINTERRUPT Interrupt + ); + +// End S008 +// Define save area for EISA adapter objects. +// + +PADAPTER_OBJECT HalpEisaAdapter[8]; + +// +// Define save area for EISA interrupt mask resiters and level\edge control +// registers. +// + +UCHAR HalpEisaInterrupt1Mask; +UCHAR HalpEisaInterrupt2Mask; +UCHAR HalpEisaInterrupt1Level; +UCHAR HalpEisaInterrupt2Level; + +// Start S008 +// Define EISA bus interrupt affinity. +// + +KAFFINITY HalpEisaBusAffinity; +// End S008 + +PADAPTER_OBJECT +HalpAllocateEisaAdapter( + IN PDEVICE_DESCRIPTION DeviceDescriptor + ) +/*++ + +Routine Description: + + This function allocates an EISA adapter object according to the + specification supplied in the device description. The necessary device + descriptor information is saved. If there is + no existing adapter object for this channel then a new one is allocated. + The saved information in the adapter object is used to set the various DMA + modes when the channel is allocated or a map transfer is done. + +Arguments: + + DeviceDescription - Supplies the description of the device which want to + use the DMA adapter. + +Return Value: + + Returns a pointer to the newly created adapter object or NULL if one + cannot be created. + +--*/ + +{ + PADAPTER_OBJECT adapterObject; + PVOID adapterBaseVa; + ULONG channelNumber; + ULONG controllerNumber; + DMA_EXTENDED_MODE extendedMode; + UCHAR adapterMode; + BOOLEAN useChannel; + BOOLEAN eisaSystem; + + // + // Determine if the the channel number is important. Master cards on + // Eisa do not use a channel number. + // + + if (DeviceDescriptor->InterfaceType == Eisa && + DeviceDescriptor->Master) { + + useChannel = FALSE; + } else { + + useChannel = TRUE; + } + + // + // Channel 4 cannot be used since it is used for chaining. Return null if + // it is requested. + // + + if ((DeviceDescriptor->DmaChannel == 4 || + DeviceDescriptor->DmaChannel > 7) && useChannel) { + + return(NULL); + } + + // + // Set the channel number number. + // + + channelNumber = DeviceDescriptor->DmaChannel & 0x03; + + // + // Set the adapter base address to the Base address register and controller + // number. + // + + if (!(DeviceDescriptor->DmaChannel & 0x04)) { + + controllerNumber = 1; + adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort; + + } else { + + controllerNumber = 2; + adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort; + + } + + // + // Determine if a new adapter object is necessary. If so then allocate it. + // + + if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) { + + adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel]; + + } else { + + // + // Allocate an adapter object. + // + + adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter( + 0, + adapterBaseVa, + NULL + ); + + if (adapterObject == NULL) { + + return(NULL); + + } + + if (useChannel) { + + HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject; + + } + + } + + + // + // If the channel is not used then indicate the this is an Eisa bus + // master by setting the page port and mode to cascade even though + // it is not used. + // + + if (!useChannel) { + adapterObject->PagePort = (PVOID) (~0x0); + ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE; + return(adapterObject); + } + + // + // Setup the pointers to all the random registers. + // + + adapterObject->ChannelNumber = (UCHAR)channelNumber; // S004 + + if (controllerNumber == 1) { + + switch ((UCHAR)channelNumber) { + + case 0: + adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel0; + break; + + case 1: + adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel1; + break; + + case 2: + adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel2; + break; + + case 3: + adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel3; + break; + } + + // + // Set the adapter number. + // + + adapterObject->AdapterNumber = 1; + + // + // Save the extended mode register address. + // + + adapterBaseVa = + &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort; + + } else { + + switch (channelNumber) { + case 1: + adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel5; + break; + + case 2: + adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel6; + break; + + case 3: + adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel7; + break; + } + + // + // Set the adapter number. + // + + adapterObject->AdapterNumber = 2; + + // + // Save the extended mode register address. + // + adapterBaseVa = + &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort; + + } + + // + // Initialzie the extended mode port. + // + + *((PUCHAR) &extendedMode) = 0; + extendedMode.ChannelNumber = (UCHAR)channelNumber; // S004 + + switch (DeviceDescriptor->DmaSpeed) { + case Compatible: + extendedMode.TimingMode = COMPATIBLITY_TIMING; + break; + + case TypeA: + extendedMode.TimingMode = TYPE_A_TIMING; + break; + + case TypeB: + extendedMode.TimingMode = TYPE_B_TIMING; + break; + + case TypeC: + extendedMode.TimingMode = BURST_TIMING; + break; + + default: + ObDereferenceObject( adapterObject ); + return(NULL); + + } + + switch (DeviceDescriptor->DmaWidth) { + case Width8Bits: + extendedMode.TransferSize = BY_BYTE_8_BITS; + break; + + case Width16Bits: + extendedMode.TransferSize = BY_BYTE_16_BITS; + break; + + case Width32Bits: + extendedMode.TransferSize = BY_BYTE_32_BITS; + break; + + default: + ObDereferenceObject( adapterObject ); + return(NULL); + + } + + WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode)); + + // + // Initialize the adapter mode register value to the correct parameters, + // and save them in the adapter object. + // + + adapterMode = 0; + ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber; + + if (DeviceDescriptor->Master) { + + ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE; + + // + // Set the mode, and enable the request. + // + + if (adapterObject->AdapterNumber == 1) { + + // + // This request is for DMA controller 1 + // + + PDMA1_CONTROL dmaControl; + + dmaControl = adapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + // + // Unmask the DMA channel. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber) + ); + + } else { + + // + // This request is for DMA controller 1 + // + + PDMA2_CONTROL dmaControl; + + dmaControl = adapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + // + // Unmask the DMA channel. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber) + ); + + } + + } else if (DeviceDescriptor->DemandMode) { + + ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE; + + } else { + + ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE; + + } + + if (DeviceDescriptor->AutoInitialize) { + + ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1; + + } + + adapterObject->AdapterMode = adapterMode; + + return(adapterObject); +} + +BOOLEAN +HalpCreateEisaStructures ( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the structures necessary for EISA operations + and connects the intermediate interrupt dispatcher. It also initializes the + EISA interrupt controller. + +Arguments: + + None. + +Return Value: + + If the second level interrupt dispatcher is connected, then a value of + TRUE is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + UCHAR DataByte; + KIRQL oldIrql; + UCHAR charBuffer; // S006 + + /* Start S001, S008 */ + // + // Directly connect the EISA interrupt dispatcher to the level for + // EISA bus interrupt. + // + // N.B. This vector is reserved for exclusive use by the HAL (see + // interrupt initialization. + // + + PCR->InterruptRoutine[EISA_DEVICE_VECTOR] = (PKINTERRUPT_ROUTINE)HalpEisaDispatch; // A002 + /* End S001, S008 */ + + // + // Raise the IRQL while the EISA interrupt controller is initalized. + // + + /* Start S001 */ + KeRaiseIrql(INT1_LEVEL, &oldIrql); + /* End S001 */ + + // + // Initialize the EISA interrupt controller. There are two cascaded + // interrupt controllers, each of which must initialized with 4 initialize + // control words. + // + + DataByte = 0; + ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1; + ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0, + DataByte + ); + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0, + DataByte + ); + + // + // The second intitialization control word sets the iterrupt vector to + // 0-15. + // + + DataByte = 0; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + DataByte + ); + + DataByte = 0x08; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + DataByte + ); + + // + // The thrid initialization control word set the controls for slave mode. + // The master ICW3 uses bit position and the slave ICW3 uses a numberic. + // + + DataByte = 1 << SLAVE_IRQL_LEVEL; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + DataByte + ); + + DataByte = SLAVE_IRQL_LEVEL; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + DataByte + ); + + // + // The fourth initialization control word is used to specify normal + // end-of-interrupt mode and not special-fully-nested mode. + // + + DataByte = 0; + ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + DataByte + ); + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + DataByte + ); + + + // + // Disable all of the interrupts except the slave. + // + + HalpEisaInterrupt1Mask = (UCHAR)~(1 << SLAVE_IRQL_LEVEL); // S004 + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + HalpEisaInterrupt1Mask + ); + + HalpEisaInterrupt2Mask = 0xFF; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + HalpEisaInterrupt2Mask + ); + + // + // Initialize the edge/level register masks to 0 which is the default + // edge sensitive value. + // + + HalpEisaInterrupt1Level = 0; + HalpEisaInterrupt2Level = 0; + + // Start S008 + // Set EISA bus interrupt affinity. + // + + HalpEisaBusAffinity = PCR->SetMember; + // End S008 + + // + // Restore IRQL level. + // + + KeLowerIrql(oldIrql); + + /* Start S001, S008 */ + // + // Enable eisa interrupt on LR4360 + // + KiAcquireSpinLock(&HalpSystemInterruptLock); + + HalpBuiltinInterruptEnable |= iREN_ENABLE_EISA_INTERRUPT; + WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, + HalpBuiltinInterruptEnable); + + KiReleaseSpinLock(&HalpSystemInterruptLock); + + /* End S008 */ + // + // Initialize the DMA mode registers to a default value. + // Disable all of the DMA channels except channel 4 which is that + // cascade of channels 0-3. + // + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask, + 0x0F + ); + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask, + 0x0E + ); + /* End S001 */ + + // Start S006 + charBuffer = READ_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus ); +// charBuffer = (charBuffer & 0x03); // S009 + charBuffer = ((charBuffer & 0x03) | 0X0C); // S009 + WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, + charBuffer + ); + /* Start S001 in xxinitnt.c */ + charBuffer = READ_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl + ); + /* End S001 in xxinitnt.c */ +// charBuffer = ( (charBuffer & 0x01) | 0x0e ); // S009 + charBuffer = (charBuffer & 0x01); // S009 + WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, + charBuffer ); // S007 + // End S006 + + return(TRUE); +} + + +VOID +HalpDisableEisaInterrupt( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function Disables the EISA bus specified EISA bus interrupt. + +Arguments: + + Vector - Supplies the vector of the ESIA interrupt that is Disabled. + +Return Value: + + None. + +--*/ + +{ + + // + // Calculate the EISA interrupt vector. + // + + Vector -= EISA_VECTORS; + + // + // Determine if this vector is for interrupt controller 1 or 2. + // + + if (Vector & 0x08) { + + // + // The interrupt is in controller 2. + // + + Vector &= 0x7; + + HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector; + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + HalpEisaInterrupt2Mask + ); + + } else { + + // + // The interrupt is in controller 1. + // + + Vector &= 0x7; + + HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector; + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + HalpEisaInterrupt1Mask + ); + + } + +} +// +// +//extern KSPIN_LOCK HalpIoMapSpinLock; +VOID +HalpEisaMapTransfer( + IN PADAPTER_OBJECT AdapterObject, + IN ULONG Offset, + IN ULONG Length, + IN BOOLEAN WriteToDevice + ) + +/*++ + +Routine Description: + + This function programs the EISA DMA controller for a transfer. + +Arguments: + + Adapter - Supplies the DMA adapter object to be programed. + + Offset - Supplies the logical address to use for the transfer. + + Length - Supplies the length of the transfer in bytes. + + WriteToDevice - Indicates the direction of the transfer. + +Return Value: + + None. + +--*/ + +{ + PUCHAR BytePtr; + UCHAR adapterMode; + KIRQL Irql; // K001 + + BytePtr = (PUCHAR) &Offset; + +// ASSERT(Offset >= 0x100000); // S009 + + adapterMode = AdapterObject->AdapterMode; + + // + // Check to see if this request is for a master I/O card. + // + + if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) { + + // + // Set the mode, Disable the request and return. + // + + if (AdapterObject->AdapterNumber == 1) { + + // + // This request is for DMA controller 1 + // + + PDMA1_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + // + // Unmask the DMA channel. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber) + ); + + } else { + + // + // This request is for DMA controller 1 + // + + PDMA2_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + // + // Unmask the DMA channel. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber) + ); + + } + + return; + } + + + // + // Determine the mode based on the transfer direction. + // + + ((PDMA_EISA_MODE) &adapterMode)->TransferType = WriteToDevice ? + WRITE_TRANSFER : READ_TRANSFER; + + // K001 + // grab the spinlock for the system DMA controller + // +#if !defined(DUMMYDMA) + KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql ); +#endif + // + // Determine the controller number based on the Adapter base va. + // + + if (AdapterObject->AdapterNumber == 1) { + + // + // This request is for DMA controller 1 + // + + PDMA1_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 ); + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseAddress, + BytePtr[0] + ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseAddress, + BytePtr[1] + ); + + WRITE_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) + + (ULONG)AdapterObject->PagePort, + BytePtr[2] + ); + + // + // Write the high page register with zero value. This enable a special mode + // which allows ties the page register and base count into a single 24 bit + // address register. + // + + WRITE_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) + + (ULONG)AdapterObject->PagePort, + 0 + ); + + + // + // Notify DMA chip of the length to transfer. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount, + (UCHAR) ((Length - 1) & 0xff) + ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount, + (UCHAR) ((Length - 1) >> 8) + ); + + + // + // Set the DMA chip to read or write mode; and unmask it. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber) + ); + + } else { + + // + // This request is for DMA controller 1 + // + + PDMA2_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 ); + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseAddress, + BytePtr[0] + ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseAddress, + BytePtr[1] + ); + + WRITE_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) + + (ULONG)AdapterObject->PagePort, + BytePtr[2] + ); + + // + // Write the high page register with zero value. This enable a special mode + // which allows ties the page register and base count into a single 24 bit + // address register. + // + + WRITE_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) + + (ULONG)AdapterObject->PagePort, + 0 + ); + + + // + // Notify DMA chip of the length to transfer. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount, + (UCHAR) ((Length - 1) & 0xff) + ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount, + (UCHAR) ((Length - 1) >> 8) + ); + + + // + // Set the DMA chip to read or write mode; and unmask it. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber) + ); + } +#if !defined(DUMMYDMA) + KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql); +#endif +} + + +VOID +HalpEnableEisaInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ) + +/*++ + +Routine Description: + + This function enables the EISA bus specified EISA bus interrupt and sets + the level/edge register to the requested value. + +Arguments: + + Vector - Supplies the vector of the EISA interrupt that is enabled. + + InterruptMode - Supplies the mode of the interrupt; LevelSensitive or + Latched. + +Return Value: + + None. + +--*/ + +{ + + // + // Calculate the EISA interrupt vector. + // + + Vector -= EISA_VECTORS; + + // + // Determine if this vector is for interrupt controller 1 or 2. + // + + if (Vector & 0x08) { + + // + // The interrupt is in controller 2. + // + + Vector &= 0x7; + + HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector); + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + HalpEisaInterrupt2Mask + ); + + // + // Set the level/edge control register. + // + + if (InterruptMode == LevelSensitive) { + + HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector); + + } else { + + HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector); + + } + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel, + HalpEisaInterrupt2Level + ); + + } else { + + // + // The interrupt is in controller 1. + // + + Vector &= 0x7; + + HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector); + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + HalpEisaInterrupt1Mask + ); + + // + // Set the level/edge control register. + // + + if (InterruptMode == LevelSensitive) { + + HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector); + + } else { + + HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector); + + } + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel, + HalpEisaInterrupt1Level + ); + } +} + +// Start S008 +BOOLEAN +HalpEisaDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ) + +/*++ + +Routine Description: + + This routine is entered as the result of an interrupt being generated + via the vector that is directly connected to EISA device interrupt. + + N.B. This interrupt is directly connected and therefore, no argument + values are defined. + +Arguments: + + None. + +Return Value: + + Returns the value returned from the second level routine. + +--*/ + +{ + PULONG dispatchCode; + USHORT interruptVector; + PKINTERRUPT interruptObject; + BOOLEAN returnValue; + + // + // Read the interrupt vector. + // + + interruptVector = (UCHAR)READ_REGISTER_UCHAR( (PVOID)(LR_PHYSICAL_PCI_INT_ACK_BASE | KSEG1_BASE)); + + // + // If the vector is nonzero, then it is either an EISA interrupt + // of an NMI interrupt. Otherwise, the interrupt is no longer + // present. + // + + if (interruptVector != 0) { + + // + // If the interrupt vector is 0x8000 then the interrupt is an NMI. + // Otherwise, dispatch the interrupt to the appropriate interrupt + // handler. + // + +// if (interruptVector != 0x8000) { + //K001 Start + if(interruptVector == 7|| interruptVector==15 ){ + + PVOID IsrPortAddr; + UCHAR IsrValue; + +#define OCW3_READ_ISR 0x0B +#define OCW3_READ_IRR 0x0A + + // + // Master or Slave ? + // + IsrPortAddr = (interruptVector == 7) ? + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0: + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0; + + // SetUp to ISR Regsiter + WRITE_REGISTER_UCHAR( IsrPortAddr, OCW3_READ_ISR ); + // Read ISR Register + IsrValue=READ_REGISTER_UCHAR( IsrPortAddr ); + // Resume to IRR Register + WRITE_REGISTER_UCHAR( IsrPortAddr, OCW3_READ_IRR); + + if(!IsrValue){ + // This is a spurious interrupt!!. No Call Driver. + goto NocallDriver; + } + } + // K001 End + + // + // Mask the upper bits off since the vector is only a byte and + // dispatch to the secondary interrupt service routine. + // + + interruptVector &= 0xff; + dispatchCode = (PULONG)(PCR->InterruptRoutine[EISA_VECTORS + interruptVector]); + interruptObject = CONTAINING_RECORD(dispatchCode, + KINTERRUPT, + DispatchCode); + + returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject); + +NocallDriver: + + // + // Dismiss the interrupt in the EISA interrupt controllers. + // + // If this is a cascaded interrupt then the interrupt must be + // dismissed in both controllers. + // + + if (interruptVector & 0x08) { + WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0, + NONSPECIFIC_END_OF_INTERRUPT); + } + + WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0, + NONSPECIFIC_END_OF_INTERRUPT); + +// } else { +// returnValue = HalHandleNMI(NULL, NULL); +// } + + } else { + returnValue = FALSE; + } + + return returnValue; +} +// End S008 + +BOOLEAN +HalHandleNMI( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ) +/*++ + +Routine Description: + + This function is called when an EISA NMI occurs. It print the appropriate + status information and bugchecks. + +Arguments: + + Interrupt - Supplies a pointer to the interrupt object + + ServiceContext - Bug number to call bugcheck with. + +Return Value: + + Returns TRUE. + +--*/ +{ + KeBugCheck(NMI_HARDWARE_FAILURE); + return(TRUE); +} |