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.
1534 lines
34 KiB
1534 lines
34 KiB
/*++
|
|
|
|
Copyright (c) 1990-1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
D:\nt\private\ntos\ndis\aic5900\init.c
|
|
|
|
Abstract:
|
|
|
|
Author:
|
|
|
|
Kyle Brandon (KyleB)
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "aic5900.h"
|
|
|
|
#define MODULE_NUMBER MODULE_INIT
|
|
|
|
#pragma NDIS_INIT_FUNCTION(DriverEntry)
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
NDIS_MINIPORT_CHARACTERISTICS Aic5900Chars;
|
|
NDIS_HANDLE hWrapper;
|
|
|
|
//
|
|
// Initialize the wrapper.
|
|
//
|
|
NdisMInitializeWrapper(
|
|
&hWrapper,
|
|
DriverObject,
|
|
RegistryPath,
|
|
NULL);
|
|
|
|
NdisZeroMemory(&Aic5900Chars, sizeof(Aic5900Chars));
|
|
|
|
//
|
|
// Initialize the miniport characteristics.
|
|
//
|
|
Aic5900Chars.MajorNdisVersion = AIC5900_NDIS_MAJOR_VERSION;
|
|
Aic5900Chars.MinorNdisVersion = AIC5900_NDIS_MINOR_VERSION;
|
|
Aic5900Chars.CheckForHangHandler = Aic5900CheckForHang;
|
|
Aic5900Chars.DisableInterruptHandler = Aic5900DisableInterrupt;
|
|
Aic5900Chars.EnableInterruptHandler = Aic5900EnableInterrupt;
|
|
Aic5900Chars.HaltHandler = Aic5900Halt;
|
|
Aic5900Chars.HandleInterruptHandler = Aic5900HandleInterrupt;
|
|
Aic5900Chars.InitializeHandler = Aic5900Initialize;
|
|
Aic5900Chars.ISRHandler = Aic5900ISR;
|
|
Aic5900Chars.ReconfigureHandler = NULL;
|
|
Aic5900Chars.ResetHandler = Aic5900Reset;
|
|
|
|
Aic5900Chars.ReturnPacketHandler = Aic5900ReturnPackets;
|
|
Aic5900Chars.AllocateCompleteHandler = Aic5900AllocateComplete;
|
|
Aic5900Chars.SetInformationHandler = Aic5900SetInformation;
|
|
Aic5900Chars.QueryInformationHandler = Aic5900QueryInformation;
|
|
|
|
Aic5900Chars.CoSendPacketsHandler = Aic5900SendPackets;
|
|
|
|
Aic5900Chars.CoCreateVcHandler = Aic5900CreateVc;
|
|
Aic5900Chars.CoDeleteVcHandler = Aic5900DeleteVc;
|
|
Aic5900Chars.CoActivateVcHandler = Aic5900ActivateVc;
|
|
Aic5900Chars.CoDeactivateVcHandler = Aic5900DeactivateVc;
|
|
Aic5900Chars.CoRequestHandler = Aic5900Request;
|
|
|
|
//
|
|
// Register the miniport with NDIS.
|
|
//
|
|
Status = NdisMRegisterMiniport(
|
|
hWrapper,
|
|
&Aic5900Chars,
|
|
sizeof(Aic5900Chars));
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
//
|
|
// Save the handle to the wrapper.
|
|
//
|
|
gWrapperHandle = hWrapper;
|
|
}
|
|
#if DBG
|
|
else
|
|
{
|
|
DbgPrint("NdisMRegisterMiniport failed! Status: 0x%x\n", Status);
|
|
}
|
|
#endif
|
|
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
aic5900ReadConfigurationInformation(
|
|
IN NDIS_HANDLE ConfigurationHandle,
|
|
IN PAIC5900_REGISTRY_PARAMETER pRegistryParameter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
NDIS_HANDLE ConfigHandle;
|
|
PNDIS_CONFIGURATION_PARAMETER pConfigParameter;
|
|
UINT c;
|
|
|
|
//
|
|
// Open the configuration section of the registry for this adapter.
|
|
//
|
|
NdisOpenConfiguration(&Status, &ConfigHandle, ConfigurationHandle);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Unable to open the Aic5900's Parameters registry key\n"));
|
|
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Read in the registry parameters.
|
|
//
|
|
for (c = 0; c < Aic5900MaxRegistryEntry; c++)
|
|
{
|
|
NdisReadConfiguration(
|
|
&Status,
|
|
&pConfigParameter,
|
|
ConfigHandle,
|
|
&gaRegistryParameterString[c],
|
|
NdisParameterHexInteger);
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
pRegistryParameter[c].fPresent = TRUE;
|
|
pRegistryParameter[c].Value = pConfigParameter->ParameterData.IntegerData;
|
|
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
|
|
("Read registry parameter: %u = 0x%x\n", c, pRegistryParameter[c].Value));
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Close the configuration handle.
|
|
//
|
|
NdisCloseConfiguration(ConfigHandle);
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
aic5900ReadPciConfiguration(
|
|
IN PADAPTER_BLOCK pAdapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
PPCI_COMMON_CONFIG PciCommonConfig;
|
|
PHARDWARE_INFO pHwInfo = pAdapter->HardwareInfo;
|
|
PNDIS_RESOURCE_LIST ResourceList;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource;
|
|
NDIS_STATUS Status;
|
|
UINT c;
|
|
UINT Temp;
|
|
|
|
//
|
|
// Allocate memory for the pci common config space.
|
|
//
|
|
ALLOCATE_MEMORY(
|
|
&Status,
|
|
&pHwInfo->PciCommonConfig,
|
|
PCI_COMMON_HDR_LENGTH);
|
|
if (NULL == pHwInfo->PciCommonConfig)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("aic5900ReadPciConfiguration() failed to allocate memory for PCI Common Config.\n"));
|
|
|
|
return(NDIS_STATUS_RESOURCES);
|
|
}
|
|
|
|
PciCommonConfig = pHwInfo->PciCommonConfig;
|
|
|
|
//
|
|
// Read the board id. This is a combination of the vendor id and
|
|
// the device id.
|
|
//
|
|
Temp = NdisReadPciSlotInformation(
|
|
pAdapter->MiniportAdapterHandle,
|
|
pHwInfo->SlotNumber,
|
|
0,
|
|
PciCommonConfig,
|
|
PCI_COMMON_HDR_LENGTH);
|
|
if (Temp != PCI_COMMON_HDR_LENGTH)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Unable to read PCI configuration header\n"));
|
|
|
|
return(NDIS_STATUS_FAILURE);
|
|
}
|
|
|
|
//
|
|
// Verify vendor & device id's.
|
|
//
|
|
if ((ADAPTEC_PCI_VENDOR_ID != PciCommonConfig->VendorID) ||
|
|
(AIC5900_PCI_DEVICE_ID != PciCommonConfig->DeviceID))
|
|
{
|
|
return(NDIS_STATUS_FAILURE);
|
|
}
|
|
|
|
//
|
|
// Set the command word in pci space.
|
|
//
|
|
PciCommonConfig->Command = PCI_ENABLE_MEMORY_SPACE |
|
|
PCI_ENABLE_BUS_MASTER |
|
|
PCI_ENABLE_WRITE_AND_INVALIDATE |
|
|
PCI_ENABLE_SERR;
|
|
|
|
NdisWritePciSlotInformation(
|
|
pAdapter->MiniportAdapterHandle,
|
|
pHwInfo->SlotNumber,
|
|
FIELD_OFFSET(PCI_COMMON_CONFIG, Command),
|
|
&PciCommonConfig->Command,
|
|
sizeof(PciCommonConfig->Command));
|
|
|
|
NdisReadPciSlotInformation(
|
|
pAdapter->MiniportAdapterHandle,
|
|
pHwInfo->SlotNumber,
|
|
0,
|
|
PciCommonConfig,
|
|
PCI_COMMON_HDR_LENGTH);
|
|
|
|
PciCommonConfig->u.type0.BaseAddresses[0] &= 0xFFFFFFF0;
|
|
|
|
//
|
|
// For noisy debug dump what we find in the PCI space.
|
|
//
|
|
dbgDumpPciCommonConfig(PciCommonConfig);
|
|
|
|
//
|
|
// Assign the pci resources.
|
|
//
|
|
Status = NdisMPciAssignResources(
|
|
pAdapter->MiniportAdapterHandle,
|
|
pHwInfo->SlotNumber,
|
|
&ResourceList);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("NdisMPciAssignResoures() failed: 0x%x\n", Status));
|
|
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Walk the resource list to get the adapters configuration
|
|
// information.
|
|
//
|
|
for (c = 0; c < ResourceList->Count; c++)
|
|
{
|
|
Resource = &ResourceList->PartialDescriptors[c];
|
|
switch (Resource->Type)
|
|
{
|
|
case CmResourceTypeInterrupt:
|
|
//
|
|
// Save the interrupt number with our adapter block.
|
|
//
|
|
pHwInfo->InterruptLevel = Resource->u.Interrupt.Level;
|
|
pHwInfo->InterruptVector = Resource->u.Interrupt.Vector;
|
|
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
|
|
("Configured to use interrupt Level: %u interrupt vector: %u\n", pHwInfo->InterruptLevel, pHwInfo->InterruptVector));
|
|
|
|
break;
|
|
|
|
case CmResourceTypeMemory:
|
|
|
|
//
|
|
// Save the memory mapped base physical address and it's length.
|
|
//
|
|
pHwInfo->PhysicalIoSpace = Resource->u.Memory.Start;
|
|
pHwInfo->IoSpaceLength = Resource->u.Memory.Length;
|
|
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
|
|
("Configured to use mapped memory memory 0x%x:0x%x of length 0x%x\n",
|
|
NdisGetPhysicalAddressHigh(pHwInfo->PhysicalIoSpace),
|
|
NdisGetPhysicalAddressLow(pHwInfo->PhysicalIoSpace),
|
|
pHwInfo->IoSpaceLength));
|
|
|
|
break;
|
|
|
|
case CmResourceTypePort:
|
|
|
|
//
|
|
// Save the port.
|
|
//
|
|
pHwInfo->InitialPort = NdisGetPhysicalAddressLow(Resource->u.Port.Start);
|
|
pHwInfo->NumberOfPorts = Resource->u.Port.Length;
|
|
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
|
|
("Configured to use port memory 0x%x of length 0x%x\n",
|
|
pHwInfo->InitialPort,
|
|
pHwInfo->NumberOfPorts));
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
aic5900GetNicModelNumberFromString(
|
|
IN PHARDWARE_INFO pHwInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
ULONG NicModel;
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
|
|
AIC_ULONG_TO_ULONG(&NicModel, (PULONG)(&pHwInfo->FCodeImage->Model[5]));
|
|
|
|
//
|
|
// Compare the second DWORD in the NicModelString
|
|
//
|
|
switch (NicModel)
|
|
{
|
|
case '5910':
|
|
pHwInfo->NicModelNumber = ANA_5910;
|
|
|
|
//
|
|
// This is a 25Mbps adapter and has a 16MHz cell clock.
|
|
//
|
|
pHwInfo->CellClockRate = CELL_CLOCK_16MHZ;
|
|
|
|
break;
|
|
|
|
case '5930':
|
|
pHwInfo->NicModelNumber = ANA_5930;
|
|
|
|
//
|
|
// This is a 155Mbps adapter and has a 25MHz cell clock.
|
|
//
|
|
pHwInfo->CellClockRate = CELL_CLOCK_25MHZ;
|
|
|
|
break;
|
|
|
|
case '5940':
|
|
pHwInfo->NicModelNumber = ANA_5940;
|
|
|
|
//
|
|
// This is a 155Mbps adapter and has a 25MHz cell clock.
|
|
//
|
|
pHwInfo->CellClockRate = CELL_CLOCK_25MHZ;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Invalid NIC Model String!\n"));
|
|
|
|
pHwInfo->NicModelNumber = ANA_INVALID;
|
|
|
|
Status = NDIS_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
aic5900ReadEepromInformation(
|
|
IN PADAPTER_BLOCK pAdapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will map the EEPROM address into memory and read the offsets for the other
|
|
information that will be needed.
|
|
|
|
Arguments:
|
|
|
|
pAdapter - Pointer to the adapter block to save the information.
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS if everthing went ok.
|
|
NDIS_STATUS_FAILURE otherwise.
|
|
|
|
--*/
|
|
{
|
|
NDIS_PHYSICAL_ADDRESS PhysicalAddress;
|
|
NDIS_STATUS Status;
|
|
PHARDWARE_INFO pHwInfo;
|
|
|
|
PPCI_FCODE_IMAGE pFCode;
|
|
PPCI_FCODE_IMAGE pFCodeImage;
|
|
|
|
PUCHAR EepromBase = NULL;
|
|
UCHAR HighByte;
|
|
UCHAR LowByte;
|
|
|
|
USHORT FCodeImageOffset;
|
|
ULONG FCodeName;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Initialize the hardware info.
|
|
//
|
|
pHwInfo = pAdapter->HardwareInfo;
|
|
|
|
//
|
|
// Map the first part of the EEPROM to read the
|
|
// configuration information.
|
|
//
|
|
PhysicalAddress = pHwInfo->PhysicalIoSpace;
|
|
|
|
Status = NdisMMapIoSpace(
|
|
&EepromBase,
|
|
pAdapter->MiniportAdapterHandle,
|
|
PhysicalAddress,
|
|
FCODE_SIZE);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Failed to map the PCI FCode I/O space into memory\n"));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get the offset to the Fcode image.
|
|
//
|
|
EEPROM_READ_UCHAR(EepromBase + 3, &HighByte);
|
|
EEPROM_READ_UCHAR(EepromBase + 2, &LowByte);
|
|
FCodeImageOffset = (USHORT)((HighByte << 8) + LowByte);
|
|
|
|
if (0xFFFF == FCodeImageOffset)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Invalid data read from the EEPROM.\n"));
|
|
Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
|
|
break;
|
|
}
|
|
|
|
pFCode = (PPCI_FCODE_IMAGE)(EepromBase + FCodeImageOffset);
|
|
|
|
ALLOCATE_MEMORY(&Status, &pHwInfo->FCodeImage, FCODE_SIZE);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Failed to allocate memory for the eeprom image\n"));
|
|
break;
|
|
}
|
|
|
|
EEPROM_READ_BUFFER(pHwInfo->FCodeImage, pFCode, FCODE_SIZE);
|
|
|
|
pFCodeImage = pHwInfo->FCodeImage;
|
|
|
|
//
|
|
// For debug this will get dumped.
|
|
//
|
|
dbgDumpPciFCodeImage(pFCodeImage);
|
|
|
|
//
|
|
// Check the name parameter in the fcode image.
|
|
// We add 1 since this name is in PASCAL format (the first byte
|
|
// is the length of the string)....
|
|
//
|
|
AIC_ULONG_TO_ULONG(&FCodeName, (PULONG)(&pFCodeImage->Name[1]));
|
|
if (FCodeName != FCODE_NAME)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Invalid name in FCode Image\n"));
|
|
|
|
Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get the model number for the NIC.
|
|
//
|
|
Status = aic5900GetNicModelNumberFromString(pHwInfo);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get the ROM version number.
|
|
//
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->RomVersionNumber, &pFCodeImage->RomVersionNumber);
|
|
|
|
//
|
|
// Get EPROM offset and size and map in.
|
|
//
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->rEpromOffset, &pFCodeImage->roEpromOffset);
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->rEpromSize, &pFCodeImage->roEpromSize);
|
|
|
|
NdisSetPhysicalAddressLow(
|
|
PhysicalAddress,
|
|
NdisGetPhysicalAddressLow(pHwInfo->PhysicalIoSpace) +
|
|
pHwInfo->rEpromOffset);
|
|
|
|
Status = NdisMMapIoSpace(
|
|
&pHwInfo->rEprom,
|
|
pAdapter->MiniportAdapterHandle,
|
|
PhysicalAddress,
|
|
pHwInfo->rEpromSize);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get R/W EPROM offset and size and map in.
|
|
//
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->rwEpromOffset, &pFCodeImage->rwEpromOffset);
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->rwEpromSize, &pFCodeImage->rwEpromSize);
|
|
|
|
NdisSetPhysicalAddressLow(
|
|
PhysicalAddress,
|
|
NdisGetPhysicalAddressLow(pHwInfo->PhysicalIoSpace) +
|
|
pHwInfo->rwEpromOffset);
|
|
|
|
Status = NdisMMapIoSpace(
|
|
&pHwInfo->rwEprom,
|
|
pAdapter->MiniportAdapterHandle,
|
|
PhysicalAddress,
|
|
pHwInfo->rwEpromSize);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get PHY offset and size and map in.
|
|
//
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->PhyOffset, &pFCodeImage->PhyOffset);
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->PhySize, &pFCodeImage->PhySize);
|
|
|
|
NdisSetPhysicalAddressLow(
|
|
PhysicalAddress,
|
|
NdisGetPhysicalAddressLow(pHwInfo->PhysicalIoSpace) +
|
|
pHwInfo->PhyOffset);
|
|
|
|
Status = NdisMMapIoSpace(
|
|
(PVOID *)&pHwInfo->Phy,
|
|
pAdapter->MiniportAdapterHandle,
|
|
PhysicalAddress,
|
|
pHwInfo->PhySize);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get EXTERNAL offset and size and map in.
|
|
//
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->ExternalOffset, &pFCodeImage->ExternalOffset);
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->ExternalSize, &pFCodeImage->ExternalSize);
|
|
|
|
NdisSetPhysicalAddressLow(
|
|
PhysicalAddress,
|
|
NdisGetPhysicalAddressLow(pHwInfo->PhysicalIoSpace) +
|
|
pHwInfo->ExternalOffset);
|
|
|
|
Status = NdisMMapIoSpace(
|
|
&pHwInfo->External,
|
|
pAdapter->MiniportAdapterHandle,
|
|
PhysicalAddress,
|
|
pHwInfo->ExternalSize);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get SAR offset and size and map in.
|
|
//
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->MidwayOffset, &pFCodeImage->SarOffset);
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->MidwaySize, &pFCodeImage->SarSize);
|
|
|
|
NdisSetPhysicalAddressLow(
|
|
PhysicalAddress,
|
|
NdisGetPhysicalAddressLow(pHwInfo->PhysicalIoSpace) +
|
|
pHwInfo->MidwayOffset);
|
|
|
|
Status = NdisMMapIoSpace(
|
|
(PVOID *)&pHwInfo->Midway,
|
|
pAdapter->MiniportAdapterHandle,
|
|
PhysicalAddress,
|
|
pHwInfo->MidwaySize);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get PCI Config offset and size and map in.
|
|
//
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->PciCfgOffset, &pFCodeImage->PciConfigOffset);
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->PciCfgSize, &pFCodeImage->PciConfigSize);
|
|
|
|
NdisSetPhysicalAddressLow(
|
|
PhysicalAddress,
|
|
NdisGetPhysicalAddressLow(pHwInfo->PhysicalIoSpace) +
|
|
pHwInfo->PciCfgOffset);
|
|
|
|
Status = NdisMMapIoSpace(
|
|
(PVOID *)&pHwInfo->PciConfigSpace,
|
|
pAdapter->MiniportAdapterHandle,
|
|
PhysicalAddress,
|
|
pHwInfo->PciCfgSize);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get SAR RAM offset and size and map in.
|
|
//
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->SarRamOffset, &pFCodeImage->SarMemOffset);
|
|
AIC_ULONG_TO_ULONG(&pHwInfo->SarRamSize, &pFCodeImage->SarMemSize);
|
|
|
|
NdisSetPhysicalAddressLow(
|
|
PhysicalAddress,
|
|
NdisGetPhysicalAddressLow(pHwInfo->PhysicalIoSpace) +
|
|
pHwInfo->SarRamOffset);
|
|
|
|
Status = NdisMMapIoSpace(
|
|
(PVOID *)&pHwInfo->SarRam,
|
|
pAdapter->MiniportAdapterHandle,
|
|
PhysicalAddress,
|
|
pHwInfo->SarRamSize);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Read in the manufacturer address for the nic.
|
|
//
|
|
EEPROM_READ_BUFFER(
|
|
pHwInfo->PermanentAddress,
|
|
(((PUCHAR)pHwInfo->rEprom) + pHwInfo->rEpromSize) - sizeof(EEPROM_MANUFACTURER_INFO),
|
|
ATM_ADDRESS_LENGTH);
|
|
|
|
//
|
|
// Save the permanent address in the station address by default.
|
|
//
|
|
NdisMoveMemory(
|
|
pHwInfo->StationAddress,
|
|
pHwInfo->PermanentAddress,
|
|
ATM_ADDRESS_LENGTH);
|
|
|
|
dbgDumpHardwareInformation(pHwInfo);
|
|
} while (FALSE);
|
|
|
|
if (EepromBase != NULL)
|
|
{
|
|
NdisMUnmapIoSpace(
|
|
pAdapter->MiniportAdapterHandle,
|
|
(PVOID)EepromBase,
|
|
FCODE_SIZE);
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
VOID
|
|
aic5900FreeResources(
|
|
IN PADAPTER_BLOCK pAdapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
PHARDWARE_INFO pHwInfo;
|
|
PVC_BLOCK pVc;
|
|
PLIST_ENTRY Link;
|
|
|
|
if (NULL != pAdapter)
|
|
{
|
|
if (NULL != pAdapter->HardwareInfo)
|
|
{
|
|
pHwInfo = pAdapter->HardwareInfo;
|
|
|
|
if (NULL != pHwInfo->PciCommonConfig)
|
|
{
|
|
FREE_MEMORY(pHwInfo->PciCommonConfig, PCI_COMMON_HDR_LENGTH);
|
|
}
|
|
|
|
if (NULL != pHwInfo->PortOffset)
|
|
{
|
|
NdisMDeregisterIoPortRange(
|
|
pAdapter->MiniportAdapterHandle,
|
|
pHwInfo->InitialPort,
|
|
pHwInfo->NumberOfPorts,
|
|
pHwInfo->PortOffset);
|
|
}
|
|
|
|
if (NULL != pHwInfo->rEprom)
|
|
{
|
|
NdisMUnmapIoSpace(
|
|
pAdapter->MiniportAdapterHandle,
|
|
pHwInfo->rEprom,
|
|
pHwInfo->rEpromSize);
|
|
}
|
|
|
|
if (NULL != pHwInfo->rwEprom)
|
|
{
|
|
NdisMUnmapIoSpace(
|
|
pAdapter->MiniportAdapterHandle,
|
|
pHwInfo->rwEprom,
|
|
pHwInfo->rwEpromSize);
|
|
}
|
|
|
|
if (NULL != pHwInfo->Phy)
|
|
{
|
|
NdisMUnmapIoSpace(
|
|
pAdapter->MiniportAdapterHandle,
|
|
pHwInfo->Phy,
|
|
pHwInfo->PhySize);
|
|
}
|
|
|
|
if (NULL != pHwInfo->External)
|
|
{
|
|
NdisMUnmapIoSpace(
|
|
pAdapter->MiniportAdapterHandle,
|
|
pHwInfo->External,
|
|
pHwInfo->ExternalSize);
|
|
}
|
|
|
|
if (NULL != pHwInfo->Midway)
|
|
{
|
|
NdisMUnmapIoSpace(
|
|
pAdapter->MiniportAdapterHandle,
|
|
pHwInfo->Midway,
|
|
pHwInfo->MidwaySize);
|
|
}
|
|
|
|
if (NULL != pHwInfo->PciConfigSpace)
|
|
{
|
|
NdisMUnmapIoSpace(
|
|
pAdapter->MiniportAdapterHandle,
|
|
pHwInfo->PciConfigSpace,
|
|
pHwInfo->PciCfgSize);
|
|
}
|
|
|
|
if (NULL != pHwInfo->SarRam)
|
|
{
|
|
NdisMUnmapIoSpace(
|
|
pAdapter->MiniportAdapterHandle,
|
|
(PVOID)pHwInfo->SarRam,
|
|
pHwInfo->SarRamSize);
|
|
}
|
|
|
|
if (NULL != pHwInfo->FCodeImage)
|
|
{
|
|
FREE_MEMORY(pHwInfo->FCodeImage, FCODE_SIZE);
|
|
}
|
|
|
|
if (HW_TEST_FLAG(pHwInfo, fHARDWARE_INFO_INTERRUPT_REGISTERED))
|
|
{
|
|
NdisMDeregisterInterrupt(&pHwInfo->Interrupt);
|
|
}
|
|
|
|
//
|
|
// Free the spin lock for the hardware information.
|
|
//
|
|
NdisFreeSpinLock(&pHwInfo->Lock);
|
|
|
|
//
|
|
// Free the memory used for the hardware information.
|
|
//
|
|
FREE_MEMORY(pHwInfo, sizeof(HARDWARE_INFO));
|
|
}
|
|
|
|
///
|
|
// Clean up our list of active VCs.
|
|
///
|
|
while (!IsListEmpty(&pAdapter->ActiveVcList))
|
|
{
|
|
//
|
|
// Remove the VC from the list, deactivate it and delete it.
|
|
//
|
|
Link = RemoveHeadList(&pAdapter->ActiveVcList);
|
|
pVc = CONTAINING_RECORD(Link, VC_BLOCK, Link);
|
|
Aic5900DeactivateVc((NDIS_HANDLE)pVc);
|
|
Aic5900DeleteVc((NDIS_HANDLE)pVc);
|
|
}
|
|
|
|
//
|
|
// Walk our list of inactive VCs.
|
|
//
|
|
while (!IsListEmpty(&pAdapter->InactiveVcList))
|
|
{
|
|
//
|
|
// Remove the VC from the list and delete it.
|
|
//
|
|
Link = RemoveHeadList(&pAdapter->InactiveVcList);
|
|
pVc = CONTAINING_RECORD(Link, VC_BLOCK, Link);
|
|
Aic5900DeleteVc((NDIS_HANDLE)pVc);
|
|
}
|
|
|
|
//
|
|
// Free up the spin lock for the adapter block.
|
|
//
|
|
NdisFreeSpinLock(&pAdapter->Lock);
|
|
|
|
//
|
|
// Free the memory allocated for the adapter block.
|
|
//
|
|
FREE_MEMORY(pAdapter, sizeof(ADAPTER_BLOCK));
|
|
}
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
aic5900InitPciRegisters(
|
|
IN PADAPTER_BLOCK pAdapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
PHARDWARE_INFO pHwInfo = pAdapter->HardwareInfo;
|
|
PCI_DEVICE_CONFIG regConfig;
|
|
PCI_DEVICE_ENABLE_PCI_INTERRUPT regEnableInt;
|
|
PCI_DEVICE_DMA_CONTROL regDmaControl;
|
|
|
|
//
|
|
// Reset the ORION
|
|
//
|
|
GET_PCI_DEV_CFG(pHwInfo, ®Config);
|
|
regConfig.SoftwareReset = 1;
|
|
SET_PCI_DEV_CFG(pHwInfo, regConfig.reg);
|
|
|
|
//
|
|
// Program the interrupt enable register.
|
|
//
|
|
GET_PCI_DEV_ENABLE_INT(pHwInfo, ®EnableInt);
|
|
regEnableInt.EnableDpeInt = 0;
|
|
regEnableInt.EnableSseInt = 1;
|
|
regEnableInt.EnableStaInt = 1;
|
|
regEnableInt.EnableRmaInt = 1;
|
|
regEnableInt.EnableRtaInt = 1;
|
|
regEnableInt.EnableDprInt = 1;
|
|
SET_PCI_DEV_ENABLE_INT(pHwInfo, regEnableInt.reg);
|
|
|
|
//
|
|
// Program the PCI device config register.
|
|
//
|
|
GET_PCI_DEV_CFG(pHwInfo, ®Config);
|
|
regConfig.MasterSwapBytes = 1;
|
|
regConfig.EnableInterrupt = 1;
|
|
SET_PCI_DEV_CFG(pHwInfo, regConfig.reg);
|
|
|
|
//
|
|
// Program the DMA control register.
|
|
//
|
|
GET_PCI_DEV_DMA_CONTROL(pHwInfo, ®DmaControl);
|
|
regDmaControl.CacheThresholdEnable = 1;
|
|
SET_PCI_DEV_DMA_CONTROL(pHwInfo, regDmaControl.reg);
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
aic5900InitPhyRegisters(
|
|
IN PADAPTER_BLOCK pAdapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
PHARDWARE_INFO pHwInfo = pAdapter->HardwareInfo;
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
|
|
switch (pAdapter->HardwareInfo->NicModelNumber)
|
|
{
|
|
case ANA_5910:
|
|
|
|
//
|
|
// Reset the IBM TC and PDM chips. The host can reset TC
|
|
// and PDM chips by first writing a word to the Software Reset
|
|
// register and then reading it back.
|
|
//
|
|
// Reset clears the STATUS register and flushes the TC receive
|
|
// FIFO.
|
|
//
|
|
SET_IBM_TC_SOFTWARE_RESET(pHwInfo, 0);
|
|
|
|
//
|
|
// Enable TC overrun and cell error interrupts.
|
|
//
|
|
SET_IBM_TC_MASK(pHwInfo, 0x04);
|
|
|
|
break;
|
|
|
|
case ANA_5940:
|
|
case ANA_5930:
|
|
|
|
//
|
|
// Set and clear the reset bit for the phy.
|
|
//
|
|
SET_SUNI_MASTER_RESET_IDEN(pHwInfo, fSUNI_MRI_RESET);
|
|
SET_SUNI_MASTER_RESET_IDEN(pHwInfo, 0);
|
|
|
|
//
|
|
// Clear the SUNI test mode.
|
|
//
|
|
SET_SUNI_MASTER_TEST(pHwInfo, 0);
|
|
|
|
//
|
|
// Enable SUNI RACP interrupts.
|
|
//
|
|
SET_SUNI_RACP_INT_ENABLE_STATUS(pHwInfo, (fSUNI_RACP_IES_FIFOE | fSUNI_RACP_IES_HCSE));
|
|
|
|
break;
|
|
|
|
default:
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
|
|
("aic5900InitPhyRegisters: Unknown adapter model 0x%x\n", pAdapter->HardwareInfo->NicModelNumber));
|
|
|
|
Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
|
|
|
|
break;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
aic5900InitSarRegisters(
|
|
IN PADAPTER_BLOCK pAdapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
PSAR_INFO pSar;
|
|
PHARDWARE_INFO pHwInfo = pAdapter->HardwareInfo;
|
|
PXMIT_SEG_CHANNEL pCurrent;
|
|
ULONG RamOffset;
|
|
UINT c;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Allocate memory for the sar.
|
|
//
|
|
ALLOCATE_MEMORY(&Status, &pSar, sizeof(SAR_INFO));
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
break;
|
|
}
|
|
|
|
ZERO_MEMORY(pSar, sizeof(SAR_INFO));
|
|
|
|
NdisAllocateSpinLock(&pSar->lockFreeXmitSegment);
|
|
|
|
//
|
|
// Initialize the VCI table, DMA receive and transmit queues,
|
|
// the service list, and everything else in the SAR ram.
|
|
//
|
|
for (c = 0; c < pHwInfo->SarRamSize / 4; c++)
|
|
{
|
|
NdisWriteRegisterUlong(pHwInfo->SarRam + c, 0);
|
|
}
|
|
|
|
//
|
|
// Initialize the memory manager for our sar ram....
|
|
//
|
|
Status = Aic5900InitializeRamInfo(&pHwInfo->hRamInfo, pHwInfo->SarRamSize);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Unable to initialize the memory manager for the adapter memory\n"));
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for the VCI table.
|
|
// NOTE:
|
|
// We don't need to save the ram offset since this is always
|
|
// at offset 0.
|
|
//
|
|
Status = Aic5900AllocateRam(
|
|
&RamOffset,
|
|
pHwInfo->hRamInfo,
|
|
sizeof(MIDWAY_VCI_TABLE_ENTRY) * MAX_VCS);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_ERR,
|
|
("Unable to allocate the VCI table in adapter ram\n"));
|
|
|
|
break;
|
|
}
|
|
|
|
ASSERT(MIDWAY_VCI_TABLE_OFFSET == RamOffset);
|
|
|
|
//
|
|
// Allocate memory for the receive DMA queue.
|
|
// NOTE:
|
|
// We don't need to save the RAM offset since this is always at
|
|
// offset 0x4000.
|
|
//
|
|
Status = Aic5900AllocateRam(
|
|
&RamOffset,
|
|
pHwInfo->hRamInfo,
|
|
sizeof(MIDWAY_DMA_DESC) * MIDWAY_DMA_QUEUE_SIZE);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Unable to allocate the receive queue from the adapter ram\n"));
|
|
|
|
break;
|
|
}
|
|
|
|
ASSERT(MIDWAY_RECEIVE_DMA_QUEUE_OFFSET == RamOffset);
|
|
|
|
//
|
|
// Allocate memory for the transmit DMA queue.
|
|
// NOTE:
|
|
// We don't need to save the RAM offset since this is always at
|
|
// offset 0x5000.
|
|
//
|
|
Status = Aic5900AllocateRam(
|
|
&RamOffset,
|
|
pHwInfo->hRamInfo,
|
|
sizeof(MIDWAY_DMA_DESC) * MIDWAY_DMA_QUEUE_SIZE);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Unable to allocate the transmit queue from the adapter ram\n"));
|
|
|
|
break;
|
|
}
|
|
|
|
ASSERT(MIDWAY_TRANSMIT_DMA_QUEUE_OFFSET == RamOffset);
|
|
|
|
//
|
|
// Allocate memory for the service queue.
|
|
// NOTE:
|
|
// We don't need to save the RAM offset since this is always at
|
|
// offset 0x6000.
|
|
//
|
|
Status = Aic5900AllocateRam(
|
|
&RamOffset,
|
|
pHwInfo->hRamInfo,
|
|
sizeof(MIDWAY_SERVICE_LIST) * MIDWAY_SERVICE_QUEUE_SIZE);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Unable to allocate the service queue\n"));
|
|
|
|
break;
|
|
}
|
|
|
|
ASSERT(MIDWAY_SERVICE_QUEUE_OFFSET == RamOffset);
|
|
|
|
//
|
|
// Get a block of nic ram for the transmit channel.
|
|
//
|
|
Status = Aic5900AllocateRam(&RamOffset, pHwInfo->hRamInfo, BLOCK_16K);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Unable to allocate adapter memory for the UBR channel\n"));
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Setup the UBR (best effort) channel.
|
|
//
|
|
pCurrent = &pSar->XmitSegChannel[0];
|
|
pSar->ubrXmitChannel = pCurrent;
|
|
|
|
NdisZeroMemory(pCurrent, sizeof(XMIT_SEG_CHANNEL));
|
|
|
|
NdisAllocateSpinLock(&pCurrent->lock);
|
|
pCurrent->Adapter = pAdapter;
|
|
pCurrent->MidwayChannelNumber = MIDWAY_XMIT_SEG_CHANNEL_UBR;
|
|
|
|
pCurrent->MidwayInitRegs.XmitPlace.Size =
|
|
CONVERT_BYTE_SIZE_TO_MIDWAY_SIZE(BLOCK_16K / 4);
|
|
pCurrent->MidwayInitRegs.XmitPlace.Location =
|
|
CONVERT_BYTE_OFFSET_TO_MIDWAY_LOCATION(RamOffset);
|
|
pCurrent->MidwayInitRegs.XmitReadPointer.Register = 0;
|
|
pCurrent->MidwayInitRegs.XmitDescriptorStart.Register = 0;
|
|
|
|
pCurrent->MidwayTransmitRegs =
|
|
&pHwInfo->Midway->TransmitRegisters[MIDWAY_XMIT_SEG_CHANNEL_UBR];
|
|
|
|
pCurrent->SegmentSize = BLOCK_SIZE_16k / 4;
|
|
pCurrent->Segment = (HWUL *)&pHwInfo->SarRam[RamOffset / 4];
|
|
pCurrent->SegmentReadPointer = 0;
|
|
pCurrent->SegmentWritePointer = 0;
|
|
pCurrent->SegmentRoom = BLOCK_SIZE_16k / 4;
|
|
pCurrent->XmitPduBytes = 0;
|
|
|
|
InitializeListHead(&pCurrent->SegmentWaitQ);
|
|
InitializeListHead(&pCurrent->TransmitWaitQ);
|
|
|
|
for (c = 1, pCurrent = &pSar->XmitSegChannel[c];
|
|
c < MIDWAY_MAX_SEGMENT_CHANNELS;
|
|
c++, pCurrent++)
|
|
{
|
|
NdisZeroMemory(pCurrent, sizeof(XMIT_SEG_CHANNEL));
|
|
NdisAllocateSpinLock(&pCurrent->lock);
|
|
|
|
pCurrent->Adapter = pAdapter;
|
|
pCurrent->MidwayChannelNumber = c;
|
|
|
|
//
|
|
// Place the segment channel on the free queue.
|
|
//
|
|
pCurrent->Next = pSar->FreeXmitSegChannel;
|
|
pSar->FreeXmitSegChannel = pCurrent;
|
|
|
|
//
|
|
// Get a pointer to the midway transmit registers.
|
|
//
|
|
pCurrent->MidwayTransmitRegs =
|
|
&pHwInfo->Midway->TransmitRegisters[c];
|
|
|
|
//
|
|
// Initialize the queues.
|
|
//
|
|
InitializeListHead(&pCurrent->SegmentWaitQ);
|
|
InitializeListHead(&pCurrent->TransmitWaitQ);
|
|
}
|
|
|
|
//
|
|
// Initialize the Midway Master Control register.
|
|
//
|
|
pSar->MidwayMasterControl = (MID_REG_MC_S_DMA_ENABLE |
|
|
MID_REG_MC_S_XMT_ENABLE |
|
|
MID_REG_MC_S_RCV_ENABLE |
|
|
MID_REG_MC_S_XMT_LOCK_MODE);
|
|
pHwInfo->Midway->MCS = pSar->MidwayMasterControl;
|
|
|
|
//
|
|
// Initialize the UBR transmit channel.
|
|
//
|
|
pHwInfo->Midway->TransmitRegisters[MIDWAY_XMIT_SEG_CHANNEL_UBR].XmitPlace.Register =
|
|
pSar->ubrXmitChannel->MidwayInitRegs.XmitPlace.Register;
|
|
|
|
pHwInfo->Midway->TransmitRegisters[MIDWAY_XMIT_SEG_CHANNEL_UBR].XmitReadPointer.Register =
|
|
pSar->ubrXmitChannel->MidwayInitRegs.XmitReadPointer.Register;
|
|
|
|
pHwInfo->Midway->TransmitRegisters[MIDWAY_XMIT_SEG_CHANNEL_UBR].XmitDescriptorStart.Register =
|
|
pSar->ubrXmitChannel->MidwayInitRegs.XmitDescriptorStart.Register;
|
|
|
|
pHwInfo->InterruptMask = MID_REG_INT_PCI |
|
|
MID_REG_INT_XMT_COMPLETE_7 |
|
|
MID_REG_INT_XMT_COMPLETE_6 |
|
|
MID_REG_INT_XMT_COMPLETE_5 |
|
|
MID_REG_INT_XMT_COMPLETE_4 |
|
|
MID_REG_INT_XMT_COMPLETE_3 |
|
|
MID_REG_INT_XMT_COMPLETE_2 |
|
|
MID_REG_INT_XMT_COMPLETE_1 |
|
|
MID_REG_INT_XMT_COMPLETE_0 |
|
|
MID_REG_INT_XMT_DMA_OVFL |
|
|
MID_REG_INT_XMT_IDEN_MISMTCH |
|
|
MID_REG_INT_DMA_ERR_ACK |
|
|
MID_REG_INT_RCV_DMA_COMPLETE |
|
|
MID_REG_INT_XMT_DMA_COMPLETE |
|
|
MID_REG_INT_SERVICE |
|
|
MID_REG_INT_SUNI_INT;
|
|
|
|
pHwInfo->Midway->IE = pHwInfo->InterruptMask;
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
} while (FALSE);
|
|
|
|
//
|
|
// If we failed somewhere above then we need to cleanup....
|
|
//
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
if (NULL != pHwInfo->hRamInfo)
|
|
{
|
|
Aic5900UnloadRamInfo(pHwInfo->hRamInfo);
|
|
}
|
|
|
|
if (NULL != pSar)
|
|
{
|
|
NdisFreeSpinLock(&pSar->lockFreeXmitSegment);
|
|
FREE_MEMORY(pSar, sizeof(SAR_INFO));
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
Aic5900Initialize(
|
|
OUT PNDIS_STATUS OpenErrorStatus,
|
|
OUT PUINT SelectedMediumIndex,
|
|
IN PNDIS_MEDIUM MediumArray,
|
|
IN UINT MediumArraySize,
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN NDIS_HANDLE ConfigurationHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
UINT c;
|
|
PADAPTER_BLOCK pAdapter;
|
|
PHARDWARE_INFO pHwInfo;
|
|
NDIS_STATUS Status;
|
|
PAIC5900_REGISTRY_PARAMETER pRegistryParameter;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Initialize for clean-up.
|
|
//
|
|
pAdapter = NULL;
|
|
|
|
//
|
|
// Do we support any of the given media types?
|
|
//
|
|
for (c = 0; c < MediumArraySize; c++)
|
|
{
|
|
if (MediumArray[c] == NdisMediumAtm)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we went through the whole media list without finding
|
|
// a supported media type let the wrapper know.
|
|
//
|
|
if (c == MediumArraySize)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Media not supported by version of ndis\n"));
|
|
|
|
Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
|
|
|
|
break;
|
|
}
|
|
|
|
*SelectedMediumIndex = c;
|
|
|
|
//
|
|
// Allocate memory for the registry parameters.
|
|
//
|
|
ALLOCATE_MEMORY(
|
|
&Status,
|
|
&pRegistryParameter,
|
|
sizeof(AIC5900_REGISTRY_PARAMETER) * Aic5900MaxRegistryEntry);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_COMP_ERR,
|
|
("Unable to allocate memroy for the registry parameters\n"));
|
|
|
|
break;
|
|
}
|
|
|
|
ZERO_MEMORY(
|
|
pRegistryParameter,
|
|
sizeof(AIC5900_REGISTRY_PARAMETER) * Aic5900MaxRegistryEntry);
|
|
|
|
//
|
|
// Fill in some default registry values.
|
|
//
|
|
pRegistryParameter[Aic5900VcHashTableSize].Value = 13;
|
|
|
|
//
|
|
// Read our parameters out of the registry.
|
|
//
|
|
Status = aic5900ReadConfigurationInformation(
|
|
pRegistryParameter,
|
|
ConfigurationHandle);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Failed to read the configuration information from the registry\n"));
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for our adapter block and initialize it.
|
|
//
|
|
ALLOCATE_MEMORY(
|
|
&Status,
|
|
&pAdapter,
|
|
sizeof(ADAPTER_BLOCK) +
|
|
(pRegistryParameter[Aic5900VcHashTableSize].Value * sizeof(ULONG)));
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Failed to allocate memory for the adapter block\n"));
|
|
break;
|
|
}
|
|
|
|
ZERO_MEMORY(pAdapter, sizeof(ADAPTER_BLOCK));
|
|
|
|
pAdapter->MiniportAdapterHandle = MiniportAdapterHandle;
|
|
|
|
NdisAllocateSpinLock(&pAdapter->Lock);
|
|
|
|
//
|
|
// Spin lock and other odd allocations/initializations.
|
|
//
|
|
InitializeListHead(&pAdapter->ActiveVcList);
|
|
InitializeListHead(&pAdapter->InactiveVcList);
|
|
|
|
//
|
|
// Allocate memory for the hardware information.
|
|
//
|
|
ALLOCATE_MEMORY(&Status, &pAdapter->HardwareInfo, sizeof(HARDWARE_INFO));
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Failed to allocate memory for the hardware information\n"));
|
|
|
|
break;
|
|
}
|
|
|
|
ZERO_MEMORY(pAdapter->HardwareInfo, sizeof(HARDWARE_INFO));
|
|
|
|
pHwInfo = pAdapter->HardwareInfo;
|
|
|
|
NdisAllocateSpinLock(&pHwInfo->Lock);
|
|
|
|
//
|
|
// Get the registry parameters.
|
|
//
|
|
ASSERT(pRegistryParameter[Aic5900BusNumber].fPresent);
|
|
pHwInfo->BusNumber = pRegistryParameter[Aic5900BusNumber].Value;
|
|
|
|
ASSERT(pRegistryParameter[Aic5900SlotNumber].fPresent);
|
|
pHwInfo->SlotNumber = pRegistryParameter[Aic5900SlotNumber].Value;
|
|
|
|
//
|
|
// Set the atributes for the adapter.
|
|
//
|
|
NdisMSetAttributes(
|
|
MiniportAdapterHandle,
|
|
(NDIS_HANDLE)pAdapter,
|
|
TRUE,
|
|
NdisInterfacePci);
|
|
|
|
//
|
|
// Assign the PCI resources.
|
|
//
|
|
Status = aic5900ReadPciConfiguration(pAdapter);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Failed to read the PCI configuration information\n"));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Register the Port addresses.
|
|
//
|
|
Status = NdisMRegisterIoPortRange(
|
|
&pHwInfo->PortOffset,
|
|
pAdapter->MiniportAdapterHandle,
|
|
pHwInfo->InitialPort,
|
|
pHwInfo->NumberOfPorts);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Failed to register the I/O port range\n"));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get the EEPROM parameters
|
|
//
|
|
Status = aic5900ReadEepromInformation(pAdapter);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Failed to read the EEPROM information from the adapter\n"));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Register the interrupt.
|
|
//
|
|
Status = NdisMRegisterInterrupt(
|
|
&pHwInfo->Interrupt,
|
|
pAdapter->MiniportAdapterHandle,
|
|
pHwInfo->InterruptVector,
|
|
pHwInfo->InterruptLevel,
|
|
TRUE,
|
|
TRUE,
|
|
NdisInterruptLevelSensitive);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Failed to register the interrupt with ndis\n"));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Initialize the PCI device/configuration registers.
|
|
//
|
|
Status = aic5900InitPciRegisters(pAdapter);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Failed to initialize the PCI Device/Configuration registers\n"));
|
|
|
|
break;
|
|
}
|
|
|
|
Status = aic5900InitPhyRegisters(pAdapter);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Failed to initialize the PHY registers\n"));
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Initialize the SAR
|
|
//
|
|
Status = aic5900InitSarRegisters(pAdapter);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
|
|
("Failed to initialize the SAR registers\n"));
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Return success.
|
|
//
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
} while (FALSE);
|
|
|
|
//
|
|
// Should we clean up?
|
|
//
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
aic5900FreeResources(pAdapter);
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|