1478 lines
34 KiB
C
1478 lines
34 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990 Microsoft Corporation
|
|||
|
Copyright (c) 1992, 1993 Digital Equipment Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
eisasup.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
The module provides the platform-independent
|
|||
|
EISA bus support for Alpha systems.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Jeff Havens (jhavens) 19-Jun-1991
|
|||
|
Miche Baker-Harvey (miche) 13-May-1992
|
|||
|
Jeff McLeman (DEC) 1-Jun-1992
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
#include "halp.h"
|
|||
|
#include "eisa.h"
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Define save area for ESIA adapter objects.
|
|||
|
//
|
|||
|
|
|||
|
PADAPTER_OBJECT HalpEisaAdapter[8];
|
|||
|
|
|||
|
//
|
|||
|
// This value indicates if Eisa DMA is supported on this system.
|
|||
|
//
|
|||
|
|
|||
|
BOOLEAN HalpEisaDma;
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
HalpEisaInitializeDma(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Initialize DMA support for Eisa/Isa systems.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
UCHAR DataByte;
|
|||
|
|
|||
|
//
|
|||
|
// Determine if Eisa DMA is supported.
|
|||
|
//
|
|||
|
|
|||
|
HalpEisaDma = FALSE;
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort.Channel2, 0x55);
|
|||
|
DataByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort.Channel2);
|
|||
|
|
|||
|
if (DataByte == 0x55) {
|
|||
|
HalpEisaDma = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
PADAPTER_OBJECT
|
|||
|
HalpAllocateEisaAdapter(
|
|||
|
IN PDEVICE_DESCRIPTION DeviceDescriptor,
|
|||
|
OUT PULONG NumberOfMapRegisters
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function returns the appropriate adapter object for the device defined
|
|||
|
in the device description structure. This code works for Isa and Eisa
|
|||
|
systems.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceDescriptor - Supplies a description of the device.
|
|||
|
|
|||
|
NumberOfMapRegisters - Returns the maximum number of map registers which
|
|||
|
may be allocated by the device driver.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A pointer to the requested adapter object or NULL if an adapter could not
|
|||
|
be created.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PADAPTER_OBJECT adapterObject;
|
|||
|
PVOID adapterBaseVa;
|
|||
|
ULONG channelNumber;
|
|||
|
ULONG controllerNumber;
|
|||
|
DMA_EXTENDED_MODE extendedMode;
|
|||
|
UCHAR adapterMode;
|
|||
|
ULONG numberOfMapRegisters;
|
|||
|
BOOLEAN useChannel;
|
|||
|
ULONG maximumLength;
|
|||
|
UCHAR DataByte;
|
|||
|
|
|||
|
useChannel = TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// Support for ISA local bus machines:
|
|||
|
// If the driver is a Master but really does not want a channel since it
|
|||
|
// is using the local bus DMA, just don't use an ISA channel.
|
|||
|
//
|
|||
|
|
|||
|
if (DeviceDescriptor->InterfaceType == Isa &&
|
|||
|
DeviceDescriptor->DmaChannel > 7) {
|
|||
|
|
|||
|
useChannel = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
|
|||
|
// macro works correctly.
|
|||
|
//
|
|||
|
|
|||
|
maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
|
|||
|
|
|||
|
//
|
|||
|
// Channel 4 cannot be used since it is used for chaining. Return null if
|
|||
|
// it is requested.
|
|||
|
//
|
|||
|
|
|||
|
if (DeviceDescriptor->DmaChannel == 4 && useChannel) {
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Determine the number of map registers required based on the maximum
|
|||
|
// transfer length. Limit the maximum transfer to 64K.
|
|||
|
//
|
|||
|
|
|||
|
#define MAXIMUM_ISA_MAP_REGISTER (__64K >> PAGE_SHIFT)
|
|||
|
|
|||
|
numberOfMapRegisters = BYTES_TO_PAGES(maximumLength) + 1;
|
|||
|
numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
|
|||
|
MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
|
|||
|
|
|||
|
//
|
|||
|
// 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];
|
|||
|
|
|||
|
if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
|
|||
|
adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Allocate an adapter object.
|
|||
|
//
|
|||
|
|
|||
|
adapterObject = HalpAllocateAdapter();
|
|||
|
|
|||
|
if (adapterObject == NULL) {
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
|
|||
|
if (useChannel == TRUE) {
|
|||
|
HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set the maximum number of map registers for this channel bus on
|
|||
|
// the number requested and the type of device.
|
|||
|
//
|
|||
|
|
|||
|
adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
|
|||
|
|
|||
|
//
|
|||
|
// Establish the base va used to program the DMA controller.
|
|||
|
//
|
|||
|
|
|||
|
adapterObject->AdapterBaseVa = adapterBaseVa;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
*NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
|
|||
|
|
|||
|
if (DeviceDescriptor->Master) {
|
|||
|
adapterObject->MasterDevice = TRUE;
|
|||
|
} else {
|
|||
|
adapterObject->MasterDevice = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the channel number is not used then we are finished. The rest of
|
|||
|
// the work deals with channels.
|
|||
|
//
|
|||
|
|
|||
|
if (useChannel == FALSE) {
|
|||
|
return(adapterObject);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Setup the pointers to all the random registers.
|
|||
|
//
|
|||
|
|
|||
|
adapterObject->ChannelNumber = (UCHAR) channelNumber;
|
|||
|
|
|||
|
if (controllerNumber == 1) {
|
|||
|
|
|||
|
switch ((UCHAR)channelNumber) {
|
|||
|
|
|||
|
case 0:
|
|||
|
adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
|
|||
|
break;
|
|||
|
|
|||
|
case 1:
|
|||
|
adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
|
|||
|
break;
|
|||
|
|
|||
|
case 3:
|
|||
|
adapterObject->PagePort = (PUCHAR) &((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 = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
|
|||
|
break;
|
|||
|
|
|||
|
case 3:
|
|||
|
adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set the adapter number.
|
|||
|
//
|
|||
|
|
|||
|
adapterObject->AdapterNumber = 2;
|
|||
|
|
|||
|
//
|
|||
|
// Save the extended mode register address.
|
|||
|
//
|
|||
|
adapterBaseVa =
|
|||
|
&((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
adapterObject->Width16Bits = FALSE;
|
|||
|
|
|||
|
if (HalpEisaDma) {
|
|||
|
|
|||
|
//
|
|||
|
// 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;
|
|||
|
|
|||
|
//
|
|||
|
// Note Width16bits should not be set here because there is no need
|
|||
|
// to shift the address and the transfer count.
|
|||
|
//
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case Width32Bits:
|
|||
|
extendedMode.TransferSize = BY_BYTE_32_BITS;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
ObDereferenceObject( adapterObject );
|
|||
|
return(NULL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Save the extended mode in the adapter.
|
|||
|
// Then write the extended mode value for this channel.
|
|||
|
//
|
|||
|
|
|||
|
adapterObject->ExtendedMode = *((PDMA_EXTENDED_MODE)&extendedMode);
|
|||
|
|
|||
|
WRITE_PORT_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
|
|||
|
|
|||
|
} else if (DeviceDescriptor->Master == FALSE) {
|
|||
|
|
|||
|
|
|||
|
switch (DeviceDescriptor->DmaWidth) {
|
|||
|
case Width8Bits:
|
|||
|
|
|||
|
//
|
|||
|
// The channel must use controller 1.
|
|||
|
//
|
|||
|
|
|||
|
if (controllerNumber != 1) {
|
|||
|
ObDereferenceObject( adapterObject );
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case Width16Bits:
|
|||
|
|
|||
|
//
|
|||
|
// The channel must use controller 2.
|
|||
|
//
|
|||
|
|
|||
|
if (controllerNumber != 2) {
|
|||
|
ObDereferenceObject( adapterObject );
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
|
|||
|
adapterObject->Width16Bits = TRUE;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
ObDereferenceObject( adapterObject );
|
|||
|
return(NULL);
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// 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_PORT_UCHAR( &dmaControl->Mode, adapterMode );
|
|||
|
|
|||
|
//
|
|||
|
// Unmask the DMA channel.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
&dmaControl->SingleMask,
|
|||
|
(UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
|
|||
|
);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// This request is for DMA controller 1
|
|||
|
//
|
|||
|
|
|||
|
PDMA2_CONTROL dmaControl;
|
|||
|
|
|||
|
dmaControl = adapterObject->AdapterBaseVa;
|
|||
|
|
|||
|
WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
|
|||
|
|
|||
|
//
|
|||
|
// Unmask the DMA channel.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_PORT_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
|
|||
|
HalpMapEisaTransfer(
|
|||
|
IN PADAPTER_OBJECT AdapterObject,
|
|||
|
IN ULONG LogicalAddress,
|
|||
|
IN ULONG Length,
|
|||
|
IN BOOLEAN WriteToDevice
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is invoked to perform the actual programming of the
|
|||
|
DMA controllers to perform a transfer for Eisa/Isa systems.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AdapterObject - Pointer to the adapter object representing the DMA
|
|||
|
controller channel that has been allocated.
|
|||
|
|
|||
|
Mdl - Pointer to the MDL that describes the pages of memory that are
|
|||
|
being read or written.
|
|||
|
|
|||
|
MapRegisterBase - The address of the base map register that has been
|
|||
|
allocated to the device driver for use in mapping the transfer.
|
|||
|
|
|||
|
CurrentVa - Current virtual address in the buffer described by the MDL
|
|||
|
that the transfer is being done to or from.
|
|||
|
|
|||
|
Length - Supplies the length of the transfer. This determines the
|
|||
|
number of map registers that need to be written to map the transfer.
|
|||
|
Returns the length of the transfer which was actually mapped.
|
|||
|
|
|||
|
WriteToDevice - Boolean value that indicates whether this is a write
|
|||
|
to the device from memory (TRUE), or vice versa.
|
|||
|
|
|||
|
LogicalAddress - Supplies the logical address of the transfer.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns a boolean identifying if the operation was successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
KIRQL Irql;
|
|||
|
UCHAR adapterMode;
|
|||
|
PUCHAR bytePointer;
|
|||
|
UCHAR dataByte;
|
|||
|
ULONG logicalAddress;
|
|||
|
ULONG transferLength;
|
|||
|
|
|||
|
logicalAddress = LogicalAddress;
|
|||
|
transferLength = Length;
|
|||
|
|
|||
|
//
|
|||
|
// Determine the mode based on the transfer direction.
|
|||
|
//
|
|||
|
|
|||
|
adapterMode = AdapterObject->AdapterMode;
|
|||
|
((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
|
|||
|
WRITE_TRANSFER : READ_TRANSFER);
|
|||
|
|
|||
|
bytePointer = (PUCHAR) &logicalAddress;
|
|||
|
|
|||
|
//
|
|||
|
// Check to see if this request is for a master I/O card.
|
|||
|
//
|
|||
|
|
|||
|
//jnfix - this code not in Jensen
|
|||
|
if( ((PDMA_EISA_MODE)&adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
|
|||
|
|
|||
|
//
|
|||
|
// Set the mode, disable the request and return.
|
|||
|
//
|
|||
|
|
|||
|
if( AdapterObject->AdapterNumber == 1 ){
|
|||
|
|
|||
|
//
|
|||
|
// 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 {
|
|||
|
|
|||
|
//
|
|||
|
// 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) );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (AdapterObject->Width16Bits) {
|
|||
|
|
|||
|
//
|
|||
|
// If this is a 16 bit transfer then adjust the length and the address
|
|||
|
// for the 16 bit DMA mode.
|
|||
|
//
|
|||
|
|
|||
|
transferLength >>= 1;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Grab the spinlock for the system DMA controller.
|
|||
|
//
|
|||
|
|
|||
|
KeAcquireSpinLock( &AdapterObject->MapAdapter->SpinLock, &Irql );
|
|||
|
|
|||
|
//
|
|||
|
// Determine the controller number based on the Adapter number.
|
|||
|
//
|
|||
|
|
|||
|
if (AdapterObject->AdapterNumber == 1) {
|
|||
|
|
|||
|
//
|
|||
|
// This request is for DMA controller 1
|
|||
|
//
|
|||
|
|
|||
|
PDMA1_CONTROL dmaControl;
|
|||
|
|
|||
|
dmaControl = AdapterObject->AdapterBaseVa;
|
|||
|
|
|||
|
WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
|
|||
|
|
|||
|
WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
|
|||
|
.DmaBaseAddress,
|
|||
|
bytePointer[0]
|
|||
|
);
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
|
|||
|
.DmaBaseAddress,
|
|||
|
bytePointer[1]
|
|||
|
);
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
|
|||
|
(ULONG)AdapterObject->PagePort,
|
|||
|
bytePointer[2]
|
|||
|
);
|
|||
|
|
|||
|
if (HalpEisaDma) {
|
|||
|
|
|||
|
//
|
|||
|
// 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_PORT_UCHAR(
|
|||
|
((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
|
|||
|
(ULONG)AdapterObject->PagePort,
|
|||
|
0
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Notify DMA chip of the length to transfer.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
|
|||
|
.DmaBaseCount,
|
|||
|
(UCHAR) ((transferLength - 1) & 0xff)
|
|||
|
);
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
|
|||
|
.DmaBaseCount,
|
|||
|
(UCHAR) ((transferLength - 1) >> 8)
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Set the DMA chip to read or write mode; and unmask it.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
&dmaControl->SingleMask,
|
|||
|
(UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
|
|||
|
);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// This request is for DMA controller 2
|
|||
|
//
|
|||
|
|
|||
|
PDMA2_CONTROL dmaControl;
|
|||
|
|
|||
|
dmaControl = AdapterObject->AdapterBaseVa;
|
|||
|
|
|||
|
WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
|
|||
|
|
|||
|
WRITE_PORT_UCHAR( &dmaControl->Mode, adapterMode );
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
|
|||
|
.DmaBaseAddress,
|
|||
|
bytePointer[0]
|
|||
|
);
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
|
|||
|
.DmaBaseAddress,
|
|||
|
bytePointer[1]
|
|||
|
);
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
|
|||
|
(ULONG)AdapterObject->PagePort,
|
|||
|
bytePointer[2]
|
|||
|
);
|
|||
|
|
|||
|
if (HalpEisaDma) {
|
|||
|
|
|||
|
//
|
|||
|
// 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_PORT_UCHAR(
|
|||
|
((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
|
|||
|
(ULONG)AdapterObject->PagePort,
|
|||
|
0
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Notify DMA chip of the length to transfer.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
|
|||
|
.DmaBaseCount,
|
|||
|
(UCHAR) ((transferLength - 1) & 0xff)
|
|||
|
);
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
|
|||
|
.DmaBaseCount,
|
|||
|
(UCHAR) ((transferLength - 1) >> 8)
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Set the DMA chip to read or write mode; and unmask it.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
&dmaControl->SingleMask,
|
|||
|
(UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
KeReleaseSpinLock (&AdapterObject->MapAdapter->SpinLock, Irql);
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
HalpFlushEisaAdapter(
|
|||
|
IN PADAPTER_OBJECT AdapterObject,
|
|||
|
IN PMDL Mdl,
|
|||
|
IN PVOID MapRegisterBase,
|
|||
|
IN PVOID CurrentVa,
|
|||
|
IN ULONG Length,
|
|||
|
IN BOOLEAN WriteToDevice
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine flushes the DMA adapter object buffers. For EISA systems
|
|||
|
its clears the enable flag which aborts the dma.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AdapterObject - Pointer to the adapter object representing the DMA
|
|||
|
controller channel.
|
|||
|
|
|||
|
Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
|
|||
|
buffer to/from which the I/O occured.
|
|||
|
|
|||
|
MapRegisterBase - A pointer to the base of the map registers in the adapter
|
|||
|
or DMA controller.
|
|||
|
|
|||
|
CurrentVa - The current virtual address in the buffer described the the Mdl
|
|||
|
where the I/O operation occurred.
|
|||
|
|
|||
|
Length - Supplies the length of the transfer.
|
|||
|
|
|||
|
WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
|
|||
|
the data transfer was to the device.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE - If the transfer was successful.
|
|||
|
|
|||
|
FALSE - If there was an error in the transfer.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
BOOLEAN masterDevice;
|
|||
|
KIRQL Irql;
|
|||
|
|
|||
|
masterDevice = AdapterObject->MasterDevice;
|
|||
|
|
|||
|
KeAcquireSpinLock( &AdapterObject->MapAdapter->SpinLock, &Irql );
|
|||
|
|
|||
|
//
|
|||
|
// If this is a slave device, then stop the DMA controller.
|
|||
|
//
|
|||
|
|
|||
|
if (masterDevice == FALSE) {
|
|||
|
|
|||
|
//
|
|||
|
// Mask the DMA request line so that DMA requests cannot occur.
|
|||
|
//
|
|||
|
|
|||
|
if (AdapterObject->AdapterNumber == 1) {
|
|||
|
|
|||
|
//
|
|||
|
// This request is for DMA controller 1
|
|||
|
//
|
|||
|
|
|||
|
PDMA1_CONTROL dmaControl;
|
|||
|
|
|||
|
dmaControl = AdapterObject->AdapterBaseVa;
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
&dmaControl->SingleMask,
|
|||
|
(UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
|
|||
|
);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// This request is for DMA controller 2
|
|||
|
//
|
|||
|
|
|||
|
PDMA2_CONTROL dmaControl;
|
|||
|
|
|||
|
dmaControl = AdapterObject->AdapterBaseVa;
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(
|
|||
|
&dmaControl->SingleMask,
|
|||
|
(UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
KeReleaseSpinLock( &AdapterObject->MapAdapter->SpinLock, Irql );
|
|||
|
|
|||
|
return TRUE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpReadEisaDmaCounter(
|
|||
|
IN PADAPTER_OBJECT AdapterObject
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function reads the DMA counter and returns the number of bytes left
|
|||
|
to be transfered.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AdapterObject - Supplies a pointer to the adapter object to be read.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the number of bytes still be be transfered.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
ULONG count;
|
|||
|
ULONG high;
|
|||
|
KIRQL Irql;
|
|||
|
|
|||
|
//
|
|||
|
// Grab the spinlock for the system DMA controller.
|
|||
|
//
|
|||
|
|
|||
|
KeAcquireSpinLock( &AdapterObject->MapAdapter->SpinLock, &Irql );
|
|||
|
|
|||
|
//
|
|||
|
// Determine the controller number based on the Adapter number.
|
|||
|
//
|
|||
|
|
|||
|
if (AdapterObject->AdapterNumber == 1) {
|
|||
|
|
|||
|
//
|
|||
|
// This request is for DMA controller 1
|
|||
|
//
|
|||
|
|
|||
|
PDMA1_CONTROL dmaControl;
|
|||
|
|
|||
|
dmaControl = AdapterObject->AdapterBaseVa;
|
|||
|
|
|||
|
WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Initialize count to a value which will not match.
|
|||
|
//
|
|||
|
|
|||
|
count = 0xFFFF00;
|
|||
|
|
|||
|
//
|
|||
|
// Loop until the same high byte is read twice.
|
|||
|
//
|
|||
|
|
|||
|
do {
|
|||
|
|
|||
|
high = count;
|
|||
|
|
|||
|
WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
|
|||
|
|
|||
|
//
|
|||
|
// Read the current DMA count.
|
|||
|
//
|
|||
|
|
|||
|
count = READ_PORT_UCHAR(
|
|||
|
&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
|
|||
|
.DmaBaseCount
|
|||
|
);
|
|||
|
|
|||
|
count |= READ_PORT_UCHAR(
|
|||
|
&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
|
|||
|
.DmaBaseCount
|
|||
|
) << 8;
|
|||
|
|
|||
|
} while ((count & 0xFFFF00) != (high & 0xFFFF00));
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// This request is for DMA controller 2
|
|||
|
//
|
|||
|
|
|||
|
PDMA2_CONTROL dmaControl;
|
|||
|
|
|||
|
dmaControl = AdapterObject->AdapterBaseVa;
|
|||
|
|
|||
|
WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
|
|||
|
|
|||
|
//
|
|||
|
// Initialize count to a value which will not match.
|
|||
|
//
|
|||
|
|
|||
|
count = 0xFFFF00;
|
|||
|
|
|||
|
//
|
|||
|
// Loop until the same high byte is read twice.
|
|||
|
//
|
|||
|
|
|||
|
do {
|
|||
|
|
|||
|
high = count;
|
|||
|
|
|||
|
WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
|
|||
|
|
|||
|
//
|
|||
|
// Read the current DMA count.
|
|||
|
//
|
|||
|
|
|||
|
count = READ_PORT_UCHAR(
|
|||
|
&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
|
|||
|
.DmaBaseCount
|
|||
|
);
|
|||
|
|
|||
|
count |= READ_PORT_UCHAR(
|
|||
|
&dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
|
|||
|
.DmaBaseCount
|
|||
|
) << 8;
|
|||
|
|
|||
|
} while ((count & 0xFFFF00) != (high & 0xFFFF00));
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Release the spinlock for the system DMA controller.
|
|||
|
//
|
|||
|
|
|||
|
KeReleaseSpinLock( &AdapterObject->MapAdapter->SpinLock, Irql );
|
|||
|
|
|||
|
//
|
|||
|
// The DMA counter has a bias of one and can only be 16 bit long.
|
|||
|
//
|
|||
|
|
|||
|
count = (count + 1) & 0xFFFF;
|
|||
|
|
|||
|
//
|
|||
|
// If this is a 16 bit dma the multiply the count by 2.
|
|||
|
//
|
|||
|
|
|||
|
if (AdapterObject->Width16Bits) {
|
|||
|
|
|||
|
count *= 2;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return(count);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#if !defined(AXP_FIRMWARE)
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpGetEisaData (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN ULONG SlotNumber,
|
|||
|
IN PVOID Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The function returns the Eisa bus data for a slot or address.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
BusHandler - Registered BUSHANDLER for the target configuration space
|
|||
|
|
|||
|
RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
|
|||
|
request.
|
|||
|
|
|||
|
Buffer - Supplies the space to store the data.
|
|||
|
|
|||
|
Offset - Supplies the offset into data to begin access.
|
|||
|
|
|||
|
Length - Supplies a count in bytes of the maximum amount to return.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the amount of data stored into the buffer.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
OBJECT_ATTRIBUTES BusObjectAttributes;
|
|||
|
PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
|
|||
|
PWSTR ConfigData = L"Configuration Data";
|
|||
|
ANSI_STRING TmpString;
|
|||
|
ULONG BusNumber;
|
|||
|
UCHAR BusString[] = "00";
|
|||
|
UNICODE_STRING RootName, BusName;
|
|||
|
UNICODE_STRING ConfigDataName;
|
|||
|
NTSTATUS NtStatus;
|
|||
|
PKEY_VALUE_FULL_INFORMATION ValueInformation;
|
|||
|
PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
|
|||
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
|
|||
|
PCM_EISA_SLOT_INFORMATION SlotInformation;
|
|||
|
ULONG PartialCount;
|
|||
|
ULONG TotalDataSize, SlotDataSize;
|
|||
|
HANDLE EisaHandle, BusHandle;
|
|||
|
ULONG BytesWritten, BytesNeeded;
|
|||
|
PUCHAR KeyValueBuffer;
|
|||
|
ULONG i;
|
|||
|
ULONG DataLength = 0;
|
|||
|
PUCHAR DataBuffer = Buffer;
|
|||
|
BOOLEAN Found = FALSE;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER( RootHandler );
|
|||
|
|
|||
|
RtlInitUnicodeString(
|
|||
|
&RootName,
|
|||
|
EisaPath
|
|||
|
);
|
|||
|
|
|||
|
InitializeObjectAttributes(
|
|||
|
&ObjectAttributes,
|
|||
|
&RootName,
|
|||
|
OBJ_CASE_INSENSITIVE,
|
|||
|
(HANDLE)NULL,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Open the EISA root
|
|||
|
//
|
|||
|
|
|||
|
NtStatus = ZwOpenKey(
|
|||
|
&EisaHandle,
|
|||
|
KEY_READ,
|
|||
|
&ObjectAttributes
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(NtStatus)) {
|
|||
|
#if DBG
|
|||
|
DbgPrint("HAL: Open Status = %x\n",NtStatus);
|
|||
|
#endif
|
|||
|
return(0);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Init bus number path
|
|||
|
//
|
|||
|
|
|||
|
BusNumber = BusHandler->BusNumber;
|
|||
|
|
|||
|
if (BusNumber > 99) {
|
|||
|
return (0);
|
|||
|
}
|
|||
|
|
|||
|
if (BusNumber > 9) {
|
|||
|
BusString[0] += (UCHAR) (BusNumber/10);
|
|||
|
BusString[1] += (UCHAR) (BusNumber % 10);
|
|||
|
} else {
|
|||
|
BusString[0] += (UCHAR) BusNumber;
|
|||
|
BusString[1] = '\0';
|
|||
|
}
|
|||
|
|
|||
|
RtlInitAnsiString(
|
|||
|
&TmpString,
|
|||
|
BusString
|
|||
|
);
|
|||
|
|
|||
|
RtlAnsiStringToUnicodeString(
|
|||
|
&BusName,
|
|||
|
&TmpString,
|
|||
|
TRUE
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
InitializeObjectAttributes(
|
|||
|
&BusObjectAttributes,
|
|||
|
&BusName,
|
|||
|
OBJ_CASE_INSENSITIVE,
|
|||
|
(HANDLE)EisaHandle,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Open the EISA root + Bus Number
|
|||
|
//
|
|||
|
|
|||
|
NtStatus = ZwOpenKey(
|
|||
|
&BusHandle,
|
|||
|
KEY_READ,
|
|||
|
&BusObjectAttributes
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(NtStatus)) {
|
|||
|
#if DBG
|
|||
|
DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus);
|
|||
|
#endif
|
|||
|
return(0);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// opening the configuration data. This first call tells us how
|
|||
|
// much memory we need to allocate
|
|||
|
//
|
|||
|
|
|||
|
RtlInitUnicodeString(
|
|||
|
&ConfigDataName,
|
|||
|
ConfigData
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// This should fail. We need to make this call so we can
|
|||
|
// get the actual size of the buffer to allocate.
|
|||
|
//
|
|||
|
|
|||
|
ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i;
|
|||
|
NtStatus = ZwQueryValueKey(
|
|||
|
BusHandle,
|
|||
|
&ConfigDataName,
|
|||
|
KeyValueFullInformation,
|
|||
|
ValueInformation,
|
|||
|
0,
|
|||
|
&BytesNeeded
|
|||
|
);
|
|||
|
|
|||
|
KeyValueBuffer = ExAllocatePool(
|
|||
|
NonPagedPool,
|
|||
|
BytesNeeded
|
|||
|
);
|
|||
|
|
|||
|
if (KeyValueBuffer == NULL) {
|
|||
|
#if DBG
|
|||
|
DbgPrint("HAL: Cannot allocate Key Value Buffer\n");
|
|||
|
#endif
|
|||
|
ZwClose(BusHandle);
|
|||
|
return(0);
|
|||
|
}
|
|||
|
|
|||
|
ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
|
|||
|
|
|||
|
NtStatus = ZwQueryValueKey(
|
|||
|
BusHandle,
|
|||
|
&ConfigDataName,
|
|||
|
KeyValueFullInformation,
|
|||
|
ValueInformation,
|
|||
|
BytesNeeded,
|
|||
|
&BytesWritten
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
ZwClose(BusHandle);
|
|||
|
|
|||
|
if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) {
|
|||
|
#if DBG
|
|||
|
DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus);
|
|||
|
#endif
|
|||
|
ExFreePool(KeyValueBuffer);
|
|||
|
return(0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// We get back a Full Resource Descriptor List
|
|||
|
//
|
|||
|
|
|||
|
Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
|
|||
|
ValueInformation->DataOffset);
|
|||
|
|
|||
|
PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
|
|||
|
&(Descriptor->PartialResourceList.PartialDescriptors);
|
|||
|
PartialCount = Descriptor->PartialResourceList.Count;
|
|||
|
|
|||
|
for (i = 0; i < PartialCount; i++) {
|
|||
|
|
|||
|
//
|
|||
|
// Do each partial Resource
|
|||
|
//
|
|||
|
|
|||
|
switch (PartialResource->Type) {
|
|||
|
case CmResourceTypeNull:
|
|||
|
case CmResourceTypePort:
|
|||
|
case CmResourceTypeInterrupt:
|
|||
|
case CmResourceTypeMemory:
|
|||
|
case CmResourceTypeDma:
|
|||
|
|
|||
|
//
|
|||
|
// We dont care about these.
|
|||
|
//
|
|||
|
|
|||
|
PartialResource++;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case CmResourceTypeDeviceSpecific:
|
|||
|
|
|||
|
//
|
|||
|
// Bingo!
|
|||
|
//
|
|||
|
|
|||
|
TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
|
|||
|
|
|||
|
SlotInformation = (PCM_EISA_SLOT_INFORMATION)
|
|||
|
((PUCHAR)PartialResource +
|
|||
|
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
|
|||
|
|
|||
|
while (((LONG)TotalDataSize) > 0) {
|
|||
|
|
|||
|
if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
|
|||
|
|
|||
|
SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
|
|||
|
SlotInformation->NumberFunctions *
|
|||
|
sizeof(CM_EISA_FUNCTION_INFORMATION);
|
|||
|
}
|
|||
|
|
|||
|
if (SlotDataSize > TotalDataSize) {
|
|||
|
|
|||
|
//
|
|||
|
// Something is wrong again
|
|||
|
//
|
|||
|
|
|||
|
ExFreePool(KeyValueBuffer);
|
|||
|
return(0);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (SlotNumber != 0) {
|
|||
|
|
|||
|
SlotNumber--;
|
|||
|
|
|||
|
SlotInformation = (PCM_EISA_SLOT_INFORMATION)
|
|||
|
((PUCHAR)SlotInformation + SlotDataSize);
|
|||
|
|
|||
|
TotalDataSize -= SlotDataSize;
|
|||
|
|
|||
|
continue;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// This is our slot
|
|||
|
//
|
|||
|
|
|||
|
Found = TRUE;
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// End loop
|
|||
|
//
|
|||
|
|
|||
|
i = PartialCount;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
#if DBG
|
|||
|
DbgPrint("Bad Data in registry!\n");
|
|||
|
#endif
|
|||
|
|
|||
|
ExFreePool(KeyValueBuffer);
|
|||
|
return(0);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (Found) {
|
|||
|
|
|||
|
i = Length + Offset;
|
|||
|
if (i > SlotDataSize) {
|
|||
|
i = SlotDataSize;
|
|||
|
}
|
|||
|
|
|||
|
DataLength = i - Offset;
|
|||
|
RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ExFreePool(KeyValueBuffer);
|
|||
|
return DataLength;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
HalpAdjustEisaResourceList (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The function adjusts pResourceList to keep it in the bounds of the EISA bus
|
|||
|
resources.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BusHandler - Registered BUSHANDLER for the target configuration space
|
|||
|
|
|||
|
RootHandler - Register BUSHANDLER for the orginating HalAdjustResourceList request.
|
|||
|
|
|||
|
pResourceList - Supplies the PIO_RESOURCE_REQUIREMENTS_LIST to be checked.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
LARGE_INTEGER li64k, li4g;
|
|||
|
|
|||
|
li64k.QuadPart = 0xffff;
|
|||
|
li4g.QuadPart = 0xffffffff;
|
|||
|
|
|||
|
HalpAdjustResourceListUpperLimits (
|
|||
|
pResourceList,
|
|||
|
li64k, // Bus supports up to I/O port 0xFFFF
|
|||
|
li4g, // Bus supports up to memory 0xFFFFFFFF
|
|||
|
15, // Bus supports up to 15 IRQs
|
|||
|
7 // Bus supports up to Dma channel 7
|
|||
|
);
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
HalpAdjustIsaResourceList (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The function adjusts pResourceList to keep it in the bounds of ISA bus
|
|||
|
resources.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BusHandler - Registered BUSHANDLER for the target configuration space
|
|||
|
|
|||
|
RootHandler - Register BUSHANDLER for the orginating HalAdjustResourceList request.
|
|||
|
|
|||
|
pResourceList - Supplies the PIO_RESOURCE_REQUIREMENTS_LIST to be checked.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
LARGE_INTEGER li64k, limem;
|
|||
|
|
|||
|
li64k.QuadPart = 0xffff;
|
|||
|
limem.QuadPart = 0xffffff;
|
|||
|
|
|||
|
HalpAdjustResourceListUpperLimits (
|
|||
|
pResourceList,
|
|||
|
li64k, // Bus supports up to I/O port 0xFFFF
|
|||
|
limem, // Bus supports up to memory 0xFFFFFF
|
|||
|
15, // Bus supports up to 15 IRQs
|
|||
|
7 // Bus supports up to Dma channel 7
|
|||
|
);
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
#endif // AXP_FIRMWARE
|