diff options
Diffstat (limited to 'private/ntos/ndis/aic5900/init.c')
-rw-r--r-- | private/ntos/ndis/aic5900/init.c | 1534 |
1 files changed, 1534 insertions, 0 deletions
diff --git a/private/ntos/ndis/aic5900/init.c b/private/ntos/ndis/aic5900/init.c new file mode 100644 index 000000000..5c497d026 --- /dev/null +++ b/private/ntos/ndis/aic5900/init.c @@ -0,0 +1,1534 @@ +/*++ + +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); +} + |