mirror of https://github.com/lianthony/NT4.0
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.
1387 lines
32 KiB
1387 lines
32 KiB
/*++
|
|
|
|
Copyright (c) 1990-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
jxebsup.c
|
|
|
|
Abstract:
|
|
|
|
The module provides the EISA bus support for JAZZ systems.
|
|
|
|
|
|
--*/
|
|
|
|
|
|
#include "halp.h"
|
|
#include "eisa.h"
|
|
#include "bugcodes.h"
|
|
|
|
|
|
//
|
|
// external (defined in fxpcibus.c)
|
|
//
|
|
|
|
extern UCHAR HalpPCIPinToLineTable[];
|
|
extern UCHAR HalpPIRQTable[];
|
|
|
|
//
|
|
// Define the context structure for use by the interrupt routine.
|
|
//
|
|
|
|
typedef BOOLEAN (*PSECONDARY_DISPATCH)(
|
|
PVOID InterruptRoutine
|
|
);
|
|
|
|
//
|
|
// Declare the interupt structure and spinlock for the intermediate EISA
|
|
// interrupt dispachter.
|
|
//
|
|
|
|
KINTERRUPT HalpEisaInterrupt;
|
|
|
|
//
|
|
// The following is the interrupt object used for DMA controller interrupts.
|
|
// DMA controller interrupts occur when a memory parity error occurs or a
|
|
// programming error occurs to the DMA controller.
|
|
//
|
|
|
|
KINTERRUPT HalpEisaNmiInterrupt;
|
|
|
|
UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n";
|
|
|
|
//
|
|
// The following function is called when an EISA NMI occurs.
|
|
//
|
|
|
|
BOOLEAN
|
|
HalHandleNMI(
|
|
IN PKINTERRUPT Interrupt,
|
|
IN PVOID ServiceContext
|
|
);
|
|
|
|
//
|
|
// Define save area for EISA adapter objects.
|
|
//
|
|
|
|
PADAPTER_OBJECT HalpEisaAdapter[8];
|
|
|
|
//
|
|
// Define save area for EISA interrupt mask registers and level\edge control
|
|
// registers.
|
|
//
|
|
|
|
UCHAR HalpEisaInterrupt1Mask;
|
|
UCHAR HalpEisaInterrupt2Mask;
|
|
UCHAR HalpEisaInterrupt1Level;
|
|
UCHAR HalpEisaInterrupt2Level;
|
|
|
|
//
|
|
// Define EISA bus interrupt affinity.
|
|
//
|
|
|
|
#if defined(PROCESSOR_AFFINITY_PCR)
|
|
|
|
KAFFINITY HalpEisaBusAffinity;
|
|
|
|
#endif // PROCESSOR_AFFINITY_PCR
|
|
|
|
|
|
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;
|
|
|
|
|
|
//
|
|
// 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);
|
|
|
|
}
|
|
|
|
//
|
|
// We want to know the interface type
|
|
//
|
|
|
|
adapterObject->InterfaceType = DeviceDescriptor->InterfaceType;
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
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);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function initializes IO interrupts on a Falcon system.
|
|
|
|
This function is only called during phase 0 initialization.
|
|
|
|
Arguments:
|
|
|
|
pointer to eisa control structure.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
VOID
|
|
HalpInitializeEisaInterrupts (
|
|
IN PEISA_CONTROL controlBase
|
|
)
|
|
|
|
{
|
|
UCHAR DataByte;
|
|
ULONG i;
|
|
|
|
//
|
|
// Set EISA bus interrupt affinity.
|
|
//
|
|
|
|
#if defined(PROCESSOR_AFFINITY_PCR)
|
|
HalpEisaBusAffinity = PCR->SetMember;
|
|
#endif // PROCESSOR_AFFINITY_PCR)
|
|
|
|
//
|
|
// Let's read the PIRQ* registers to obtain the dynamic
|
|
// mapping for PCI interrupts as set by the firmware
|
|
// in the 82374/82375. We will save the PIRQ mappings
|
|
// in the HalpPCIPinToLineTable[] which is used during
|
|
// PCI bus probing and device configuration.
|
|
//
|
|
// Warning: Do not change the section of code related
|
|
// to PIRQ mappings unless you thoroughly
|
|
// understand the HalpPCIPinToLineTable[] and
|
|
// the HalpPciConfigSelectDecodeTable[]. These
|
|
// tables correspond directly to the PciConfigSelect
|
|
// register inside the PMP asic and the PIRQ
|
|
// lines which deliver the interrupts for each
|
|
// PCI device.
|
|
//
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Reserved1[0], ESC_CONFIG_ID);
|
|
WRITE_REGISTER_UCHAR(&controlBase->Reserved1[1], ESC_CONFIG_IDEN_BYTE);
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Reserved1[0], ESC_CONFIG_PIRQ0);
|
|
HalpPCIPinToLineTable[PCI_OBENET_DEVICE_NUMBER] = HalpPIRQTable[0] =
|
|
READ_REGISTER_UCHAR(&controlBase->Reserved1[1]);
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Reserved1[0], ESC_CONFIG_PIRQ1);
|
|
HalpPCIPinToLineTable[PCI_OBSCSI_DEVICE_NUMBER] = HalpPIRQTable[1] =
|
|
READ_REGISTER_UCHAR(&controlBase->Reserved1[1]);
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Reserved1[0], ESC_CONFIG_PIRQ3);
|
|
HalpPCIPinToLineTable[PCI_SLOT0_DEVICE_NUMBER] = HalpPIRQTable[2] =
|
|
READ_REGISTER_UCHAR(&controlBase->Reserved1[1]);
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Reserved1[0], ESC_CONFIG_PIRQ2);
|
|
HalpPCIPinToLineTable[PCI_SLOT1_DEVICE_NUMBER] = HalpPIRQTable[3] =
|
|
READ_REGISTER_UCHAR(&controlBase->Reserved1[1]);
|
|
|
|
//
|
|
// First lets mask off all interrupts to separate ourselves
|
|
// from the firmware to avoid spurious interrupts
|
|
//
|
|
HalpEisaInterrupt1Mask = (UCHAR)0xFF;
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt1ControlPort1, HalpEisaInterrupt1Mask);
|
|
|
|
HalpEisaInterrupt2Mask = (UCHAR)0xFF;
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt2ControlPort1, HalpEisaInterrupt2Mask);
|
|
|
|
//
|
|
// Set everything to edge before beginning the initialization
|
|
// sequence (per the 82374 errata)
|
|
//
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt1EdgeLevel, 0);
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt2EdgeLevel, 0);
|
|
|
|
//
|
|
// 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(&controlBase->Interrupt1ControlPort0, DataByte);
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt2ControlPort0, DataByte);
|
|
|
|
//
|
|
// The second intitialization control word sets the interrupt vector to
|
|
// 0-15.
|
|
//
|
|
|
|
DataByte = 0;
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt1ControlPort1, DataByte);
|
|
|
|
DataByte = 0x08;
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt2ControlPort1, DataByte);
|
|
|
|
//
|
|
// The third initialization control word set the controls for slave mode.
|
|
// The master ICW3 uses bit position and the slave ICW3 uses a numeric.
|
|
//
|
|
|
|
DataByte = 1 << SLAVE_IRQL_LEVEL;
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt1ControlPort1, DataByte);
|
|
|
|
DataByte = SLAVE_IRQL_LEVEL;
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->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(&controlBase->Interrupt1ControlPort1, DataByte);
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt2ControlPort1, DataByte);
|
|
|
|
//
|
|
// Enable the slave interrupt which connects the two cascaded
|
|
// interrupt controllers together.
|
|
//
|
|
|
|
HalpEisaInterrupt1Mask = (UCHAR) ~(1 << SLAVE_IRQL_LEVEL);
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt1ControlPort1, HalpEisaInterrupt1Mask);
|
|
|
|
HalpEisaInterrupt2Mask = (UCHAR)0xFF;
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt2ControlPort1, HalpEisaInterrupt2Mask);
|
|
|
|
//
|
|
// Program the level versus edge sensitivity of the interrupts.
|
|
//
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt1EdgeLevel, HalpEisaInterrupt1Level);
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt2EdgeLevel, HalpEisaInterrupt2Level);
|
|
|
|
//
|
|
// Clear any specific interrupts
|
|
// left hanging around by the
|
|
// boot
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt1ControlPort0, 0x20);
|
|
|
|
}
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
WRITE_REGISTER_UCHAR(&controlBase->Interrupt2ControlPort0, 0x20);
|
|
|
|
}
|
|
|
|
//
|
|
// 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(&controlBase->Dma1BasePort.AllMask, 0x0F);
|
|
WRITE_REGISTER_UCHAR(&controlBase->Dma2BasePort.AllMask, 0x0E);
|
|
|
|
//
|
|
// We're done
|
|
//
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function dispatches IO interrupts on a Falcon system.
|
|
|
|
It calls the device-specific interrupt handler (ISR).
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
VOID
|
|
HalpIoInterruptDispatch(
|
|
VOID
|
|
)
|
|
|
|
{
|
|
|
|
UCHAR interruptVector;
|
|
UCHAR inService;
|
|
PKPRCB Prcb;
|
|
BOOLEAN Status;
|
|
|
|
//
|
|
// Read IoIntAck register to determine the interrupt source
|
|
//
|
|
|
|
interruptVector = READ_REGISTER_UCHAR(HalpPmpIoIntAck);
|
|
|
|
//
|
|
// Determine if this is a bogus interrupt from the 8259
|
|
// by checking the corresponding InService bit. If it is
|
|
// real then we will deal with it normally; otherwise,
|
|
// we will just dismiss it straight away.
|
|
//
|
|
|
|
if (interruptVector == 0x07) {
|
|
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->Interrupt1ControlPort0, 0x0B);
|
|
|
|
inService = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->Interrupt1ControlPort0);
|
|
|
|
if (!(inService & 0x80)) {
|
|
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->Interrupt1ControlPort0, NONSPECIFIC_END_OF_INTERRUPT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Get the PRCB.
|
|
//
|
|
|
|
Prcb = KeGetCurrentPrcb();
|
|
|
|
//
|
|
// Dispatch to the secondary interrupt service routine.
|
|
//
|
|
|
|
Status = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[EISA_VECTORS + interruptVector])(
|
|
PCR->InterruptRoutine[EISA_VECTORS + interruptVector]
|
|
);
|
|
|
|
//
|
|
// Dismiss the interrupt in the 8259 interrupt controller.
|
|
//
|
|
|
|
//
|
|
// 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
|
|
);
|
|
|
|
}
|
|
|
|
|
|
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
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
BytePtr = (PUCHAR) &Offset;
|
|
|
|
ASSERT(Offset >= 0x100000);
|
|
|
|
//
|
|
// grab the spinlock for the system DMA controller
|
|
//
|
|
|
|
KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
|
|
|
|
|
|
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 2
|
|
//
|
|
|
|
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)
|
|
);
|
|
|
|
}
|
|
|
|
//
|
|
// Release adapter spin lock
|
|
//
|
|
|
|
KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// Determine the mode based on the transfer direction.
|
|
//
|
|
|
|
((PDMA_EISA_MODE) &adapterMode)->TransferType = WriteToDevice ?
|
|
WRITE_TRANSFER : READ_TRANSFER;
|
|
|
|
//
|
|
// 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 );
|
|
|
|
//
|
|
// Devices which do not use auto-initialize
|
|
// CommonBuffer DMA can use the scatter/gather
|
|
// capabilities of the 82374 which we manage
|
|
// through map registers similar to how previous
|
|
// MIPS machines managed the IO TLB.
|
|
//
|
|
|
|
if (!AdapterObject->AutoInitialize) {
|
|
|
|
//
|
|
// 1. Setup Scatter/Gather Descriptor Table Pointer
|
|
// register according to which channel is being used.
|
|
// 2. Issue Scatter/Gather Start command.
|
|
//
|
|
|
|
switch (AdapterObject->ChannelNumber) {
|
|
|
|
case 0:
|
|
WRITE_REGISTER_ULONG( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[16], Offset);
|
|
WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[0], SCATTER_GATHER_COMMAND);
|
|
break;
|
|
|
|
case 1:
|
|
WRITE_REGISTER_ULONG( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[20], Offset);
|
|
WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[1], SCATTER_GATHER_COMMAND);
|
|
break;
|
|
case 2:
|
|
WRITE_REGISTER_ULONG( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[24], Offset);
|
|
WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[2], SCATTER_GATHER_COMMAND);
|
|
break;
|
|
|
|
case 3:
|
|
WRITE_REGISTER_ULONG( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[28], Offset);
|
|
WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[3], SCATTER_GATHER_COMMAND);
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
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_REGISTER_UCHAR(
|
|
((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
|
|
(ULONG)AdapterObject->PagePort,
|
|
BytePtr[3]
|
|
);
|
|
|
|
//
|
|
// 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 2
|
|
//
|
|
|
|
PDMA2_CONTROL dmaControl;
|
|
|
|
dmaControl = AdapterObject->AdapterBaseVa;
|
|
|
|
WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
|
|
|
|
WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
|
|
|
|
//
|
|
// Devices which do not use auto-initialize
|
|
// CommonBuffer DMA can use the scatter/gather
|
|
// capabilities of the 82374 which we manage
|
|
// through map registers.
|
|
//
|
|
|
|
if (!AdapterObject->AutoInitialize) {
|
|
|
|
//
|
|
// 1. Setup Scatter/Gather Descriptor Table Pointer
|
|
// register according to which channel is being used.
|
|
// 2. Issue Scatter/Gather Start command.
|
|
//
|
|
|
|
switch (AdapterObject->ChannelNumber) {
|
|
|
|
case 1:
|
|
WRITE_REGISTER_ULONG( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[36], Offset);
|
|
WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[5], SCATTER_GATHER_COMMAND);
|
|
break;
|
|
|
|
case 2:
|
|
WRITE_REGISTER_ULONG( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[40], Offset);
|
|
WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[6], SCATTER_GATHER_COMMAND);
|
|
break;
|
|
|
|
case 3:
|
|
WRITE_REGISTER_ULONG( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[44], Offset);
|
|
WRITE_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase)->Reserved6[7], SCATTER_GATHER_COMMAND);
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
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_REGISTER_UCHAR(
|
|
((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
|
|
(ULONG)AdapterObject->PagePort,
|
|
BytePtr[3]
|
|
);
|
|
|
|
//
|
|
// 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)
|
|
);
|
|
}
|
|
|
|
//
|
|
// Release adapter spin lock
|
|
//
|
|
|
|
KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
|
|
|
|
}
|
|
|
|
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 ESIA 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.
|
|
//
|
|
//
|
|
// According to the 82374, the following interrupts
|
|
// MUST be edge-triggered: 0, 1, 2, 8, 13.
|
|
//
|
|
|
|
if ( (InterruptMode == LevelSensitive) && (Vector != 0) && (Vector != 0x5) ) {
|
|
|
|
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.
|
|
//
|
|
//
|
|
// According to the 82374, the following interrupts
|
|
// MUST be edge-triggered: 0, 1, 2, 8, 13.
|
|
//
|
|
// Warning: due to a firmware limitation (???) we must
|
|
// force the floppy interrupt (irq6) to be edge
|
|
// even though it will request level. There is no
|
|
// mechanism for communicating to a driver that
|
|
// its interrupt mode is different than requested.
|
|
// Hope this doesn't cause problems ...
|
|
//
|
|
|
|
if ( (InterruptMode == LevelSensitive) && (Vector >= 3) && (Vector != 6) ) {
|
|
|
|
HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
|
|
|
|
} else {
|
|
|
|
HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
|
|
|
|
}
|
|
|
|
WRITE_REGISTER_UCHAR(
|
|
&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
|
|
HalpEisaInterrupt1Level
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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.
|
|
|
|
--*/
|
|
{
|
|
UCHAR StatusByte;
|
|
UCHAR EisaPort;
|
|
ULONG port;
|
|
|
|
StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
|
|
|
|
if (StatusByte & 0x80) {
|
|
HalDisplayString ("NMI: Parity Check / Parity Error\n");
|
|
}
|
|
|
|
if (StatusByte & 0x40) {
|
|
HalDisplayString ("NMI: Channel Check / IOCHK\n");
|
|
}
|
|
|
|
//
|
|
// This is an Eisa machine, check for extnded nmi information...
|
|
//
|
|
|
|
StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl);
|
|
|
|
if (StatusByte & 0x80) {
|
|
HalDisplayString ("NMI: Fail-safe timer\n");
|
|
}
|
|
|
|
if (StatusByte & 0x40) {
|
|
HalDisplayString ("NMI: Bus Timeout\n");
|
|
}
|
|
|
|
if (StatusByte & 0x20) {
|
|
HalDisplayString ("NMI: Software NMI generated\n");
|
|
}
|
|
|
|
//
|
|
// Look for any Eisa expansion board. See if it asserted NMI.
|
|
//
|
|
|
|
for (EisaPort = 0; EisaPort <= 0xf; EisaPort++) {
|
|
port = (EisaPort << 12) + 0xC80;
|
|
port += (ULONG) HalpEisaControlBase;
|
|
WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
|
|
StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
|
|
|
|
if ((StatusByte & 0x80) == 0) {
|
|
//
|
|
// Found valid Eisa board, Check to see if it's
|
|
// if IOCHKERR is asserted.
|
|
//
|
|
|
|
StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
|
|
if (StatusByte & 0x2) {
|
|
EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
|
|
HalDisplayString (EisaNMIMsg);
|
|
}
|
|
}
|
|
}
|
|
|
|
KeBugCheck(NMI_HARDWARE_FAILURE);
|
|
return(TRUE);
|
|
}
|
|
|
|
NTSTATUS
|
|
HalpAdjustEisaResourceList (
|
|
IN PBUS_HANDLER BusHandler,
|
|
IN PBUS_HANDLER RootHandler,
|
|
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
|
|
)
|
|
{
|
|
SUPPORTED_RANGE InterruptRange;
|
|
|
|
RtlZeroMemory (&InterruptRange, sizeof InterruptRange);
|
|
InterruptRange.Base = 0;
|
|
InterruptRange.Limit = 15;
|
|
|
|
return HaliAdjustResourceListRange (
|
|
BusHandler->BusAddresses,
|
|
&InterruptRange,
|
|
pResourceList
|
|
);
|
|
}
|
|
|
|
VOID
|
|
HalpConfigureGpcsRegs(
|
|
IN PVOID ControlBase
|
|
)
|
|
|
|
{
|
|
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[0], ESC_CONFIG_ID);
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[1], ESC_CONFIG_IDEN_BYTE);
|
|
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[0], ESC_CONFIG_GPCSHA0);
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[1], (UCHAR)(PCI_CONFIG_SELECT_OFFSET >> 8));
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[0], ESC_CONFIG_GPCSLA0);
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[1], (UCHAR)(PCI_CONFIG_SELECT_OFFSET & 0xFF));
|
|
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[0], ESC_CONFIG_GPCSHA1);
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[1], (UCHAR)(EXTERNAL_PMP_CONTROL_OFFSET >> 8));
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[0], ESC_CONFIG_GPCSLA1);
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[1], (UCHAR)(EXTERNAL_PMP_CONTROL_OFFSET & 0xFF));
|
|
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[0], ESC_CONFIG_GPCSHA2);
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[1], (UCHAR)(EXTERNAL_PMP_CONTROL_OFFSET2 >> 8));
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[0], ESC_CONFIG_GPCSLA2);
|
|
WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)ControlBase)->Reserved1[1], (UCHAR)(EXTERNAL_PMP_CONTROL_OFFSET2 & 0xFF));
|
|
|
|
}
|