308 lines
9.7 KiB
C
308 lines
9.7 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
eisac.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements routines to get EISA configuration information.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Shie-Lin Tzong (shielint) 18-Jan-1992
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
16-bit real mode.
|
|||
|
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "hwdetect.h"
|
|||
|
#include "string.h"
|
|||
|
|
|||
|
typedef EISA_PORT_CONFIGURATION far *FPEISA_PORT_CONFIGURATION;
|
|||
|
|
|||
|
extern CM_EISA_FUNCTION_INFORMATION FunctionInformation;
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
GetEisaConfigurationData (
|
|||
|
FPVOID Buffer,
|
|||
|
FPULONG Size
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine collects all the eisa slot information, function
|
|||
|
information and stores it in the caller supplied Buffer and
|
|||
|
returns the size of the data.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Buffer - A pointer to a PVOID to recieve the address of configuration
|
|||
|
data.
|
|||
|
|
|||
|
Size - a pointer to a ULONG to receive the size of the configuration
|
|||
|
data.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UCHAR Slot=0;
|
|||
|
UCHAR Function=0, SlotFunctions = 0, ReturnCode;
|
|||
|
EISA_SLOT_INFORMATION SlotInformation;
|
|||
|
FPUCHAR ConfigurationData, CurrentData;
|
|||
|
FPEISA_SLOT_INFORMATION FarSlotInformation;
|
|||
|
ULONG TotalSize = DATA_HEADER_SIZE;
|
|||
|
BOOLEAN Overflowed = FALSE;
|
|||
|
|
|||
|
HwGetEisaSlotInformation(&SlotInformation, Slot);
|
|||
|
|
|||
|
TotalSize += sizeof(EISA_SLOT_INFORMATION);
|
|||
|
ConfigurationData = (FPVOID)HwAllocateHeap(TotalSize, FALSE);
|
|||
|
CurrentData = ConfigurationData + DATA_HEADER_SIZE;
|
|||
|
|
|||
|
_fmemcpy(CurrentData, (FPVOID)&SlotInformation, sizeof(EISA_SLOT_INFORMATION));
|
|||
|
FarSlotInformation = (FPEISA_SLOT_INFORMATION)CurrentData;
|
|||
|
|
|||
|
while (SlotInformation.ReturnCode != EISA_INVALID_SLOT) {
|
|||
|
|
|||
|
//
|
|||
|
// Ensure that the slot is not empty and collect all the function
|
|||
|
// information for the slot.
|
|||
|
//
|
|||
|
|
|||
|
if (SlotInformation.ReturnCode != EISA_EMPTY_SLOT) {
|
|||
|
|
|||
|
while (SlotInformation.NumberFunctions > Function) {
|
|||
|
ReturnCode = HwGetEisaFunctionInformation(
|
|||
|
&FunctionInformation, Slot, Function);
|
|||
|
Function++;
|
|||
|
|
|||
|
//
|
|||
|
// if function call succeeds and the function contains usefull
|
|||
|
// information or this is the last function for the slot and
|
|||
|
// there is no function information collected for the slot, we
|
|||
|
// will save this function information to our heap.
|
|||
|
//
|
|||
|
|
|||
|
if (!ReturnCode) {
|
|||
|
if (((FunctionInformation.FunctionFlags & 0x7f) != 0) ||
|
|||
|
(SlotInformation.NumberFunctions == Function &&
|
|||
|
SlotFunctions == 0)) {
|
|||
|
CurrentData = (FPVOID)HwAllocateHeap(
|
|||
|
sizeof(EISA_FUNCTION_INFORMATION), FALSE);
|
|||
|
if (CurrentData == NULL) {
|
|||
|
Overflowed = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
SlotFunctions++;
|
|||
|
TotalSize += sizeof(EISA_FUNCTION_INFORMATION);
|
|||
|
_fmemcpy(CurrentData,
|
|||
|
(FPVOID)&FunctionInformation,
|
|||
|
sizeof(EISA_FUNCTION_INFORMATION));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
FarSlotInformation->NumberFunctions = SlotFunctions;
|
|||
|
}
|
|||
|
if (Overflowed) {
|
|||
|
break;
|
|||
|
}
|
|||
|
Slot++;
|
|||
|
Function = 0;
|
|||
|
HwGetEisaSlotInformation(&SlotInformation, Slot);
|
|||
|
CurrentData = (FPVOID)HwAllocateHeap(
|
|||
|
sizeof(EISA_SLOT_INFORMATION), FALSE);
|
|||
|
if (CurrentData == NULL) {
|
|||
|
Overflowed = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
TotalSize += sizeof(EISA_SLOT_INFORMATION);
|
|||
|
_fmemcpy(CurrentData,
|
|||
|
(FPVOID)&SlotInformation,
|
|||
|
sizeof(EISA_SLOT_INFORMATION));
|
|||
|
FarSlotInformation = (FPEISA_SLOT_INFORMATION)CurrentData;
|
|||
|
SlotFunctions = 0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Free the last EISA_SLOT_INFORMATION space which contains the slot
|
|||
|
// information for IVALID SLOT
|
|||
|
//
|
|||
|
|
|||
|
if (Overflowed != TRUE) {
|
|||
|
HwFreeHeap(sizeof(EISA_SLOT_INFORMATION));
|
|||
|
TotalSize -= sizeof(EISA_SLOT_INFORMATION);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check if we got any EISA information. If nothing, we release
|
|||
|
// the space for data header and return.
|
|||
|
//
|
|||
|
|
|||
|
if (TotalSize == DATA_HEADER_SIZE) {
|
|||
|
HwFreeHeap(DATA_HEADER_SIZE);
|
|||
|
*(FPULONG)Buffer = (ULONG)0;
|
|||
|
*Size = (ULONG)0;
|
|||
|
} else {
|
|||
|
HwSetUpFreeFormDataHeader((FPHWRESOURCE_DESCRIPTOR_LIST)ConfigurationData,
|
|||
|
0,
|
|||
|
0,
|
|||
|
0,
|
|||
|
TotalSize - DATA_HEADER_SIZE
|
|||
|
);
|
|||
|
*(FPULONG)Buffer = (ULONG)ConfigurationData;
|
|||
|
*Size = TotalSize;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
HwEisaGetIrqFromPort (
|
|||
|
USHORT Port,
|
|||
|
PUCHAR Irq,
|
|||
|
PUCHAR TriggerMethod
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine scans EISA configuration data to match the I/O port address.
|
|||
|
The IRQ information is returned from the matched EISA function information.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Port - The I/O port address to scan for.
|
|||
|
|
|||
|
Irq - Supplies a pointer to a variable to receive the irq information.
|
|||
|
|
|||
|
TriggerMethod - Supplies a pointer to a variable to receive the
|
|||
|
EISA interrupt trigger method.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE - if the Irq information is found. Otherwise a value of FALSE is
|
|||
|
returned.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UCHAR Function, i, j;
|
|||
|
FPEISA_SLOT_INFORMATION SlotInformation;
|
|||
|
FPEISA_FUNCTION_INFORMATION Buffer;
|
|||
|
UCHAR FunctionFlags;
|
|||
|
ULONG SizeToScan = 0L;
|
|||
|
EISA_PORT_CONFIGURATION PortConfig;
|
|||
|
EISA_IRQ_DESCRIPTOR IrqConfig;
|
|||
|
SlotInformation = (FPEISA_SLOT_INFORMATION)HwEisaConfigurationData;
|
|||
|
|
|||
|
//
|
|||
|
// Scan through all the EISA configuration data.
|
|||
|
//
|
|||
|
|
|||
|
while (SizeToScan < HwEisaConfigurationSize) {
|
|||
|
if (SlotInformation->ReturnCode != EISA_EMPTY_SLOT) {
|
|||
|
|
|||
|
//
|
|||
|
// Make sure this slot contains PORT_RANGE and IRQ information.
|
|||
|
//
|
|||
|
|
|||
|
if ((SlotInformation->FunctionInformation & EISA_HAS_PORT_RANGE) &&
|
|||
|
(SlotInformation->FunctionInformation & EISA_HAS_IRQ_ENTRY)) {
|
|||
|
|
|||
|
Buffer = (FPEISA_FUNCTION_INFORMATION)(SlotInformation + 1);
|
|||
|
|
|||
|
//
|
|||
|
// For each function of the slot, if it contains both the IRQ
|
|||
|
// and PORT information, we then check for its PORT address.
|
|||
|
//
|
|||
|
|
|||
|
for (Function = 0; Function < SlotInformation->NumberFunctions; Function++) {
|
|||
|
FunctionFlags = Buffer->FunctionFlags;
|
|||
|
if ((FunctionFlags & EISA_HAS_IRQ_ENTRY) &&
|
|||
|
(FunctionFlags & EISA_HAS_PORT_RANGE)) {
|
|||
|
for (i = 0; i < 20 ; i++ ) {
|
|||
|
PortConfig = Buffer->EisaPort[i];
|
|||
|
if ((Port >= PortConfig.PortAddress) &&
|
|||
|
(Port <= (PortConfig.PortAddress +
|
|||
|
PortConfig.Configuration.NumberPorts))) {
|
|||
|
|
|||
|
//
|
|||
|
// If there is only one IRQ entry, that's the
|
|||
|
// one we want. (This is the normal case and
|
|||
|
// correct usage of EISA function data.) Otherwise,
|
|||
|
// we try to get the irq from the same index
|
|||
|
// number as port entry. (This is ALR's incorrect
|
|||
|
// way of packing functions into one function
|
|||
|
// data.)
|
|||
|
//
|
|||
|
|
|||
|
IrqConfig = Buffer->EisaIrq[0].ConfigurationByte;
|
|||
|
if (IrqConfig.MoreEntries == 0) {
|
|||
|
*Irq = IrqConfig.Interrupt;
|
|||
|
*TriggerMethod = IrqConfig.LevelTriggered;
|
|||
|
return(TRUE);
|
|||
|
} else if (i >= 7) {
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
for (j = 0; j <= i; j++) {
|
|||
|
if (j == i) {
|
|||
|
*Irq = IrqConfig.Interrupt;
|
|||
|
*TriggerMethod = IrqConfig.LevelTriggered;
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
if (!IrqConfig.MoreEntries) {
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
IrqConfig =
|
|||
|
Buffer->EisaIrq[j+1].ConfigurationByte;
|
|||
|
}
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
if (!PortConfig.Configuration.MoreEntries) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
Buffer++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Move on to next slot
|
|||
|
//
|
|||
|
|
|||
|
SizeToScan += sizeof(EISA_SLOT_INFORMATION) +
|
|||
|
sizeof(EISA_FUNCTION_INFORMATION) *
|
|||
|
SlotInformation->NumberFunctions;
|
|||
|
SlotInformation = (FPEISA_SLOT_INFORMATION)(HwEisaConfigurationData +
|
|||
|
SizeToScan);
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// This is a empty slot. We simply skip it.
|
|||
|
//
|
|||
|
|
|||
|
SizeToScan += sizeof(EISA_SLOT_INFORMATION);
|
|||
|
SlotInformation++;
|
|||
|
}
|
|||
|
}
|
|||
|
return(FALSE);
|
|||
|
}
|