X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=EdkModulePkg%2FBus%2FPci%2FUndi%2FRuntimeDxe%2FE100b.c;fp=EdkModulePkg%2FBus%2FPci%2FUndi%2FRuntimeDxe%2FE100b.c;h=0000000000000000000000000000000000000000;hp=d425778e06f3ca684230db47e094188f19a11497;hb=808def96aa4589fba9c2d0ea55837754a3b7a4f7;hpb=9216450d1143056a50a5f916984a2d7faf590488 diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.c b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.c deleted file mode 100644 index d425778e06..0000000000 --- a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.c +++ /dev/null @@ -1,3756 +0,0 @@ -/*++ - -Copyright (c) 2006, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -Module Name: - - - E100B.C - -Abstract: - - -Revision History - ---*/ - -#include "Undi32.h" - -static UINT8 basic_config_cmd[22] = { - 22, 0x08, - 0, 0, - 0, (UINT8)0x80, - 0x32, 0x03, - 1, 0, - 0x2E, 0, - 0x60, 0, - (UINT8)0xf2, 0x48, - 0, 0x40, - (UINT8)0xf2, (UINT8)0x80, // 0x40=Force full-duplex - 0x3f, 0x05, -}; - -// -// How to wait for the command unit to accept a command. -// Typically this takes 0 ticks. -// -#define wait_for_cmd_done(cmd_ioaddr) \ -{ \ - INT16 wait_count = 2000; \ - while ((InByte (AdapterInfo, cmd_ioaddr) != 0) && --wait_count >= 0) \ - DelayIt (AdapterInfo, 10); \ - if (wait_count == 0) \ - DelayIt (AdapterInfo, 50); \ -} - -UINT8 -InByte ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN UINT32 Port - ) -/*++ - -Routine Description: - This function calls the MemIo callback to read a byte from the device's - address space - Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine) - which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have - to make undi3.0 a special case - -Arguments: - Port - Which port to read from. - -Returns: - Results - The data read from the port. - ---*/ -// TODO: AdapterInfo - add argument and description to function comment -{ - UINT8 Results; - - (*AdapterInfo->Mem_Io) ( - AdapterInfo->Unique_ID, - PXE_MEM_READ, - 1, - (UINT64)Port, - (UINT64) (UINTN) &Results - ); - return Results; -} - -UINT16 -InWord ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN UINT32 Port - ) -/*++ - -Routine Description: - This function calls the MemIo callback to read a word from the device's - address space - Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine) - which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have - to make undi3.0 a special case - -Arguments: - Port - Which port to read from. - -Returns: - Results - The data read from the port. - ---*/ -// TODO: AdapterInfo - add argument and description to function comment -{ - UINT16 Results; - - (*AdapterInfo->Mem_Io) ( - AdapterInfo->Unique_ID, - PXE_MEM_READ, - 2, - (UINT64)Port, - (UINT64)(UINTN)&Results - ); - return Results; -} - -UINT32 -InLong ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN UINT32 Port - ) -/*++ - -Routine Description: - This function calls the MemIo callback to read a dword from the device's - address space - Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine) - which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have - to make undi3.0 a special case - -Arguments: - Port - Which port to read from. - -Returns: - Results - The data read from the port. - ---*/ -// TODO: AdapterInfo - add argument and description to function comment -{ - UINT32 Results; - - (*AdapterInfo->Mem_Io) ( - AdapterInfo->Unique_ID, - PXE_MEM_READ, - 4, - (UINT64)Port, - (UINT64)(UINTN)&Results - ); - return Results; -} - -VOID -OutByte ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN UINT8 Data, - IN UINT32 Port - ) -/*++ - -Routine Description: - This function calls the MemIo callback to write a byte from the device's - address space - Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine) - which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have - to make undi3.0 a special case - -Arguments: - Data - Data to write to Port. - Port - Which port to write to. - -Returns: - none - ---*/ -// TODO: AdapterInfo - add argument and description to function comment -{ - UINT8 Val; - - Val = Data; - (*AdapterInfo->Mem_Io) ( - AdapterInfo->Unique_ID, - PXE_MEM_WRITE, - 1, - (UINT64)Port, - (UINT64)(UINTN)(UINTN)&Val - ); - return ; -} - -VOID -OutWord ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN UINT16 Data, - IN UINT32 Port - ) -/*++ - -Routine Description: - This function calls the MemIo callback to write a word from the device's - address space - Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine) - which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have - to make undi3.0 a special case - -Arguments: - Data - Data to write to Port. - Port - Which port to write to. - -Returns: - none - ---*/ -// TODO: AdapterInfo - add argument and description to function comment -{ - UINT16 Val; - - Val = Data; - (*AdapterInfo->Mem_Io) ( - AdapterInfo->Unique_ID, - PXE_MEM_WRITE, - 2, - (UINT64)Port, - (UINT64)(UINTN)&Val - ); - return ; -} - -VOID -OutLong ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN UINT32 Data, - IN UINT32 Port - ) -/*++ - -Routine Description: - This function calls the MemIo callback to write a dword from the device's - address space - Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine) - which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have - to make undi3.0 a special case - -Arguments: - Data - Data to write to Port. - Port - Which port to write to. - -Returns: - none - ---*/ -// TODO: AdapterInfo - add argument and description to function comment -{ - UINT32 Val; - - Val = Data; - (*AdapterInfo->Mem_Io) ( - AdapterInfo->Unique_ID, - PXE_MEM_WRITE, - 4, - (UINT64)Port, - (UINT64)(UINTN)&Val - ); - return ; -} - -STATIC -UINTN -MapIt ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN UINT64 MemAddr, - IN UINT32 Size, - IN UINT32 Direction, - OUT UINT64 MappedAddr - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - MemAddr - TODO: add argument description - Size - TODO: add argument description - Direction - TODO: add argument description - MappedAddr - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - UINT64 *PhyAddr; - - PhyAddr = (UINT64 *) (UINTN) MappedAddr; - // - // mapping is different for theold and new NII protocols - // - if (AdapterInfo->VersionFlag == 0x30) { - if (AdapterInfo->Virt2Phys_30 == (VOID *) NULL) { - *PhyAddr = (UINT64) AdapterInfo->MemoryPtr; - } else { - (*AdapterInfo->Virt2Phys_30) (MemAddr, (UINT64) (UINTN) PhyAddr); - } - - if (*PhyAddr > FOUR_GIGABYTE) { - return PXE_STATCODE_INVALID_PARAMETER; - } - } else { - if (AdapterInfo->Map_Mem == (VOID *) NULL) { - // - // this UNDI cannot handle addresses beyond 4 GB without a map routine - // - if (MemAddr > FOUR_GIGABYTE) { - return PXE_STATCODE_INVALID_PARAMETER; - } else { - *PhyAddr = MemAddr; - } - } else { - (*AdapterInfo->Map_Mem) ( - AdapterInfo->Unique_ID, - MemAddr, - Size, - Direction, - MappedAddr - ); - } - } - - return PXE_STATCODE_SUCCESS; -} - -STATIC -VOID -UnMapIt ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN UINT64 MemAddr, - IN UINT32 Size, - IN UINT32 Direction, - IN UINT64 MappedAddr - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - MemAddr - TODO: add argument description - Size - TODO: add argument description - Direction - TODO: add argument description - MappedAddr - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - if (AdapterInfo->VersionFlag > 0x30) { - // - // no mapping service - // - if (AdapterInfo->UnMap_Mem != (VOID *) NULL) { - (*AdapterInfo->UnMap_Mem) ( - AdapterInfo->Unique_ID, - MemAddr, - Size, - Direction, - MappedAddr - ); - - } - } - - return ; -} - -STATIC -VOID -DelayIt ( - IN NIC_DATA_INSTANCE *AdapterInfo, - UINT16 MicroSeconds - ) -/*++ - -Routine Description: - -Arguments: - AdapterInfo - Pointer to the NIC data structure information - which the UNDI driver is layering on.. - -Returns: - ---*/ -// TODO: MicroSeconds - add argument and description to function comment -{ - if (AdapterInfo->VersionFlag == 0x30) { - (*AdapterInfo->Delay_30) (MicroSeconds); - } else { - (*AdapterInfo->Delay) (AdapterInfo->Unique_ID, MicroSeconds); - } -} - -STATIC -VOID -BlockIt ( - IN NIC_DATA_INSTANCE *AdapterInfo, - UINT32 flag - ) -/*++ - -Routine Description: - -Arguments: - AdapterInfo - Pointer to the NIC data structure information - which the UNDI driver is layering on.. - -Returns: - ---*/ -// TODO: flag - add argument and description to function comment -{ - if (AdapterInfo->VersionFlag == 0x30) { - (*AdapterInfo->Block_30) (flag); - } else { - (*AdapterInfo->Block) (AdapterInfo->Unique_ID, flag); - } -} - -STATIC -UINT8 -Load_Base_Regs ( - NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - // - // we will use the linear (flat) memory model and fill our base registers - // with 0's so that the entire physical address is our offset - // - // - // we reset the statistics totals here because this is where we are loading stats addr - // - AdapterInfo->RxTotals = 0; - AdapterInfo->TxTotals = 0; - - // - // Load the statistics block address. - // - wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); - OutLong (AdapterInfo, (UINT32) AdapterInfo->stat_phy_addr, AdapterInfo->ioaddr + SCBPointer); - OutByte (AdapterInfo, CU_STATSADDR, AdapterInfo->ioaddr + SCBCmd); - AdapterInfo->statistics->done_marker = 0; - - wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); - OutLong (AdapterInfo, 0, AdapterInfo->ioaddr + SCBPointer); - OutByte (AdapterInfo, RX_ADDR_LOAD, AdapterInfo->ioaddr + SCBCmd); - - wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); - OutLong (AdapterInfo, 0, AdapterInfo->ioaddr + SCBPointer); - OutByte (AdapterInfo, CU_CMD_BASE, AdapterInfo->ioaddr + SCBCmd); - - return 0; -} - -STATIC -UINT8 -IssueCB ( - NIC_DATA_INSTANCE *AdapterInfo, - TxCB *cmd_ptr - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - cmd_ptr - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - UINT16 status; - - wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); - - // - // read the CU status, if it is idle, write the address of cb_ptr - // in the scbpointer and issue a cu_start, - // if it is suspended, remove the suspend bit in the previous command - // block and issue a resume - // - // Ensure that the CU Active Status bit is not on from previous CBs. - // - status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus); - - // - // Skip acknowledging the interrupt if it is not already set - // - - // - // ack only the cna the integer - // - if ((status & SCB_STATUS_CNA) != 0) { - OutWord (AdapterInfo, SCB_STATUS_CNA, AdapterInfo->ioaddr + SCBStatus); - - } - - if ((status & SCB_STATUS_CU_MASK) == SCB_STATUS_CU_IDLE) { - // - // give a cu_start - // - OutLong (AdapterInfo, cmd_ptr->PhysTCBAddress, AdapterInfo->ioaddr + SCBPointer); - OutByte (AdapterInfo, CU_START, AdapterInfo->ioaddr + SCBCmd); - } else { - // - // either active or suspended, give a resume - // - - cmd_ptr->PrevTCBVirtualLinkPtr->cb_header.command &= ~(CmdSuspend | CmdIntr); - OutByte (AdapterInfo, CU_RESUME, AdapterInfo->ioaddr + SCBCmd); - } - - return 0; -} - -STATIC -UINT8 -Configure ( - NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - // - // all command blocks are of TxCB format - // - TxCB *cmd_ptr; - UINT8 *data_ptr; - volatile INT16 Index; - UINT8 my_filter; - - cmd_ptr = GetFreeCB (AdapterInfo); - data_ptr = (UINT8 *) (&cmd_ptr->PhysTBDArrayAddres); - - // - // start the config data right after the command header - // - for (Index = 0; Index < sizeof (basic_config_cmd); Index++) { - data_ptr[Index] = basic_config_cmd[Index]; - } - - my_filter = (UINT8) ((AdapterInfo->Rx_Filter & PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS) ? 1 : 0); - my_filter = (UINT8) ((my_filter | (AdapterInfo->Rx_Filter & PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST) ? 0 : 2)); - - data_ptr[15] = (UINT8) (data_ptr[15] | my_filter); - data_ptr[19] = (UINT8) (AdapterInfo->Duplex ? 0xC0 : 0x80); - data_ptr[21] = (UINT8) ((AdapterInfo->Rx_Filter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) ? 0x0D : 0x05); - - // - // check if we have to use the AUI port instead - // - if ((AdapterInfo->PhyRecord[0] & 0x8000) != 0) { - data_ptr[15] |= 0x80; - data_ptr[8] = 0; - } - - BlockIt (AdapterInfo, TRUE); - cmd_ptr->cb_header.command = CmdSuspend | CmdConfigure; - - IssueCB (AdapterInfo, cmd_ptr); - wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); - - BlockIt (AdapterInfo, FALSE); - - CommandWaitForCompletion (cmd_ptr, AdapterInfo); - - // - // restore the cb values for tx - // - cmd_ptr->PhysTBDArrayAddres = cmd_ptr->PhysArrayAddr; - cmd_ptr->ByteCount = cmd_ptr->Threshold = cmd_ptr->TBDCount = 0; - // - // fields beyond the immediatedata are assumed to be safe - // add the CB to the free list again - // - SetFreeCB (AdapterInfo, cmd_ptr); - return 0; -} - -UINT8 -E100bSetupIAAddr ( - NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - // - // all command blocks are of TxCB format - // - TxCB *cmd_ptr; - UINT16 *data_ptr; - UINT16 *eaddrs; - - eaddrs = (UINT16 *) AdapterInfo->CurrentNodeAddress; - - cmd_ptr = GetFreeCB (AdapterInfo); - data_ptr = (UINT16 *) (&cmd_ptr->PhysTBDArrayAddres); - - // - // AVOID a bug (?!) here by marking the command already completed. - // - cmd_ptr->cb_header.command = (CmdSuspend | CmdIASetup); - cmd_ptr->cb_header.status = 0; - data_ptr[0] = eaddrs[0]; - data_ptr[1] = eaddrs[1]; - data_ptr[2] = eaddrs[2]; - - BlockIt (AdapterInfo, TRUE); - IssueCB (AdapterInfo, cmd_ptr); - wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); - BlockIt (AdapterInfo, FALSE); - - CommandWaitForCompletion (cmd_ptr, AdapterInfo); - - // - // restore the cb values for tx - // - cmd_ptr->PhysTBDArrayAddres = cmd_ptr->PhysArrayAddr; - cmd_ptr->ByteCount = cmd_ptr->Threshold = cmd_ptr->TBDCount = 0; - // - // fields beyond the immediatedata are assumed to be safe - // add the CB to the free list again - // - SetFreeCB (AdapterInfo, cmd_ptr); - return 0; -} - -STATIC -VOID -StopRU ( - IN NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - Instructs the NIC to stop receiving packets. - -Arguments: - AdapterInfo - Pointer to the NIC data structure information - which the UNDI driver is layering on.. -Returns: - ---*/ -{ - if (AdapterInfo->Receive_Started) { - - // - // Todo: verify that we must wait for previous command completion. - // - wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); - - // - // Disable interrupts, and stop the chip's Rx process. - // - OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd); - OutWord (AdapterInfo, INT_MASK | RX_ABORT, AdapterInfo->ioaddr + SCBCmd); - - AdapterInfo->Receive_Started = FALSE; - } - - return ; -} - -STATIC -INT8 -StartRU ( - NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - Instructs the NIC to start receiving packets. - -Arguments: - AdapterInfo - Pointer to the NIC data structure information - which the UNDI driver is layering on.. -Returns: - 0 - Successful - -1 - Already Started ---*/ -{ - - if (AdapterInfo->Receive_Started) { - // - // already started - // - return -1; - } - - AdapterInfo->cur_rx_ind = 0; - AdapterInfo->Int_Status = 0; - - wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); - - OutLong (AdapterInfo, (UINT32) AdapterInfo->rx_phy_addr, AdapterInfo->ioaddr + SCBPointer); - OutByte (AdapterInfo, RX_START, AdapterInfo->ioaddr + SCBCmd); - - wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); - - AdapterInfo->Receive_Started = TRUE; - return 0; -} - -UINTN -E100bInit ( - IN NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - Configures the chip. This routine expects the NIC_DATA_INSTANCE structure to be filled in. - -Arguments: - AdapterInfo - Pointer to the NIC data structure information - which the UNDI driver is layering on.. - -Returns: - 0 - Successful - PXE_STATCODE_NOT_ENOUGH_MEMORY - Insufficient length of locked memory - other - Failure initializing chip ---*/ -{ - PCI_CONFIG_HEADER *CfgHdr; - UINTN stat; - UINTN rx_size; - UINTN tx_size; - - if (AdapterInfo->MemoryLength < MEMORY_NEEDED) { - return PXE_STATCODE_NOT_ENOUGH_MEMORY; - } - - stat = MapIt ( - AdapterInfo, - AdapterInfo->MemoryPtr, - AdapterInfo->MemoryLength, - TO_AND_FROM_DEVICE, - (UINT64)(UINTN) &AdapterInfo->Mapped_MemoryPtr - ); - - if (stat != 0) { - return stat; - } - - CfgHdr = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]); - - // - // fill in the ioaddr, int... from the config space - // - AdapterInfo->int_num = CfgHdr->int_line; - - // - // we don't need to validate integer number, what if they don't want to assign one? - // if (AdapterInfo->int_num == 0 || AdapterInfo->int_num == 0xff) - // return PXE_STATCODE_DEVICE_FAILURE; - // - AdapterInfo->ioaddr = 0; - AdapterInfo->VendorID = CfgHdr->VendorID; - AdapterInfo->DeviceID = CfgHdr->DeviceID; - AdapterInfo->RevID = CfgHdr->RevID; - AdapterInfo->SubVendorID = CfgHdr->SubVendorID; - AdapterInfo->SubSystemID = CfgHdr->SubSystemID; - AdapterInfo->flash_addr = 0; - - // - // Read the station address EEPROM before doing the reset. - // Perhaps this should even be done before accepting the device, - // then we wouldn't have a device name with which to report the error. - // - if (E100bReadEepromAndStationAddress (AdapterInfo) != 0) { - return PXE_STATCODE_DEVICE_FAILURE; - - } - // - // ## calculate the buffer #s depending on memory given - // ## calculate the rx and tx ring pointers - // - - AdapterInfo->TxBufCnt = TX_BUFFER_COUNT; - AdapterInfo->RxBufCnt = RX_BUFFER_COUNT; - rx_size = (AdapterInfo->RxBufCnt * sizeof (RxFD)); - tx_size = (AdapterInfo->TxBufCnt * sizeof (TxCB)); - AdapterInfo->rx_ring = (RxFD *) (UINTN) (AdapterInfo->MemoryPtr); - AdapterInfo->tx_ring = (TxCB *) (UINTN) (AdapterInfo->MemoryPtr + rx_size); - AdapterInfo->statistics = (struct speedo_stats *) (UINTN) (AdapterInfo->MemoryPtr + rx_size + tx_size); - - AdapterInfo->rx_phy_addr = AdapterInfo->Mapped_MemoryPtr; - AdapterInfo->tx_phy_addr = AdapterInfo->Mapped_MemoryPtr + rx_size; - AdapterInfo->stat_phy_addr = AdapterInfo->tx_phy_addr + tx_size; - - // - // auto detect. - // - AdapterInfo->PhyAddress = 0xFF; - AdapterInfo->Rx_Filter = PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; - AdapterInfo->Receive_Started = FALSE; - AdapterInfo->mcast_list.list_len = 0; - return InitializeChip (AdapterInfo); -} - -UINT8 -E100bSetInterruptState ( - IN NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - Sets the interrupt state for the NIC. - -Arguments: - AdapterInfo - Pointer to the NIC data structure information - which the UNDI driver is layering on.. -Returns: - 0 - Successful ---*/ -{ - // - // don't set receive interrupt if receiver is disabled... - // - UINT16 cmd_word; - - if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_RECEIVE) != 0) { - cmd_word = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBCmd); - cmd_word &= ~INT_MASK; - OutWord (AdapterInfo, cmd_word, AdapterInfo->ioaddr + SCBCmd); - } else { - // - // disable ints, should not be given for SW Int. - // - OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd); - } - - if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_SOFTWARE) != 0) { - // - // reset the bit in our mask, it is only one time!! - // - AdapterInfo->int_mask &= ~(PXE_OPFLAGS_INTERRUPT_SOFTWARE); - cmd_word = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBCmd); - cmd_word |= DRVR_INT; - OutWord (AdapterInfo, cmd_word, AdapterInfo->ioaddr + SCBCmd); - } - - return 0; -} -// -// we are not going to disable broadcast for the WOL's sake! -// -UINTN -E100bSetfilter ( - NIC_DATA_INSTANCE *AdapterInfo, - UINT16 new_filter, - UINT64 cpb, - UINT32 cpbsize - ) -/*++ - -Routine Description: - Instructs the NIC to start receiving packets. - -Arguments: - AdapterInfo - Pointer to the NIC data structure information - which the UNDI driver is layering on.. - new_filter - - cpb - - cpbsize - - -Returns: - 0 - Successful - -1 - Already Started ---*/ -{ - PXE_CPB_RECEIVE_FILTERS *mc_list = (PXE_CPB_RECEIVE_FILTERS *) (UINTN)cpb; - UINT16 cfg_flt; - UINT16 old_filter; - UINT16 Index; - UINT16 Index2; - UINT16 mc_count; - TxCB *cmd_ptr; - struct MC_CB_STRUCT *data_ptr; - UINT16 mc_byte_cnt; - - old_filter = AdapterInfo->Rx_Filter; - - // - // only these bits need a change in the configuration - // actually change in bcast requires configure but we ignore that change - // - cfg_flt = PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS | - PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; - - if ((old_filter & cfg_flt) != (new_filter & cfg_flt)) { - XmitWaitForCompletion (AdapterInfo); - - if (AdapterInfo->Receive_Started) { - StopRU (AdapterInfo); - } - - AdapterInfo->Rx_Filter = (UINT8) (new_filter | PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST); - Configure (AdapterInfo); - } - - // - // check if mcast setting changed - // - if ( ((new_filter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != - (old_filter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) ) || - (mc_list != NULL) ) { - - - if (mc_list != NULL) { - mc_count = AdapterInfo->mcast_list.list_len = (UINT16) (cpbsize / PXE_MAC_LENGTH); - - for (Index = 0; (Index < mc_count && Index < MAX_MCAST_ADDRESS_CNT); Index++) { - for (Index2 = 0; Index2 < PXE_MAC_LENGTH; Index2++) { - AdapterInfo->mcast_list.mc_list[Index][Index2] = mc_list->MCastList[Index][Index2]; - } - } - } - - // - // are we setting the list or resetting?? - // - if ((new_filter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) { - // - // we are setting a new list! - // - mc_count = AdapterInfo->mcast_list.list_len; - // - // count should be the actual # of bytes in the list - // so multiply this with 6 - // - mc_byte_cnt = (UINT16) ((mc_count << 2) + (mc_count << 1)); - AdapterInfo->Rx_Filter |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; - } else { - // - // disabling the list in the NIC. - // - mc_byte_cnt = mc_count = 0; - AdapterInfo->Rx_Filter &= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST); - } - - // - // before issuing any new command! - // - XmitWaitForCompletion (AdapterInfo); - - if (AdapterInfo->Receive_Started) { - StopRU (AdapterInfo); - - } - - cmd_ptr = GetFreeCB (AdapterInfo); - if (cmd_ptr == NULL) { - return PXE_STATCODE_QUEUE_FULL; - } - // - // fill the command structure and issue - // - data_ptr = (struct MC_CB_STRUCT *) (&cmd_ptr->PhysTBDArrayAddres); - // - // first 2 bytes are the count; - // - data_ptr->count = mc_byte_cnt; - for (Index = 0; Index < mc_count; Index++) { - for (Index2 = 0; Index2 < PXE_HWADDR_LEN_ETHER; Index2++) { - data_ptr->m_list[Index][Index2] = AdapterInfo->mcast_list.mc_list[Index][Index2]; - } - } - - cmd_ptr->cb_header.command = CmdSuspend | CmdMulticastList; - cmd_ptr->cb_header.status = 0; - - BlockIt (AdapterInfo, TRUE); - IssueCB (AdapterInfo, cmd_ptr); - wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); - - BlockIt (AdapterInfo, FALSE); - - CommandWaitForCompletion (cmd_ptr, AdapterInfo); - - cmd_ptr->PhysTBDArrayAddres = cmd_ptr->PhysArrayAddr; - cmd_ptr->ByteCount = cmd_ptr->Threshold = cmd_ptr->TBDCount = 0; - // - // fields beyond the immediatedata are assumed to be safe - // add the CB to the free list again - // - SetFreeCB (AdapterInfo, cmd_ptr); - } - - if (new_filter != 0) { - // - // enable unicast and start the RU - // - AdapterInfo->Rx_Filter = (UINT8) (AdapterInfo->Rx_Filter | (new_filter | PXE_OPFLAGS_RECEIVE_FILTER_UNICAST)); - StartRU (AdapterInfo); - } else { - // - // may be disabling everything! - // - if (AdapterInfo->Receive_Started) { - StopRU (AdapterInfo); - } - - AdapterInfo->Rx_Filter |= (~PXE_OPFLAGS_RECEIVE_FILTER_UNICAST); - } - - return 0; -} - -UINTN -E100bTransmit ( - NIC_DATA_INSTANCE *AdapterInfo, - UINT64 cpb, - UINT16 opflags - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - cpb - TODO: add argument description - opflags - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - PXE_CPB_TRANSMIT_FRAGMENTS *tx_ptr_f; - PXE_CPB_TRANSMIT *tx_ptr_1; - TxCB *tcb_ptr; - UINT64 Tmp_ptr; - UINTN stat; - INT32 Index; - UINT16 wait_sec; - - tx_ptr_1 = (PXE_CPB_TRANSMIT *) (UINTN) cpb; - tx_ptr_f = (PXE_CPB_TRANSMIT_FRAGMENTS *) (UINTN) cpb; - - // - // stop reentrancy here - // - if (AdapterInfo->in_transmit) { - return PXE_STATCODE_BUSY; - - } - - AdapterInfo->in_transmit = TRUE; - - // - // Prevent interrupts from changing the Tx ring from underneath us. - // - // Calculate the Tx descriptor entry. - // - if ((tcb_ptr = GetFreeCB (AdapterInfo)) == NULL) { - AdapterInfo->in_transmit = FALSE; - return PXE_STATCODE_QUEUE_FULL; - } - - AdapterInfo->TxTotals++; - - tcb_ptr->cb_header.command = (CmdSuspend | CmdTx | CmdTxFlex); - tcb_ptr->cb_header.status = 0; - - // - // no immediate data, set EOF in the ByteCount - // - tcb_ptr->ByteCount = 0x8000; - - // - // The data region is always in one buffer descriptor, Tx FIFO - // threshold of 256. - // 82557 multiplies the threashold value by 8, so give 256/8 - // - tcb_ptr->Threshold = 32; - if ((opflags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) != 0) { - - if (tx_ptr_f->FragCnt > MAX_XMIT_FRAGMENTS) { - SetFreeCB (AdapterInfo, tcb_ptr); - AdapterInfo->in_transmit = FALSE; - return PXE_STATCODE_INVALID_PARAMETER; - } - - tcb_ptr->TBDCount = (UINT8) tx_ptr_f->FragCnt; - - for (Index = 0; Index < tx_ptr_f->FragCnt; Index++) { - stat = MapIt ( - AdapterInfo, - tx_ptr_f->FragDesc[Index].FragAddr, - tx_ptr_f->FragDesc[Index].FragLen, - TO_DEVICE, - (UINT64)(UINTN) &Tmp_ptr - ); - if (stat != 0) { - SetFreeCB (AdapterInfo, tcb_ptr); - AdapterInfo->in_transmit = FALSE; - return PXE_STATCODE_INVALID_PARAMETER; - } - - tcb_ptr->TBDArray[Index].phys_buf_addr = (UINT32) Tmp_ptr; - tcb_ptr->TBDArray[Index].buf_len = tx_ptr_f->FragDesc[Index].FragLen; - } - - tcb_ptr->free_data_ptr = tx_ptr_f->FragDesc[0].FragAddr; - - } else { - // - // non fragmented case - // - tcb_ptr->TBDCount = 1; - stat = MapIt ( - AdapterInfo, - tx_ptr_1->FrameAddr, - tx_ptr_1->DataLen + tx_ptr_1->MediaheaderLen, - TO_DEVICE, - (UINT64)(UINTN) &Tmp_ptr - ); - if (stat != 0) { - SetFreeCB (AdapterInfo, tcb_ptr); - AdapterInfo->in_transmit = FALSE; - return PXE_STATCODE_INVALID_PARAMETER; - } - - tcb_ptr->TBDArray[0].phys_buf_addr = (UINT32) (Tmp_ptr); - tcb_ptr->TBDArray[0].buf_len = tx_ptr_1->DataLen + tx_ptr_1->MediaheaderLen; - tcb_ptr->free_data_ptr = tx_ptr_1->FrameAddr; - } - - // - // must wait for previous command completion only if it was a non-transmit - // - BlockIt (AdapterInfo, TRUE); - IssueCB (AdapterInfo, tcb_ptr); - BlockIt (AdapterInfo, FALSE); - - // - // see if we need to wait for completion here - // - if ((opflags & PXE_OPFLAGS_TRANSMIT_BLOCK) != 0) { - // - // don't wait for more than 1 second!!! - // - wait_sec = 1000; - while (tcb_ptr->cb_header.status == 0) { - DelayIt (AdapterInfo, 10); - wait_sec--; - if (wait_sec == 0) { - break; - } - } - // - // we need to un-map any mapped buffers here - // - if ((opflags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) != 0) { - - for (Index = 0; Index < tx_ptr_f->FragCnt; Index++) { - Tmp_ptr = tcb_ptr->TBDArray[Index].phys_buf_addr; - UnMapIt ( - AdapterInfo, - tx_ptr_f->FragDesc[Index].FragAddr, - tx_ptr_f->FragDesc[Index].FragLen, - TO_DEVICE, - (UINT64) Tmp_ptr - ); - } - } else { - Tmp_ptr = tcb_ptr->TBDArray[0].phys_buf_addr; - UnMapIt ( - AdapterInfo, - tx_ptr_1->FrameAddr, - tx_ptr_1->DataLen + tx_ptr_1->MediaheaderLen, - TO_DEVICE, - (UINT64) Tmp_ptr - ); - } - - if (tcb_ptr->cb_header.status == 0) { - SetFreeCB (AdapterInfo, tcb_ptr); - AdapterInfo->in_transmit = FALSE; - return PXE_STATCODE_DEVICE_FAILURE; - } - - SetFreeCB (AdapterInfo, tcb_ptr); - } - // - // CB will be set free later in get_status (or when we run out of xmit buffers - // - AdapterInfo->in_transmit = FALSE; - - return 0; -} - -UINTN -E100bReceive ( - NIC_DATA_INSTANCE *AdapterInfo, - UINT64 cpb, - UINT64 db - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - cpb - TODO: add argument description - db - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - PXE_CPB_RECEIVE *rx_cpbptr; - PXE_DB_RECEIVE *rx_dbptr; - RxFD *rx_ptr; - INT32 status; - INT32 Index; - UINT16 pkt_len; - UINT16 ret_code; - PXE_FRAME_TYPE pkt_type; - UINT16 Tmp_len; - EtherHeader *hdr_ptr; - ret_code = PXE_STATCODE_NO_DATA; - pkt_type = PXE_FRAME_TYPE_NONE; - status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus); - AdapterInfo->Int_Status = (UINT16) (AdapterInfo->Int_Status | status); - // - // acknoledge the interrupts - // - OutWord (AdapterInfo, (UINT16) (status & 0xfc00), (UINT32) (AdapterInfo->ioaddr + SCBStatus)); - - // - // include the prev ints as well - // - status = AdapterInfo->Int_Status; - rx_cpbptr = (PXE_CPB_RECEIVE *) (UINTN) cpb; - rx_dbptr = (PXE_DB_RECEIVE *) (UINTN) db; - - rx_ptr = &AdapterInfo->rx_ring[AdapterInfo->cur_rx_ind]; - - // - // be in a loop just in case (we may drop a pkt) - // - while ((status = rx_ptr->cb_header.status) & RX_COMPLETE) { - - AdapterInfo->RxTotals++; - // - // If we own the next entry, it's a new packet. Send it up. - // - if (rx_ptr->forwarded) { - goto FreeRFD; - - } - - // - // discard bad frames - // - - // - // crc, align, dma overrun, too short, receive error (v22 no coll) - // - if ((status & 0x0D90) != 0) { - goto FreeRFD; - - } - - // - // make sure the status is OK - // - if ((status & 0x02000) == 0) { - goto FreeRFD; - } - - pkt_len = (UINT16) (rx_ptr->ActualCount & 0x3fff); - - if (pkt_len != 0) { - - Tmp_len = pkt_len; - if (pkt_len > rx_cpbptr->BufferLen) { - Tmp_len = (UINT16) rx_cpbptr->BufferLen; - } - - CopyMem ((INT8 *) (UINTN) rx_cpbptr->BufferAddr, (INT8 *) &rx_ptr->RFDBuffer, Tmp_len); - - hdr_ptr = (EtherHeader *) &rx_ptr->RFDBuffer; - // - // fill the CDB and break the loop - // - - // - // includes header - // - rx_dbptr->FrameLen = pkt_len; - rx_dbptr->MediaHeaderLen = PXE_MAC_HEADER_LEN_ETHER; - - for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { - if (hdr_ptr->dest_addr[Index] != AdapterInfo->CurrentNodeAddress[Index]) { - break; - } - } - - if (Index >= PXE_HWADDR_LEN_ETHER) { - pkt_type = PXE_FRAME_TYPE_UNICAST; - } else { - for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { - if (hdr_ptr->dest_addr[Index] != AdapterInfo->BroadcastNodeAddress[Index]) { - break; - } - } - - if (Index >= PXE_HWADDR_LEN_ETHER) { - pkt_type = PXE_FRAME_TYPE_BROADCAST; - } else { - if ((hdr_ptr->dest_addr[0] & 1) == 1) { - // - // mcast - // - - pkt_type = PXE_FRAME_TYPE_MULTICAST; - } else { - pkt_type = PXE_FRAME_TYPE_PROMISCUOUS; - } - } - } - - rx_dbptr->Type = pkt_type; - rx_dbptr->Protocol = hdr_ptr->type; - - for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { - rx_dbptr->SrcAddr[Index] = hdr_ptr->src_addr[Index]; - rx_dbptr->DestAddr[Index] = hdr_ptr->dest_addr[Index]; - } - - rx_ptr->forwarded = TRUE; - // - // success - // - ret_code = 0; - Recycle_RFD (AdapterInfo, AdapterInfo->cur_rx_ind); - AdapterInfo->cur_rx_ind++; - if (AdapterInfo->cur_rx_ind == AdapterInfo->RxBufCnt) { - AdapterInfo->cur_rx_ind = 0; - } - break; - } - -FreeRFD: - Recycle_RFD (AdapterInfo, AdapterInfo->cur_rx_ind); - AdapterInfo->cur_rx_ind++; - if (AdapterInfo->cur_rx_ind == AdapterInfo->RxBufCnt) { - AdapterInfo->cur_rx_ind = 0; - } - - rx_ptr = &AdapterInfo->rx_ring[AdapterInfo->cur_rx_ind]; - } - - if (pkt_type == PXE_FRAME_TYPE_NONE) { - AdapterInfo->Int_Status &= (~SCB_STATUS_FR); - } - - status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus); - if ((status & SCB_RUS_NO_RESOURCES) != 0) { - // - // start the receive unit here! - // leave all the filled frames, - // - SetupReceiveQueues (AdapterInfo); - OutLong (AdapterInfo, (UINT32) AdapterInfo->rx_phy_addr, AdapterInfo->ioaddr + SCBPointer); - OutWord (AdapterInfo, RX_START, AdapterInfo->ioaddr + SCBCmd); - AdapterInfo->cur_rx_ind = 0; - } - - return ret_code; -} - -INT16 -E100bReadEepromAndStationAddress ( - NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - INT32 Index; - INT32 Index2; - UINT16 sum; - UINT16 eeprom_len; - UINT8 addr_len; - UINT16 *eedata; - - eedata = (UINT16 *) (&AdapterInfo->NVData[0]); - - sum = 0; - addr_len = E100bGetEepromAddrLen (AdapterInfo); - - // - // in words - // - AdapterInfo->NVData_Len = eeprom_len = (UINT16) (1 << addr_len); - for (Index2 = 0, Index = 0; Index < eeprom_len; Index++) { - UINT16 value; - value = E100bReadEeprom (AdapterInfo, Index, addr_len); - eedata[Index] = value; - sum = (UINT16) (sum + value); - if (Index < 3) { - AdapterInfo->PermNodeAddress[Index2++] = (UINT8) value; - AdapterInfo->PermNodeAddress[Index2++] = (UINT8) (value >> 8); - } - } - - if (sum != 0xBABA) { - return -1; - } - - for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { - AdapterInfo->CurrentNodeAddress[Index] = AdapterInfo->PermNodeAddress[Index]; - } - - for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { - AdapterInfo->BroadcastNodeAddress[Index] = 0xff; - } - - for (Index = PXE_HWADDR_LEN_ETHER; Index < PXE_MAC_LENGTH; Index++) { - AdapterInfo->CurrentNodeAddress[Index] = 0; - AdapterInfo->PermNodeAddress[Index] = 0; - AdapterInfo->BroadcastNodeAddress[Index] = 0; - } - - return 0; -} - -// -// CBList is a circular linked list -// 1) When all are free, Tail->next == Head and FreeCount == # allocated -// 2) When none are free, Tail == Head and FreeCount == 0 -// 3) when one is free, Tail == Head and Freecount == 1 -// 4) First non-Free frame is always at Tail->next -// -UINT8 -SetupCBlink ( - NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - TxCB *head_ptr; - TxCB *tail_ptr; - TxCB *cur_ptr; - INT32 Index; - UINTN array_off; - - cur_ptr = &(AdapterInfo->tx_ring[0]); - array_off = (UINTN) (&cur_ptr->TBDArray) - (UINTN) cur_ptr; - for (Index = 0; Index < AdapterInfo->TxBufCnt; Index++) { - cur_ptr[Index].cb_header.status = 0; - cur_ptr[Index].cb_header.command = 0; - - cur_ptr[Index].PhysTCBAddress = - (UINT32) AdapterInfo->tx_phy_addr + (Index * sizeof (TxCB)); - - cur_ptr[Index].PhysArrayAddr = (UINT32)(cur_ptr[Index].PhysTCBAddress + array_off); - cur_ptr[Index].PhysTBDArrayAddres = (UINT32)(cur_ptr[Index].PhysTCBAddress + array_off); - - cur_ptr->free_data_ptr = (UINT64) 0; - - if (Index < AdapterInfo->TxBufCnt - 1) { - cur_ptr[Index].cb_header.link = cur_ptr[Index].PhysTCBAddress + sizeof (TxCB); - cur_ptr[Index].NextTCBVirtualLinkPtr = &cur_ptr[Index + 1]; - cur_ptr[Index + 1].PrevTCBVirtualLinkPtr = &cur_ptr[Index]; - } - } - - head_ptr = &cur_ptr[0]; - tail_ptr = &cur_ptr[AdapterInfo->TxBufCnt - 1]; - tail_ptr->cb_header.link = head_ptr->PhysTCBAddress; - tail_ptr->NextTCBVirtualLinkPtr = head_ptr; - head_ptr->PrevTCBVirtualLinkPtr = tail_ptr; - - AdapterInfo->FreeCBCount = AdapterInfo->TxBufCnt; - AdapterInfo->FreeTxHeadPtr = head_ptr; - // - // set tail of the free list, next to this would be either in use - // or the head itself - // - AdapterInfo->FreeTxTailPtr = tail_ptr; - - AdapterInfo->xmit_done_head = AdapterInfo->xmit_done_tail = 0; - - return 0; -} - -TxCB * -GetFreeCB ( - NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - TxCB *free_cb_ptr; - - // - // claim any hanging free CBs - // - if (AdapterInfo->FreeCBCount <= 1) { - CheckCBList (AdapterInfo); - } - - // - // don't use up the last CB problem if the previous CB that the CU used - // becomes the last CB we submit because of the SUSPEND bit we set. - // the CU thinks it was never cleared. - // - - if (AdapterInfo->FreeCBCount <= 1) { - return NULL; - } - - BlockIt (AdapterInfo, TRUE); - free_cb_ptr = AdapterInfo->FreeTxHeadPtr; - AdapterInfo->FreeTxHeadPtr = free_cb_ptr->NextTCBVirtualLinkPtr; - --AdapterInfo->FreeCBCount; - BlockIt (AdapterInfo, FALSE); - return free_cb_ptr; -} - -VOID -SetFreeCB ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN TxCB *cb_ptr - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - cb_ptr - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - // - // here we assume cb are returned in the order they are taken out - // and we link the newly freed cb at the tail of free cb list - // - cb_ptr->cb_header.status = 0; - cb_ptr->free_data_ptr = (UINT64) 0; - - AdapterInfo->FreeTxTailPtr = cb_ptr; - ++AdapterInfo->FreeCBCount; - return ; -} - -UINT16 -next ( - IN UINT16 ind - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - ind - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - UINT16 Tmp; - - Tmp = (UINT16) (ind + 1); - if (Tmp >= (TX_BUFFER_COUNT << 1)) { - Tmp = 0; - } - - return Tmp; -} - -UINT16 -CheckCBList ( - IN NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - TxCB *Tmp_ptr; - UINT16 cnt; - - cnt = 0; - while (1) { - Tmp_ptr = AdapterInfo->FreeTxTailPtr->NextTCBVirtualLinkPtr; - if ((Tmp_ptr->cb_header.status & CMD_STATUS_MASK) != 0) { - // - // check if Q is full - // - if (next (AdapterInfo->xmit_done_tail) != AdapterInfo->xmit_done_head) { - AdapterInfo->xmit_done[AdapterInfo->xmit_done_tail] = Tmp_ptr->free_data_ptr; - - UnMapIt ( - AdapterInfo, - Tmp_ptr->free_data_ptr, - Tmp_ptr->TBDArray[0].buf_len, - TO_DEVICE, - (UINT64) Tmp_ptr->TBDArray[0].phys_buf_addr - ); - - AdapterInfo->xmit_done_tail = next (AdapterInfo->xmit_done_tail); - } - - SetFreeCB (AdapterInfo, Tmp_ptr); - } else { - break; - } - } - - return cnt; -} -// -// Description : Initialize the RFD list list by linking each element together -// in a circular list. The simplified memory model is used. -// All data is in the RFD. The RFDs are linked together and the -// last one points back to the first one. When the current RFD -// is processed (frame received), its EL bit is set and the EL -// bit in the previous RXFD is cleared. -// Allocation done during INIT, this is making linked list. -// -UINT8 -SetupReceiveQueues ( - IN NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - RxFD *rx_ptr; - RxFD *tail_ptr; - UINT16 Index; - - AdapterInfo->cur_rx_ind = 0; - rx_ptr = (&AdapterInfo->rx_ring[0]); - - for (Index = 0; Index < AdapterInfo->RxBufCnt; Index++) { - rx_ptr[Index].cb_header.status = 0; - rx_ptr[Index].cb_header.command = 0; - rx_ptr[Index].RFDSize = RX_BUFFER_SIZE; - rx_ptr[Index].ActualCount = 0; - // - // RBDs not used, simple memory model - // - rx_ptr[Index].rx_buf_addr = (UINT32) (-1); - - // - // RBDs not used, simple memory model - // - rx_ptr[Index].forwarded = FALSE; - - // - // don't use Tmp_ptr if it is beyond the last one - // - if (Index < AdapterInfo->RxBufCnt - 1) { - rx_ptr[Index].cb_header.link = (UINT32) AdapterInfo->rx_phy_addr + ((Index + 1) * sizeof (RxFD)); - } - } - - tail_ptr = (&AdapterInfo->rx_ring[AdapterInfo->RxBufCnt - 1]); - tail_ptr->cb_header.link = (UINT32) AdapterInfo->rx_phy_addr; - - // - // set the EL bit - // - tail_ptr->cb_header.command = 0xC000; - AdapterInfo->RFDTailPtr = tail_ptr; - return 0; -} - -VOID -Recycle_RFD ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN UINT16 rx_index - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - rx_index - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - RxFD *rx_ptr; - RxFD *tail_ptr; - // - // change the EL bit and change the AdapterInfo->RxTailPtr - // rx_ptr is assumed to be the head of the Q - // AdapterInfo->rx_forwarded[rx_index] = FALSE; - // - rx_ptr = &AdapterInfo->rx_ring[rx_index]; - tail_ptr = AdapterInfo->RFDTailPtr; - // - // set el_bit and suspend bit - // - rx_ptr->cb_header.command = 0xc000; - rx_ptr->cb_header.status = 0; - rx_ptr->ActualCount = 0; - rx_ptr->forwarded = FALSE; - AdapterInfo->RFDTailPtr = rx_ptr; - // - // resetting the el_bit. - // - tail_ptr->cb_header.command = 0; - // - // check the receive unit, fix if there is any problem - // - return ; -} -// -// Serial EEPROM section. -// -// EEPROM_Ctrl bits. -// -#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */ -#define EE_CS 0x02 /* EEPROM chip select. */ -#define EE_DI 0x04 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x01 -#define EE_WRITE_1 0x05 -#define EE_DO 0x08 /* EEPROM chip data out. */ -#define EE_ENB (0x4800 | EE_CS) - -// -// Delay between EEPROM clock transitions. -// This will actually work with no delay on 33Mhz PCI. -// -#define eeprom_delay(nanosec) DelayIt (AdapterInfo, nanosec); - -// -// The EEPROM commands include the alway-set leading bit. -// -#define EE_WRITE_CMD 5 // 101b -#define EE_READ_CMD 6 // 110b -#define EE_ERASE_CMD (7 << 6) - -STATIC -VOID -shift_bits_out ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN UINT16 val, - IN UINT8 num_bits - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - val - TODO: add argument description - num_bits - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - INT32 Index; - UINT8 Tmp; - UINT32 EEAddr; - - EEAddr = AdapterInfo->ioaddr + SCBeeprom; - - for (Index = num_bits; Index >= 0; Index--) { - INT16 dataval; - - // - // will be 0 or 4 - // - dataval = (INT16) ((val & (1 << Index)) ? EE_DI : 0); - - // - // mask off the data_in bit - // - Tmp = (UINT8) (InByte (AdapterInfo, EEAddr) &~EE_DI); - Tmp = (UINT8) (Tmp | dataval); - OutByte (AdapterInfo, Tmp, EEAddr); - eeprom_delay (100); - // - // raise the eeprom clock - // - OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr); - eeprom_delay (150); - // - // lower the eeprom clock - // - OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr); - eeprom_delay (150); - } -} - -STATIC -UINT16 -shift_bits_in ( - IN NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - UINT8 Tmp; - INT32 Index; - UINT16 retval; - UINT32 EEAddr; - - EEAddr = AdapterInfo->ioaddr + SCBeeprom; - - retval = 0; - for (Index = 15; Index >= 0; Index--) { - // - // raise the clock - // - - // - // mask off the data_in bit - // - Tmp = InByte (AdapterInfo, EEAddr); - OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr); - eeprom_delay (100); - Tmp = InByte (AdapterInfo, EEAddr); - retval = (UINT16) ((retval << 1) | ((Tmp & EE_DO) ? 1 : 0)); - // - // lower the clock - // - OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr); - eeprom_delay (100); - } - - return retval; -} - -STATIC -BOOLEAN -E100bSetEepromLockOut ( - IN NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - This routine sets the EEPROM lockout bit to gain exclusive access to the - eeprom. the access bit is the most significant bit in the General Control - Register 2 in the SCB space. - -Arguments: - AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. - -Returns: - TRUE - if it got the access - FALSE - if it fails to get the exclusive access - ---*/ -{ - UINTN wait; - UINT8 tmp; - - if ((AdapterInfo->DeviceID == D102_DEVICE_ID) || - (AdapterInfo->RevID >= D102_REVID)) { - - wait = 500; - - while (wait--) { - - tmp = InByte (AdapterInfo, AdapterInfo->ioaddr + SCBGenCtrl2); - tmp |= GCR2_EEPROM_ACCESS_SEMAPHORE; - OutByte (AdapterInfo, tmp, AdapterInfo->ioaddr + SCBGenCtrl2); - - DelayIt (AdapterInfo, 50); - tmp = InByte (AdapterInfo, AdapterInfo->ioaddr + SCBGenCtrl2); - - if (tmp & GCR2_EEPROM_ACCESS_SEMAPHORE) { - return TRUE; - } - } - - return FALSE; - } - - return TRUE; -} - -STATIC -VOID -E100bReSetEepromLockOut ( - IN NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - This routine Resets the EEPROM lockout bit to giveup access to the - eeprom. the access bit is the most significant bit in the General Control - Register 2 in the SCB space. - -Arguments: - AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. - -Returns: - None - ---*/ -{ - UINT8 tmp; - - if ((AdapterInfo->DeviceID == D102_DEVICE_ID) || - (AdapterInfo->RevID >= D102_REVID)) { - - tmp = InByte (AdapterInfo, AdapterInfo->ioaddr + SCBGenCtrl2); - tmp &= ~(GCR2_EEPROM_ACCESS_SEMAPHORE); - OutByte (AdapterInfo, tmp, AdapterInfo->ioaddr + SCBGenCtrl2); - - DelayIt (AdapterInfo, 50); - } -} - -UINT16 -E100bReadEeprom ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN INT32 Location, - IN UINT8 AddrLen - ) -/*++ - -Routine Description: - Using the NIC data structure information, read the EEPROM to get a Word of data for the MAC address. - -Arguments: - AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. - Location - Word offset into the MAC address to read. - AddrLen - Number of bits of address length. - -Returns: - RetVal - The word read from the EEPROM. - ---*/ -{ - UINT16 RetVal; - UINT8 Tmp; - - UINT32 EEAddr; - UINT16 ReadCmd; - - EEAddr = AdapterInfo->ioaddr + SCBeeprom; - ReadCmd = (UINT16) (Location | (EE_READ_CMD << AddrLen)); - - RetVal = 0; - - // - // get exclusive access to the eeprom first! - // - E100bSetEepromLockOut (AdapterInfo); - - // - // eeprom control reg bits: x,x,x,x,DO,DI,CS,SK - // to write the opcode+data value out one bit at a time in DI starting at msb - // and then out a 1 to sk, wait, out 0 to SK and wait - // repeat this for all the bits to be written - // - - // - // 11110010b - // - Tmp = (UINT8) (InByte (AdapterInfo, EEAddr) & 0xF2); - OutByte (AdapterInfo, (UINT8) (Tmp | EE_CS), EEAddr); - - // - // 3 for the read opcode 110b - // - shift_bits_out (AdapterInfo, ReadCmd, (UINT8) (3 + AddrLen)); - - // - // read the eeprom word one bit at a time - // - RetVal = shift_bits_in (AdapterInfo); - - // - // Terminate the EEPROM access and leave eeprom in a clean state. - // - Tmp = InByte (AdapterInfo, EEAddr); - Tmp &= ~(EE_CS | EE_DI); - OutByte (AdapterInfo, Tmp, EEAddr); - - // - // raise the clock and lower the eeprom shift clock - // - OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr); - eeprom_delay (100); - - OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr); - eeprom_delay (100); - - // - // giveup access to the eeprom - // - E100bReSetEepromLockOut (AdapterInfo); - - return RetVal; -} - -UINT8 -E100bGetEepromAddrLen ( - IN NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - Using the NIC data structure information, read the EEPROM to determine how many bits of address length - this EEPROM is in Words. - -Arguments: - AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. - -Returns: - RetVal - The word read from the EEPROM. - ---*/ -{ - UINT8 Tmp; - UINT8 AddrLen; - UINT32 EEAddr; - // - // assume 64word eeprom (so,6 bits of address_length) - // - UINT16 ReadCmd; - - EEAddr = AdapterInfo->ioaddr + SCBeeprom; - ReadCmd = (EE_READ_CMD << 6); - - // - // get exclusive access to the eeprom first! - // - E100bSetEepromLockOut (AdapterInfo); - - // - // address we are trying to read is 0 - // eeprom control reg bits: x,x,x,x,DO,,DI,,CS,SK - // to write the opcode+data value out one bit at a time in DI starting at msb - // and then out a 1 to sk, wait, out 0 to SK and wait - // repeat this for all the bits to be written - // - Tmp = (UINT8) (InByte (AdapterInfo, EEAddr) & 0xF2); - - // - // enable eeprom access - // - OutByte (AdapterInfo, (UINT8) (Tmp | EE_CS), EEAddr); - - // - // 3 for opcode, 6 for the default address len - // - shift_bits_out (AdapterInfo, ReadCmd, (UINT8) (3 + 6)); - - // - // (in case of a 64 word eeprom). - // read the "dummy zero" from EE_DO to say that the address we wrote - // (six 0s) is accepted, write more zeros (until 8) to get a "dummy zero" - // - - // - // assume the smallest - // - AddrLen = 6; - Tmp = InByte (AdapterInfo, EEAddr); - while ((AddrLen < 8) && ((Tmp & EE_DO) != 0)) { - OutByte (AdapterInfo, (UINT8) (Tmp &~EE_DI), EEAddr); - eeprom_delay (100); - - // - // raise the eeprom clock - // - OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr); - eeprom_delay (150); - - // - // lower the eeprom clock - // - OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr); - eeprom_delay (150); - Tmp = InByte (AdapterInfo, EEAddr); - AddrLen++; - } - - // - // read the eeprom word, even though we don't need this - // - shift_bits_in (AdapterInfo); - - // - // Terminate the EEPROM access. - // - Tmp = InByte (AdapterInfo, EEAddr); - Tmp &= ~(EE_CS | EE_DI); - OutByte (AdapterInfo, Tmp, EEAddr); - - // - // raise the clock and lower the eeprom shift clock - // - OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr); - eeprom_delay (100); - - OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr); - eeprom_delay (100); - - // - // giveup access to the eeprom! - // - E100bReSetEepromLockOut (AdapterInfo); - - return AddrLen; -} - -UINTN -E100bStatistics ( - NIC_DATA_INSTANCE *AdapterInfo, - UINT64 DBaddr, - UINT16 DBsize - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - DBaddr - TODO: add argument description - DBsize - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - PXE_DB_STATISTICS db; - // - // wait upto one second (each wait is 100 micro s) - // - UINT32 Wait; - Wait = 10000; - wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); - - // - // Clear statistics done marker. - // - AdapterInfo->statistics->done_marker = 0; - - // - // Issue statistics dump (or dump w/ reset) command. - // - OutByte ( - AdapterInfo, - (UINT8) (DBsize ? CU_SHOWSTATS : CU_DUMPSTATS), - (UINT32) (AdapterInfo->ioaddr + SCBCmd) - ); - - // - // Wait for command to complete. - // - // zero the db here just to chew up a little more time. - // - - ZeroMem ((VOID *) &db, sizeof db); - - while (Wait != 0) { - // - // Wait a bit before checking. - // - - DelayIt (AdapterInfo, 100); - - // - // Look for done marker at end of statistics. - // - - switch (AdapterInfo->statistics->done_marker) { - case 0xA005: - case 0xA007: - break; - - default: - Wait--; - continue; - } - - // - // if we did not "continue" from the above switch, we are done, - // - break; - } - - // - // If this is a reset, we are out of here! - // - if (DBsize == 0) { - return PXE_STATCODE_SUCCESS; - } - - // - // Convert NIC statistics counter format to EFI/UNDI - // specification statistics counter format. - // - - // - // 54 3210 fedc ba98 7654 3210 - // db.Supported = 01 0000 0100 1101 0001 0111; - // - db.Supported = 0x104D17; - - // - // Statistics from the NIC - // - - db.Data[0x01] = AdapterInfo->statistics->rx_good_frames; - - db.Data[0x02] = AdapterInfo->statistics->rx_runt_errs; - - db.Data[0x08] = AdapterInfo->statistics->rx_crc_errs + - AdapterInfo->statistics->rx_align_errs; - - db.Data[0x04] = db.Data[0x02] + - db.Data[0x08] + - AdapterInfo->statistics->rx_resource_errs + - AdapterInfo->statistics->rx_overrun_errs; - - db.Data[0x00] = db.Data[0x01] + db.Data[0x04]; - - db.Data[0x0B] = AdapterInfo->statistics->tx_good_frames; - - db.Data[0x0E] = AdapterInfo->statistics->tx_coll16_errs + - AdapterInfo->statistics->tx_late_colls + - AdapterInfo->statistics->tx_underruns + - AdapterInfo->statistics->tx_one_colls + - AdapterInfo->statistics->tx_multi_colls; - - db.Data[0x14] = AdapterInfo->statistics->tx_total_colls; - - db.Data[0x0A] = db.Data[0x0B] + - db.Data[0x0E] + - AdapterInfo->statistics->tx_lost_carrier; - - if (DBsize > sizeof db) { - DBsize = sizeof db; - } - - CopyMem ((VOID *) (UINTN) DBaddr, (VOID *) &db, (UINTN) DBsize); - - return PXE_STATCODE_SUCCESS; -} - -UINTN -E100bReset ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN INT32 OpFlags - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - OpFlags - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - - UINT16 save_filter; - // - // disable the interrupts - // - OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd); - - // - // wait for the tx queue to complete - // - CheckCBList (AdapterInfo); - - XmitWaitForCompletion (AdapterInfo); - - if (AdapterInfo->Receive_Started) { - StopRU (AdapterInfo); - } - - InitializeChip (AdapterInfo); - - // - // check the opflags and restart receive filters - // - if ((OpFlags & PXE_OPFLAGS_RESET_DISABLE_FILTERS) == 0) { - - save_filter = AdapterInfo->Rx_Filter; - // - // if we give the filter same as Rx_Filter, - // this routine will not set mcast list (it thinks there is no change) - // to force it, we will reset that flag in the Rx_Filter - // - AdapterInfo->Rx_Filter &= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST); - E100bSetfilter (AdapterInfo, save_filter, (UINT64) 0, (UINT32) 0); - } - - if ((OpFlags & PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) != 0) { - // - // disable the interrupts - // - AdapterInfo->int_mask = 0; - } - // - // else leave the interrupt in the pre-set state!!! - // - E100bSetInterruptState (AdapterInfo); - - return 0; -} - -UINTN -E100bShutdown ( - IN NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - // - // disable the interrupts - // - OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd); - - // - // stop the receive unit - // - if (AdapterInfo->Receive_Started) { - StopRU (AdapterInfo); - } - - // - // wait for the tx queue to complete - // - CheckCBList (AdapterInfo); - if (AdapterInfo->FreeCBCount != AdapterInfo->TxBufCnt) { - wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); - } - - // - // we do not want to reset the phy, it takes a long time to renegotiate the - // link after that (3-4 seconds) - // - InitializeChip (AdapterInfo); - SelectiveReset (AdapterInfo); - return 0; -} - -VOID -MdiWrite ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN UINT8 RegAddress, - IN UINT8 PhyAddress, - IN UINT16 DataValue - ) -/*++ - -Routine Description: - This routine will write a value to the specified MII register - of an external MDI compliant device (e.g. PHY 100). The command will - execute in polled mode. - -Arguments: - AdapterInfo - pointer to the structure that contains the NIC's context. - RegAddress - The MII register that we are writing to - PhyAddress - The MDI address of the Phy component. - DataValue - The value that we are writing to the MII register. - -Returns: - nothing ---*/ -{ - UINT32 WriteCommand; - - WriteCommand = ((UINT32) DataValue) | - ((UINT32)(RegAddress << 16)) | - ((UINT32)(PhyAddress << 21)) | - ((UINT32)(MDI_WRITE << 26)); - - // - // Issue the write command to the MDI control register. - // - OutLong (AdapterInfo, WriteCommand, AdapterInfo->ioaddr + SCBCtrlMDI); - - // - // wait 20usec before checking status - // - DelayIt (AdapterInfo, 20); - - // - // poll for the mdi write to complete - while ((InLong (AdapterInfo, AdapterInfo->ioaddr + SCBCtrlMDI) & - MDI_PHY_READY) == 0){ - DelayIt (AdapterInfo, 20); - } -} - -VOID -MdiRead ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN UINT8 RegAddress, - IN UINT8 PhyAddress, - IN OUT UINT16 *DataValue - ) -/*++ - -Routine Description: - This routine will read a value from the specified MII register - of an external MDI compliant device (e.g. PHY 100), and return - it to the calling routine. The command will execute in polled mode. - -Arguments: - AdapterInfo - pointer to the structure that contains the NIC's context. - RegAddress - The MII register that we are reading from - PhyAddress - The MDI address of the Phy component. - DataValue - pointer to the value that we read from the MII register. - -Returns: - ---*/ -{ - UINT32 ReadCommand; - - ReadCommand = ((UINT32) (RegAddress << 16)) | - ((UINT32) (PhyAddress << 21)) | - ((UINT32) (MDI_READ << 26)); - - // - // Issue the read command to the MDI control register. - // - OutLong (AdapterInfo, ReadCommand, AdapterInfo->ioaddr + SCBCtrlMDI); - - // - // wait 20usec before checking status - // - DelayIt (AdapterInfo, 20); - - // - // poll for the mdi read to complete - // - while ((InLong (AdapterInfo, AdapterInfo->ioaddr + SCBCtrlMDI) & - MDI_PHY_READY) == 0) { - DelayIt (AdapterInfo, 20); - - } - - *DataValue = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBCtrlMDI); -} - -VOID -PhyReset ( - NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - This routine will reset the PHY that the adapter is currently - configured to use. - -Arguments: - AdapterInfo - pointer to the structure that contains the NIC's context. - -Returns: - ---*/ -{ - UINT16 MdiControlReg; - - MdiControlReg = (MDI_CR_AUTO_SELECT | - MDI_CR_RESTART_AUTO_NEG | - MDI_CR_RESET); - - // - // Write the MDI control register with our new Phy configuration - // - MdiWrite ( - AdapterInfo, - MDI_CONTROL_REG, - AdapterInfo->PhyAddress, - MdiControlReg - ); - - return ; -} - -BOOLEAN -PhyDetect ( - NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - This routine will detect what phy we are using, set the line - speed, FDX or HDX, and configure the phy if necessary. - - The following combinations are supported: - - TX or T4 PHY alone at PHY address 1 - - T4 or TX PHY at address 1 and MII PHY at address 0 - - 82503 alone (10Base-T mode, no full duplex support) - - 82503 and MII PHY (TX or T4) at address 0 - - The sequence / priority of detection is as follows: - - PHY 1 with cable termination - - PHY 0 with cable termination - - PHY 1 (if found) without cable termination - - 503 interface - - Additionally auto-negotiation capable (NWAY) and parallel - detection PHYs are supported. The flow-chart is described in - the 82557 software writer's manual. - - NOTE: 1. All PHY MDI registers are read in polled mode. - 2. The routines assume that the 82557 has been RESET and we have - obtained the virtual memory address of the CSR. - 3. PhyDetect will not RESET the PHY. - 4. If FORCEFDX is set, SPEED should also be set. The driver will - check the values for inconsistency with the detected PHY - technology. - 5. PHY 1 (the PHY on the adapter) may have an address in the range - 1 through 31 inclusive. The driver will accept addresses in - this range. - 6. Driver ignores FORCEFDX and SPEED overrides if a 503 interface - is detected. - -Arguments: - AdapterInfo - pointer to the structure that contains the NIC's context. - -Returns: - TRUE - If a Phy was detected, and configured correctly. - FALSE - If a valid phy could not be detected and configured. - ---*/ -{ - UINT16 *eedata; - UINT16 MdiControlReg; - UINT16 MdiStatusReg; - BOOLEAN FoundPhy1; - UINT8 ReNegotiateTime; - - eedata = (UINT16 *) (&AdapterInfo->NVData[0]); - - FoundPhy1 = FALSE; - ReNegotiateTime = 35; - // - // EEPROM word [6] contains the Primary PHY record in which the least 3 bits - // indicate the PHY address - // and word [7] contains the secondary PHY record - // - AdapterInfo->PhyRecord[0] = eedata[6]; - AdapterInfo->PhyRecord[1] = eedata[7]; - AdapterInfo->PhyAddress = (UINT8) (AdapterInfo->PhyRecord[0] & 7); - - // - // Check for a phy address over-ride of 32 which indicates force use of 82503 - // not detecting the link in this case - // - if (AdapterInfo->PhyAddress == 32) { - // - // 503 interface over-ride - // Record the current speed and duplex. We will be in half duplex - // mode unless the user used the force full duplex over-ride. - // - AdapterInfo->LinkSpeed = 10; - return (TRUE); - } - - // - // If the Phy Address is between 1-31 then we must first look for phy 1, - // at that address. - // - if ((AdapterInfo->PhyAddress > 0) && (AdapterInfo->PhyAddress < 32)) { - - // - // Read the MDI control and status registers at phy 1 - // and check if we found a valid phy - // - MdiRead ( - AdapterInfo, - MDI_CONTROL_REG, - AdapterInfo->PhyAddress, - &MdiControlReg - ); - - MdiRead ( - AdapterInfo, - MDI_STATUS_REG, - AdapterInfo->PhyAddress, - &MdiStatusReg - ); - - if (!((MdiControlReg == 0xffff) || - ((MdiStatusReg == 0) && (MdiControlReg == 0)))) { - - // - // we have a valid phy1 - // Read the status register again because of sticky bits - // - FoundPhy1 = TRUE; - MdiRead ( - AdapterInfo, - MDI_STATUS_REG, - AdapterInfo->PhyAddress, - &MdiStatusReg - ); - - // - // If there is a valid link then use this Phy. - // - if (MdiStatusReg & MDI_SR_LINK_STATUS) { - return (SetupPhy(AdapterInfo)); - } - } - } - - // - // Next try to detect a PHY at address 0x00 because there was no Phy 1, - // or Phy 1 didn't have link, or we had a phy 0 over-ride - // - - // - // Read the MDI control and status registers at phy 0 - // - MdiRead (AdapterInfo, MDI_CONTROL_REG, 0, &MdiControlReg); - MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg); - - // - // check if we found a valid phy 0 - // - if (((MdiControlReg == 0xffff) || - ((MdiStatusReg == 0) && (MdiControlReg == 0)))) { - - // - // we don't have a valid phy at address 0 - // if phy address was forced to 0, then error out because we - // didn't find a phy at that address - // - if (AdapterInfo->PhyAddress == 0x0000) { - return (FALSE); - } else { - // - // at this point phy1 does not have link and there is no phy 0 at all - // if we are forced to detect the cable, error out here! - // - if (AdapterInfo->CableDetect != 0) { - return FALSE; - - } - - if (FoundPhy1) { - // - // no phy 0, but there is a phy 1 (no link I guess), so use phy 1 - // - return SetupPhy (AdapterInfo); - } else { - // - // didn't find phy 0 or phy 1, so assume a 503 interface - // - AdapterInfo->PhyAddress = 32; - - // - // Record the current speed and duplex. We'll be in half duplex - // mode unless the user used the force full duplex over-ride. - // - AdapterInfo->LinkSpeed = 10; - return (TRUE); - } - } - } else { - // - // We have a valid phy at address 0. If phy 0 has a link then we use - // phy 0. If Phy 0 doesn't have a link then we use Phy 1 (no link) - // if phy 1 is present, or phy 0 if phy 1 is not present - // If phy 1 was present, then we must isolate phy 1 before we enable - // phy 0 to see if Phy 0 has a link. - // - if (FoundPhy1) { - // - // isolate phy 1 - // - MdiWrite ( - AdapterInfo, - MDI_CONTROL_REG, - AdapterInfo->PhyAddress, - MDI_CR_ISOLATE - ); - - // - // wait 100 microseconds for the phy to isolate. - // - DelayIt (AdapterInfo, 100); - } - - // - // Since this Phy is at address 0, we must enable it. So clear - // the isolate bit, and set the auto-speed select bit - // - MdiWrite ( - AdapterInfo, - MDI_CONTROL_REG, - 0, - MDI_CR_AUTO_SELECT - ); - - // - // wait 100 microseconds for the phy to be enabled. - // - DelayIt (AdapterInfo, 100); - - // - // restart the auto-negotion process - // - MdiWrite ( - AdapterInfo, - MDI_CONTROL_REG, - 0, - MDI_CR_RESTART_AUTO_NEG | MDI_CR_AUTO_SELECT - ); - - // - // wait no more than 3.5 seconds for auto-negotiation to complete - // - while (ReNegotiateTime) { - // - // Read the status register twice because of sticky bits - // - MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg); - MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg); - - if (MdiStatusReg & MDI_SR_AUTO_NEG_COMPLETE) { - break; - } - - DelayIt (AdapterInfo, 100); - ReNegotiateTime--; - } - - // - // Read the status register again because of sticky bits - // - MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg); - - // - // If the link was not set - // - if ((MdiStatusReg & MDI_SR_LINK_STATUS) == 0) { - // - // PHY1 does not have a link and phy 0 does not have a link - // do not proceed if we need to detect the link! - // - if (AdapterInfo->CableDetect != 0) { - return FALSE; - } - - // - // the link wasn't set, so use phy 1 if phy 1 was present - // - if (FoundPhy1) { - // - // isolate phy 0 - // - MdiWrite (AdapterInfo, MDI_CONTROL_REG, 0, MDI_CR_ISOLATE); - - // - // wait 100 microseconds for the phy to isolate. - // - DelayIt (AdapterInfo, 100); - - // - // Now re-enable PHY 1 - // - MdiWrite ( - AdapterInfo, - MDI_CONTROL_REG, - AdapterInfo->PhyAddress, - MDI_CR_AUTO_SELECT - ); - - // - // wait 100 microseconds for the phy to be enabled - // - DelayIt (AdapterInfo, 100); - - // - // restart the auto-negotion process - // - MdiWrite ( - AdapterInfo, - MDI_CONTROL_REG, - AdapterInfo->PhyAddress, - MDI_CR_RESTART_AUTO_NEG | MDI_CR_AUTO_SELECT - ); - - // - // Don't wait for it to complete (we didn't have link earlier) - // - return (SetupPhy (AdapterInfo)); - } - } - - // - // Definitely using Phy 0 - // - AdapterInfo->PhyAddress = 0; - return (SetupPhy(AdapterInfo)); - } -} - -BOOLEAN -SetupPhy ( - IN NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - This routine will setup phy 1 or phy 0 so that it is configured - to match a speed and duplex over-ride option. If speed or - duplex mode is not explicitly specified in the registry, the - driver will skip the speed and duplex over-ride code, and - assume the adapter is automatically setting the line speed, and - the duplex mode. At the end of this routine, any truly Phy - specific code will be executed (each Phy has its own quirks, - and some require that certain special bits are set). - - NOTE: The driver assumes that SPEED and FORCEFDX are specified at the - same time. If FORCEDPX is set without speed being set, the driver - will encouter a fatal error and log a message into the event viewer. - -Arguments: - AdapterInfo - pointer to the structure that contains the NIC's context. - -Returns: - TRUE - If the phy could be configured correctly - FALSE - If the phy couldn't be configured correctly, because an - unsupported over-ride option was used - ---*/ -{ - UINT16 MdiControlReg; - UINT16 MdiStatusReg; - UINT16 MdiIdLowReg; - UINT16 MdiIdHighReg; - UINT16 MdiMiscReg; - UINT32 PhyId; - BOOLEAN ForcePhySetting; - - ForcePhySetting = FALSE; - - // - // If we are NOT forcing a setting for line speed or full duplex, then - // we won't force a link setting, and we'll jump down to the phy - // specific code. - // - if (((AdapterInfo->LinkSpeedReq) || (AdapterInfo->DuplexReq))) { - // - // Find out what kind of technology this Phy is capable of. - // - MdiRead ( - AdapterInfo, - MDI_STATUS_REG, - AdapterInfo->PhyAddress, - &MdiStatusReg - ); - - // - // Read the MDI control register at our phy - // - MdiRead ( - AdapterInfo, - MDI_CONTROL_REG, - AdapterInfo->PhyAddress, - &MdiControlReg - ); - - // - // Now check the validity of our forced option. If the force option is - // valid, then force the setting. If the force option is not valid, - // we'll set a flag indicating that we should error out. - // - - // - // If speed is forced to 10mb - // - if (AdapterInfo->LinkSpeedReq == 10) { - // - // If half duplex is forced - // - if ((AdapterInfo->DuplexReq & PXE_FORCE_HALF_DUPLEX) != 0) { - if (MdiStatusReg & MDI_SR_10T_HALF_DPX) { - - MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF); - ForcePhySetting = TRUE; - } - } else if ((AdapterInfo->DuplexReq & PXE_FORCE_FULL_DUPLEX) != 0) { - - // - // If full duplex is forced - // - if (MdiStatusReg & MDI_SR_10T_FULL_DPX) { - - MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT); - MdiControlReg |= MDI_CR_FULL_HALF; - ForcePhySetting = TRUE; - } - } else { - // - // If auto duplex (we actually set phy to 1/2) - // - if (MdiStatusReg & (MDI_SR_10T_FULL_DPX | MDI_SR_10T_HALF_DPX)) { - - MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF); - ForcePhySetting = TRUE; - } - } - } - - // - // If speed is forced to 100mb - // - else if (AdapterInfo->LinkSpeedReq == 100) { - // - // If half duplex is forced - // - if ((AdapterInfo->DuplexReq & PXE_FORCE_HALF_DUPLEX) != 0) { - if (MdiStatusReg & (MDI_SR_TX_HALF_DPX | MDI_SR_T4_CAPABLE)) { - - MdiControlReg &= ~(MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF); - MdiControlReg |= MDI_CR_10_100; - ForcePhySetting = TRUE; - } - } else if ((AdapterInfo->DuplexReq & PXE_FORCE_FULL_DUPLEX) != 0) { - // - // If full duplex is forced - // - if (MdiStatusReg & MDI_SR_TX_FULL_DPX) { - MdiControlReg &= ~MDI_CR_AUTO_SELECT; - MdiControlReg |= (MDI_CR_10_100 | MDI_CR_FULL_HALF); - ForcePhySetting = TRUE; - } - } else { - // - // If auto duplex (we set phy to 1/2) - // - if (MdiStatusReg & (MDI_SR_TX_HALF_DPX | MDI_SR_T4_CAPABLE)) { - - MdiControlReg &= ~(MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF); - MdiControlReg |= MDI_CR_10_100; - ForcePhySetting = TRUE; - } - } - } - - if (!ForcePhySetting) { - return (FALSE); - } - - // - // Write the MDI control register with our new Phy configuration - // - MdiWrite ( - AdapterInfo, - MDI_CONTROL_REG, - AdapterInfo->PhyAddress, - MdiControlReg - ); - - // - // wait 100 milliseconds for auto-negotiation to complete - // - DelayIt (AdapterInfo, 100); - } - - // - // Find out specifically what Phy this is. We do this because for certain - // phys there are specific bits that must be set so that the phy and the - // 82557 work together properly. - // - - MdiRead ( - AdapterInfo, - PHY_ID_REG_1, - AdapterInfo->PhyAddress, - &MdiIdLowReg - ); - MdiRead ( - AdapterInfo, - PHY_ID_REG_2, - AdapterInfo->PhyAddress, - &MdiIdHighReg - ); - - PhyId = ((UINT32) MdiIdLowReg | ((UINT32) MdiIdHighReg << 16)); - - // - // And out the revsion field of the Phy ID so that we'll be able to detect - // future revs of the same Phy. - // - PhyId &= PHY_MODEL_REV_ID_MASK; - - // - // Handle the National TX - // - if (PhyId == PHY_NSC_TX) { - - MdiRead ( - AdapterInfo, - NSC_CONG_CONTROL_REG, - AdapterInfo->PhyAddress, - &MdiMiscReg - ); - - MdiMiscReg |= (NSC_TX_CONG_TXREADY | NSC_TX_CONG_F_CONNECT); - - MdiWrite ( - AdapterInfo, - NSC_CONG_CONTROL_REG, - AdapterInfo->PhyAddress, - MdiMiscReg - ); - } - - FindPhySpeedAndDpx (AdapterInfo, PhyId); - - // - // We put a hardware fix on to our adapters to work-around the PHY_100 errata - // described below. The following code is only compiled in, if we wanted - // to attempt a software workaround to the PHY_100 A/B step problem. - // - - return (TRUE); -} - -VOID -FindPhySpeedAndDpx ( - IN NIC_DATA_INSTANCE *AdapterInfo, - IN UINT32 PhyId - ) -/*++ - -Routine Description: - This routine will figure out what line speed and duplex mode - the PHY is currently using. - -Arguments: - AdapterInfo - pointer to the structure that contains the NIC's context. - PhyId - The ID of the PHY in question. - -Returns: - NOTHING ---*/ -{ - UINT16 MdiStatusReg; - UINT16 MdiMiscReg; - UINT16 MdiOwnAdReg; - UINT16 MdiLinkPartnerAdReg; - - // - // If there was a speed and/or duplex override, then set our current - // value accordingly - // - AdapterInfo->LinkSpeed = AdapterInfo->LinkSpeedReq; - AdapterInfo->Duplex = (UINT8) ((AdapterInfo->DuplexReq & PXE_FORCE_FULL_DUPLEX) ? - FULL_DUPLEX : HALF_DUPLEX); - - // - // If speed and duplex were forced, then we know our current settings, so - // we'll just return. Otherwise, we'll need to figure out what NWAY set - // us to. - // - if (AdapterInfo->LinkSpeed && AdapterInfo->Duplex) { - return ; - - } - // - // If we didn't have a valid link, then we'll assume that our current - // speed is 10mb half-duplex. - // - - // - // Read the status register twice because of sticky bits - // - MdiRead ( - AdapterInfo, - MDI_STATUS_REG, - AdapterInfo->PhyAddress, - &MdiStatusReg - ); - MdiRead ( - AdapterInfo, - MDI_STATUS_REG, - AdapterInfo->PhyAddress, - &MdiStatusReg - ); - - // - // If there wasn't a valid link then use default speed & duplex - // - if (!(MdiStatusReg & MDI_SR_LINK_STATUS)) { - - AdapterInfo->LinkSpeed = 10; - AdapterInfo->Duplex = HALF_DUPLEX; - return ; - } - - // - // If this is an Intel PHY (a T4 PHY_100 or a TX PHY_TX), then read bits - // 1 and 0 of extended register 0, to get the current speed and duplex - // settings. - // - if ((PhyId == PHY_100_A) || (PhyId == PHY_100_C) || (PhyId == PHY_TX_ID)) { - // - // Read extended register 0 - // - MdiRead ( - AdapterInfo, - EXTENDED_REG_0, - AdapterInfo->PhyAddress, - &MdiMiscReg - ); - - // - // Get current speed setting - // - if (MdiMiscReg & PHY_100_ER0_SPEED_INDIC) { - AdapterInfo->LinkSpeed = 100; - } else { - AdapterInfo->LinkSpeed = 10; - } - - // - // Get current duplex setting -- if bit is set then FDX is enabled - // - if (MdiMiscReg & PHY_100_ER0_FDX_INDIC) { - AdapterInfo->Duplex = FULL_DUPLEX; - } else { - AdapterInfo->Duplex = HALF_DUPLEX; - } - - return ; - } - // - // Read our link partner's advertisement register - // - MdiRead ( - AdapterInfo, - AUTO_NEG_LINK_PARTNER_REG, - AdapterInfo->PhyAddress, - &MdiLinkPartnerAdReg - ); - - // - // See if Auto-Negotiation was complete (bit 5, reg 1) - // - MdiRead ( - AdapterInfo, - MDI_STATUS_REG, - AdapterInfo->PhyAddress, - &MdiStatusReg - ); - - // - // If a True NWAY connection was made, then we can detect speed/duplex by - // ANDing our adapter's advertised abilities with our link partner's - // advertised ablilities, and then assuming that the highest common - // denominator was chosed by NWAY. - // - if ((MdiLinkPartnerAdReg & NWAY_LP_ABILITY) && - (MdiStatusReg & MDI_SR_AUTO_NEG_COMPLETE)) { - - // - // Read our advertisement register - // - MdiRead ( - AdapterInfo, - AUTO_NEG_ADVERTISE_REG, - AdapterInfo->PhyAddress, - &MdiOwnAdReg - ); - - // - // AND the two advertisement registers together, and get rid of any - // extraneous bits. - // - MdiOwnAdReg = (UINT16) (MdiOwnAdReg & (MdiLinkPartnerAdReg & NWAY_LP_ABILITY)); - - // - // Get speed setting - // - if (MdiOwnAdReg & (NWAY_AD_TX_HALF_DPX | NWAY_AD_TX_FULL_DPX | NWAY_AD_T4_CAPABLE)) { - AdapterInfo->LinkSpeed = 100; - } else { - AdapterInfo->LinkSpeed = 10; - } - - // - // Get duplex setting -- use priority resolution algorithm - // - if (MdiOwnAdReg & (NWAY_AD_T4_CAPABLE)) { - AdapterInfo->Duplex = HALF_DUPLEX; - return ; - } else if (MdiOwnAdReg & (NWAY_AD_TX_FULL_DPX)) { - AdapterInfo->Duplex = FULL_DUPLEX; - return ; - } else if (MdiOwnAdReg & (NWAY_AD_TX_HALF_DPX)) { - AdapterInfo->Duplex = HALF_DUPLEX; - return ; - } else if (MdiOwnAdReg & (NWAY_AD_10T_FULL_DPX)) { - AdapterInfo->Duplex = FULL_DUPLEX; - return ; - } else { - AdapterInfo->Duplex = HALF_DUPLEX; - return ; - } - } - - // - // If we are connected to a dumb (non-NWAY) repeater or hub, and the line - // speed was determined automatically by parallel detection, then we have - // no way of knowing exactly what speed the PHY is set to unless that PHY - // has a propietary register which indicates speed in this situation. The - // NSC TX PHY does have such a register. Also, since NWAY didn't establish - // the connection, the duplex setting should HALF duplex. - // - AdapterInfo->Duplex = HALF_DUPLEX; - - if (PhyId == PHY_NSC_TX) { - // - // Read register 25 to get the SPEED_10 bit - // - MdiRead ( - AdapterInfo, - NSC_SPEED_IND_REG, - AdapterInfo->PhyAddress, - &MdiMiscReg - ); - - // - // If bit 6 was set then we're at 10mb - // - if (MdiMiscReg & NSC_TX_SPD_INDC_SPEED) { - AdapterInfo->LinkSpeed = 10; - } else { - AdapterInfo->LinkSpeed = 100; - } - } - - // - // If we don't know what line speed we are set at, then we'll default to - // 10mbs - // - else { - AdapterInfo->LinkSpeed = 10; - } -} - -VOID -XmitWaitForCompletion ( - NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - TxCB *TxPtr; - - if (AdapterInfo->FreeCBCount == AdapterInfo->TxBufCnt) { - return ; - } - - // - // used xmit cb list starts right after the free tail (ends before the - // free head ptr) - // - TxPtr = AdapterInfo->FreeTxTailPtr->NextTCBVirtualLinkPtr; - while (TxPtr != AdapterInfo->FreeTxHeadPtr) { - CommandWaitForCompletion (TxPtr, AdapterInfo); - SetFreeCB (AdapterInfo, TxPtr); - TxPtr = TxPtr->NextTCBVirtualLinkPtr; - } -} - -INT8 -CommandWaitForCompletion ( - TxCB *cmd_ptr, - NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - cmd_ptr - TODO: add argument description - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - INT16 wait; - wait = 5000; - while ((cmd_ptr->cb_header.status == 0) && (--wait > 0)) { - DelayIt (AdapterInfo, 10); - } - - if (cmd_ptr->cb_header.status == 0) { - return -1; - } - - return 0; -} - -STATIC -INT8 -SoftwareReset ( - NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - UINT8 tco_stat; - UINT16 wait; - - tco_stat = 0; - - // - // Reset the chip: stop Tx and Rx processes and clear counters. - // This takes less than 10usec and will easily finish before the next - // action. - // - - OutLong (AdapterInfo, PORT_RESET, AdapterInfo->ioaddr + SCBPort); - // - // wait for 5 milli seconds here! - // - DelayIt (AdapterInfo, 5000); - // - // TCO Errata work around for 559s only - // ----------------------------------------------------------------------------------- - // TCO Workaround Code - // haifa workaround - // ----------------------------------------------------------------------------------- - // 1. Issue SW-RST ^^^ (already done above) - // 2. Issue a redundant Set CU Base CMD immediately - // Do not set the General Pointer before the Set CU Base cycle - // Do not check the SCB CMD before the Set CU Base cycle - // 3. Wait for the SCB-CMD to be cleared - // this indicates the transition to post-driver - // 4. Poll the TCO-Req bit in the PMDR to be cleared - // this indicates the tco activity has stopped for real - // 5. Proceed with the nominal Driver Init: - // Actual Set CU & RU Base ... - // - // Check for ICH2 device ID. If this is an ICH2, - // do the TCO workaround code. - // - if (AdapterInfo->VendorID == D102_DEVICE_ID || - AdapterInfo->VendorID == ICH3_DEVICE_ID_1 || - AdapterInfo->VendorID == ICH3_DEVICE_ID_2 || - AdapterInfo->VendorID == ICH3_DEVICE_ID_3 || - AdapterInfo->VendorID == ICH3_DEVICE_ID_4 || - AdapterInfo->VendorID == ICH3_DEVICE_ID_5 || - AdapterInfo->VendorID == ICH3_DEVICE_ID_6 || - AdapterInfo->VendorID == ICH3_DEVICE_ID_7 || - AdapterInfo->VendorID == ICH3_DEVICE_ID_8 || - AdapterInfo->RevID >= 8) { // do the TCO fix - // - // donot load the scb pointer but just give load_cu cmd. - // - OutByte (AdapterInfo, CU_CMD_BASE, AdapterInfo->ioaddr + SCBCmd); - // - // wait for command to be accepted. - // - wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); - // - // read PMDR register and check bit 1 in it to see if TCO is active - // - - // - // wait for 5 milli seconds - // - wait = 5000; - while (wait) { - tco_stat = InByte (AdapterInfo, AdapterInfo->ioaddr + 0x1b); - if ((tco_stat & 2) == 0) { - // - // is the activity bit clear?? - // - break; - } - - wait--; - DelayIt (AdapterInfo, 1); - } - - if ((tco_stat & 2) != 0) { - // - // not zero?? - // - return -1; - } - } - - return 0; -} - -UINT8 -SelectiveReset ( - IN NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - UINT16 wait; - UINT32 stat; - - wait = 10; - stat = 0; - OutLong (AdapterInfo, POR_SELECTIVE_RESET, AdapterInfo->ioaddr + SCBPort); - // - // wait for this to complete - // - - // - // wait for 2 milli seconds here! - // - DelayIt (AdapterInfo, 2000); - while (wait > 0) { - wait--; - stat = InLong (AdapterInfo, AdapterInfo->ioaddr + SCBPort); - if (stat == 0) { - break; - } - - // - // wait for 1 milli second - // - DelayIt (AdapterInfo, 1000); - } - - if (stat != 0) { - return PXE_STATCODE_DEVICE_FAILURE; - } - - return 0; -} - -UINT16 -InitializeChip ( - IN NIC_DATA_INSTANCE *AdapterInfo - ) -/*++ - -Routine Description: - - TODO: Add function description - -Arguments: - - AdapterInfo - TODO: add argument description - -Returns: - - TODO: add return values - ---*/ -{ - UINT16 ret_val; - if (SoftwareReset (AdapterInfo) != 0) { - return PXE_STATCODE_DEVICE_FAILURE; - } - - // - // disable interrupts - // - OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd); - - // - // Load the base registers with 0s (we will give the complete address as - // offset later when we issue any command - // - if ((ret_val = Load_Base_Regs (AdapterInfo)) != 0) { - return ret_val; - } - - if ((ret_val = SetupCBlink (AdapterInfo)) != 0) { - return ret_val; - } - - if ((ret_val = SetupReceiveQueues (AdapterInfo)) != 0) { - return ret_val; - } - - // - // detect the PHY only if we need to detect the cable as requested by the - // initialize parameters - // - AdapterInfo->PhyAddress = 0xFF; - - if (AdapterInfo->CableDetect != 0) { - if (!PhyDetect (AdapterInfo)) { - return PXE_STATCODE_DEVICE_FAILURE; - } - } - - if ((ret_val = E100bSetupIAAddr (AdapterInfo)) != 0) { - return ret_val; - } - - if ((ret_val = Configure (AdapterInfo)) != 0) { - return ret_val; - } - - return 0; -}