|
|
/*++
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); }
|