From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/ndis/dc21x4/srom.c | 1521 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1521 insertions(+) create mode 100644 private/ntos/ndis/dc21x4/srom.c (limited to 'private/ntos/ndis/dc21x4/srom.c') diff --git a/private/ntos/ndis/dc21x4/srom.c b/private/ntos/ndis/dc21x4/srom.c new file mode 100644 index 000000000..85962f2c2 --- /dev/null +++ b/private/ntos/ndis/dc21x4/srom.c @@ -0,0 +1,1521 @@ +/*+ + * file: srom.c + * + * Copyright (C) 1992-1995 by + * Digital Equipment Corporation, Maynard, Massachusetts. + * All rights reserved. + * + * This software is furnished under a license and may be used and copied + * only in accordance of the terms of such license and with the + * inclusion of the above copyright notice. This software or any other + * copies thereof may not be provided or otherwise made available to any + * other person. No title to and ownership of the software is hereby + * transferred. + * + * The information in this software is subject to change without notice + * and should not be construed as a commitment by digital equipment + * corporation. + * + * Digital assumes no responsibility for the use or reliability of its + * software on equipment which is not supplied by digital. + * + * + * Abstract: This file contains the code to access the onboard ROM of + * adapters based on DEC's DC21X4 Ethernet Controller. + * + * Author: Philippe klein + * + * Revision History: + * + * 05-Oct-95 phk Modified Miniport version + * 10-Jan-95 phk Add ParseSRom + * 29-Nov-95 phk Add parsing for SROM format V3 + * +-*/ + +#include + +#define SROM_93LC46B_SIZE 64 //words +#define SROM_93LC46B_MAX_CYCLES 25 +#define SROM_93LC46B_ADDRESS_MSB 5 +#define SROM_93LC46B_DATA_MSB 15 +#define SROM_93LC46B_DATA_BIT 3 + +#define SROM_93LC46B_VALID_BITMASK 0x8 + +#define SROM_93LC46B_DELAY (10) + +#define CSR_READ 0x4000 +#define CSR_WRITE 0x2000 +#define SEL_SROM 0x0800 +#define DATA_1 0x0004 +#define DATA_0 0x0000 +#define CLK 0x0002 +#define CS 0x0001 + +#define DISABLE_AUTOSENSE 0x8000 + +#define EXT 0x40 +#define DC21X4_MEDIA 0x3F + + +#define MODE 0x0071 +#define SENSE_BN 0x000E +#define SENSE_DIS 0x8000 +#define DEFAULT 0x4000 +#define POLARITY 0x0080 + +#define SENSE_SHIFT 1 +#define MODE_SHIFT 18 + +#define SROM_LEGACY 0x00 +#define SROM_V1 0x01 +#define SROM_V2 0x02 +#define SROM_V3 0x03 + +#define SROM_SIZE (SROM_93LC46B_SIZE*2) + +#define SROM_IEEE_LEN 32 +#define TEST_PATTERN 0xAA5500FF +#define SROM_TIMEOUT 50 + +#define ZX312_SIGNATURE 0x0095C000 + +#define GET_MODE(_command) \ + ( (*(UNALIGNED ULONG *)(_command) & MODE) << MODE_SHIFT ) + +#define IF_DEFAULT_MEDIA(_command) \ + ( *(UNALIGNED ULONG *)(_command) & DEFAULT ) + +#define GET_POLARITY(_command) \ + ( (*(UNALIGNED ULONG *)(_command) & POLARITY) ? 0xffffffff : 0 ) + +#define GET_SENSE_MASK(_command) \ + ((*(UNALIGNED ULONG *)(_command) & SENSE_DIS) ? \ + 0 : (ULONG)(1 << ((*(UNALIGNED ULONG *)(_command) & SENSE_BN)>> SENSE_SHIFT ))) + +#pragma pack(1) +typedef struct _SROM_ID_BLOCK{ + + USHORT VendorID; + USHORT SysID; + USHORT Reserved[6]; + USHORT ID_Checksum; + UCHAR FormatVersion; + UCHAR AdapterCount; + UCHAR NetworkAddress[ETH_LENGTH_OF_ADDRESS]; + +} SROM_ID_BLOCK, *PSROM_ID_BLOCK; + +typedef struct _ADAPTER_ENTRIES{ + + UCHAR DeviceNumber; + USHORT Offset; + +} ADAPTER_ENTRIES, *PADAPTER_ENTRIES; + +#pragma pack() + +#define DE500_STR 0x1D +#define BOARD_SIGNATURE(_srom) \ + ((*(UNALIGNED ULONG *)&(_srom)[DE500_STR] == *(PULONG)&DE500Strng[0]) && \ + (*(UNALIGNED ULONG *)&(_srom)[DE500_STR+sizeof(ULONG)] == *(PULONG)&DE500Strng[sizeof(ULONG)])) + +// PHY Parsing definitions + +#define EXTENDED_FORMAT 0x80 + +#define LENGTH 0x7f +#define TYPE_0 0x0 +#define TYPE_1 0x1 +#define TYPE_2 0x2 +#define TYPE_3 0x3 + +#define MEDIA_CAPABILITIES_MASK 0xf800 +#define NWAY_ADVERTISEMENT_MASK 0x03e0 + + + + + + + + + + +#pragma NDIS_PAGABLE_FUNCTION(DC21X4ReadSerialRom) + +/*+ + * + * DC21X4ReadSerialRom + * + * Routine Description: + * + * Read the Dc21X4 Serial Rom to retrieve the adapter information + * + * Arguments: + * + * Adapter + * + * Return Value: + * + * Status + * + * +-*/ +extern +NDIS_STATUS +DC21X4ReadSerialRom ( + IN PDC21X4_ADAPTER Adapter + ) + +{ + UNALIGNED UCHAR *EthAddress; + UCHAR IdProm[SROM_IEEE_LEN *2]; + + ULONG Value; + INT Time; + UINT i; + +#if __DBG + DbgPrint ("DC21X4ReadSerialROM\n"); +#endif + + //Read the Station Address + + switch (Adapter->AdapterType) { + + case NdisInterfacePci: + + // Read the Network Address from the PCI board ID ROM + // through DC21X4's Serial ROM port + + switch (Adapter->DeviceId) { + + default: + + return DC21X4ParseSRom(Adapter); + + case DC21040_CFID: + + Adapter->MediaCapable = + (MEDIUM_10BT | MEDIUM_10B2 | MEDIUM_10B5); + + //Initialize DC21040s ID_PROM pointer + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + 0 + ); + + // Read the 32 bytes of the Ethernet ID PROM + + for (i = 0; i < SROM_IEEE_LEN; i++) { + + Time = SROM_TIMEOUT; + + do { + NdisStallExecution(1*MILLISECOND); // Wait 1 ms + DC21X4_READ_PORT( + DC21X4_IDPROM, + &Value + ); + } + while ((Value & DC21X4_IDPROM_DATA_UNVALID) && ((Time--)>0)); + if (Time > 0) { + IdProm[i] = (UCHAR)(Value & DC21X4_IDPROM_DATA); + } + else { + return NDIS_STATUS_FAILURE; + } + } + + EthAddress = &IdProm[0]; + + } + break; + + case NdisInterfaceEisa: + + Adapter->MediaCapable = + (MEDIUM_10BT | MEDIUM_10B2 | MEDIUM_10B5); + + // Read the 32 bytes of the Ethernet ID PROM + + for (i = 0; i < SROM_IEEE_LEN; i++) { + + NdisRawReadPortUchar( + Adapter->PortOffset + EISA_ID_PROM_OFFSET, + &IdProm[i] + ); +#if __DBG + DbgPrint ("Eisa: IDROM @%x %x r\n", + Adapter->PortOffset + EISA_ID_PROM_OFFSET, IdProm[i]); +#endif + } + + // Duplicate the ID Prom data in the 32 upper bytes of + // the array to cover the case where the 2 test patterns + // rap around the 32 bytes block + + MOVE_MEMORY ( + &IdProm[SROM_IEEE_LEN], + &IdProm[0], + SROM_IEEE_LEN + ); + + //Align on the test patterns + + for (i=4; i <= SROM_IEEE_LEN*2; i++) { + + if ( (*(UNALIGNED ULONG *)&IdProm[i-4] == TEST_PATTERN) && + (*(UNALIGNED ULONG *)&IdProm[i] == TEST_PATTERN) + ) break; + } + + if ( i >= SROM_IEEE_LEN ) { + // The test patterns were not found + Adapter->PermanentAddressValid = FALSE; + return NDIS_STATUS_SUCCESS; + } + else { + EthAddress = &IdProm[i+4]; + } + + break; + + } + + if (IS_NULL_ADDRESS(EthAddress)) { + Adapter->PermanentAddressValid = FALSE; +#if __DBG + DbgPrint ("SROM: NULL Burnt_In Ethernet Address\n"); +#endif + } + else if ((*(PULONG)EthAddress & 0xFFFFFF) == ZX312_SIGNATURE) { + // Zynx ZX312 Rev3's SROM does not contain a checksum + Adapter->PermanentAddressValid = TRUE; +#if __DBG + DbgPrint ("SROM: ZX312 Rev3\n"); +#endif + } + else { + Adapter->PermanentAddressValid = + VerifyChecksum(EthAddress); +#if __DBG + if (!Adapter->PermanentAddressValid) + DbgPrint ("SROM: Invalid CheckSum\n"); +#endif + } + + if (Adapter->PermanentAddressValid) { + MOVE_MEMORY ( + &Adapter->PermanentNetworkAddress[0], + EthAddress, + ETH_LENGTH_OF_ADDRESS + ); + } + + + //Sia values + + Adapter->Media[Medium10BaseT].SiaRegister[0] = DC21040_SIA0_10BT; + Adapter->Media[Medium10BaseT].SiaRegister[1] = DC21040_SIA1_10BT; + Adapter->Media[Medium10BaseT].SiaRegister[2] = DC21040_SIA2_10BT; + + Adapter->Media[Medium10Base2].SiaRegister[0] = DC21040_SIA0_10B2; + Adapter->Media[Medium10Base2].SiaRegister[1] = DC21040_SIA1_10B2; + Adapter->Media[Medium10Base2].SiaRegister[2] = DC21040_SIA2_10B2; + + Adapter->Media[Medium10Base5].SiaRegister[0] = DC21040_SIA0_10B5; + Adapter->Media[Medium10Base5].SiaRegister[1] = DC21040_SIA1_10B5; + Adapter->Media[Medium10Base5].SiaRegister[2] = DC21040_SIA2_10B5; + + return NDIS_STATUS_SUCCESS; + +} + + + + + + + + + + +#pragma NDIS_PAGABLE_FUNCTION(VerifyChecksum) + +/*+ + * + * VerifyChecksum + * + * Routine Description: + * + * Verify the checksum of an Ethernet Address + * + * Arguments: + * + * Adapter - The adapter which is being verified. + * + * EthAddress - A pointer to the address to be checked + * This 6_byte Ethernet address is followed + * by a zero byte, followed by a value such + * that the sum of a checksum on the Ethernet + * address and this value is 0xff. + * + * Return Value: + * + * TRUE if success + * +-*/ + + +BOOLEAN +VerifyChecksum( + IN UNALIGNED UCHAR *EthAddress + ) +{ + + UINT i; + UCHAR CheckSum[2]; + ULONG Sum = 0; + + // The checksum yields from the polynom: + // 10 2 9 8 + // (B[0]*2 + B[1]*2 + B[2]*2 + B[3]*2 + B[4]*2 + B[5]) mod (2**16-1) + + for (i=0; i<= 2; i++) { + + Sum *= 2; + + if (Sum > 0xffff) Sum -= 0xffff; + + Sum += (*(EthAddress+(2*i)) << 8) + *(EthAddress+(2*i)+1); + + if (Sum > 0xffff) Sum -= 0xffff; + } + + if (Sum >= 0xffff) { + Sum = 0; + } + + CheckSum[0] = (UCHAR)(Sum / 0x100); + CheckSum[1] = (UCHAR)(Sum % 0x100); + +#if __DBG + DbgPrint(" CheckSum = %02x %02x\n",CheckSum[0],CheckSum[1]); +#endif + return (*(UNALIGNED USHORT *)CheckSum == *(UNALIGNED USHORT *)(EthAddress + 6)) ; + +} + + + + + + + + + + +/*+ + * DC21X4ParseExtendedBlock + * + * Routine Description: + * + * This routine is called by the SROM Parser and takes care of the + * parsing of the info block with Extended format (EXT=1) in the 21140's + * info leaf. + * + * Arguments: + * + * Adapter - Pointer to the Data Structure + * MediaBlock - Pointer to the Serial Rom data. + * GeneralPurposeCtrl - Value of the General Purpose Ctrl + * + * Return Value: + * + * None + * +-*/ +extern +VOID +DC21X4ParseExtendedBlock( + IN PDC21X4_ADAPTER Adapter, + IN OUT UNALIGNED UCHAR **MediaBlock, + IN USHORT GeneralPurposeCtrl, + OUT PUCHAR PMediaCode + ) +{ + + UNALIGNED UCHAR *DataBytePtr; + UNALIGNED USHORT *DataWordPtr; + UNALIGNED UCHAR *EndOfBlock; + + UCHAR MediaCode; + + INT i; + INT PhyNumber; + UCHAR Length; + UCHAR Type; + USHORT External; + + DataBytePtr = (UNALIGNED CHAR *)(*MediaBlock); + + Length = (*(DataBytePtr++) & LENGTH); + EndOfBlock = DataBytePtr + Length; + + Type = *(DataBytePtr++); + +#if __DBG + DbgPrint("Block Length =%02x\n", Length); + DbgPrint("Block Type =%02x\n", Type); +#endif + + + switch (Type) { + + case TYPE_0: + + DC21X4ParseFixedBlock( + Adapter, + &DataBytePtr, + GeneralPurposeCtrl, + PMediaCode + ); + break; + + case TYPE_1: + case TYPE_3: + + PhyNumber = (INT) *(DataBytePtr++); + if (PhyNumber >= MAX_PHY_TABLE) { +#if __DBG + DbgPrint("PhyNumber =%02x Out of RANGE!!!\n", PhyNumber); +#endif + break; + } + + //General Purpose Control + Adapter->Phy[PhyNumber].GeneralPurposeCtrl = GeneralPurposeCtrl; + + //General Purpose Data + + Adapter->Phy[PhyNumber].GepSequenceLength = (INT) *(DataBytePtr++); + + if (Adapter->Phy[PhyNumber].GepSequenceLength > MAX_GPR_SEQUENCE) { +#if __DBG + DbgPrint("GepSequence =%02x Out of RANGE!!!\n", + Adapter->Phy[PhyNumber].GepSequenceLength ); +#endif + break; + } + + switch (Type) { + + case TYPE_1: + + //GepSequence Length in bytes + + for (i=0; i < Adapter->Phy[PhyNumber].GepSequenceLength; i++) { + Adapter->Phy[PhyNumber].GepSequence[i] = *(DataBytePtr++); + } + break; + + case TYPE_3: + + //GepSequence Length in words + + for (i=0; i < Adapter->Phy[PhyNumber].GepSequenceLength; i++) { + Adapter->Phy[PhyNumber].GepSequence[i] = *(UNALIGNED USHORT *)(DataBytePtr); + DataBytePtr += sizeof(USHORT); + } + break; + } + + // Reset sequence + + Adapter->Phy[PhyNumber].ResetSequenceLength = (INT) *(DataBytePtr++); + + if (Adapter->Phy[PhyNumber].ResetSequenceLength > MAX_RESET_SEQUENCE) { +#if __DBG + DbgPrint("ResetSequence =%02x Out of RANGE!!!\n", + Adapter->Phy[PhyNumber].ResetSequenceLength ); +#endif + break; + } + + for (i=0; i < Adapter->Phy[PhyNumber].ResetSequenceLength; i++) { + Adapter->Phy[PhyNumber].ResetSequence[i] = *(DataBytePtr++); + } + + // Capabilities,Nway,FullDuplex & TxmThreshold + + DataWordPtr = (UNALIGNED USHORT *) DataBytePtr; + + Adapter->Phy[PhyNumber].MediaCapabilities = + (*(DataWordPtr++) & MEDIA_CAPABILITIES_MASK); + Adapter->Phy[PhyNumber].NwayAdvertisement = + (*(DataWordPtr++) & NWAY_ADVERTISEMENT_MASK); + Adapter->Phy[PhyNumber].FullDuplexBits = + (*(DataWordPtr++) & MEDIA_CAPABILITIES_MASK); + Adapter->Phy[PhyNumber].TxThresholdModeBits = + (*(DataWordPtr++) & MEDIA_CAPABILITIES_MASK); + Adapter->Phy[PhyNumber].Present = TRUE; + + Adapter->PhyMediumInSrom = TRUE; + + DataBytePtr = (UNALIGNED UCHAR *) DataWordPtr; + + // GEP Interrupt + + switch (Type) { + + case TYPE_3: + + Adapter->Phy[PhyNumber].GepInterruptMask = + *(DataBytePtr++) << DC21X4_GEP_INTERRUPT_BIT_SHIFT; + break; + } + + +#if __DBG + DbgPrint("PHY Number= %02x\n", PhyNumber); + DbgPrint("GPR Sequence Length= %d\n", Adapter->Phy[PhyNumber].GepSequenceLength); + for (i=0; i < Adapter->Phy[PhyNumber].GepSequenceLength; i++) { + DbgPrint("GPR Sequence[%d]=%02x\n", i, Adapter->Phy[PhyNumber].GepSequence[i]); + } + DbgPrint("RESET Sequence Length= %d\n", Adapter->Phy[PhyNumber].ResetSequenceLength); + for (i=0; i < Adapter->Phy[PhyNumber].ResetSequenceLength; i++) { + DbgPrint("RESET Sequence[%d]=%02x\n", i, Adapter->Phy[PhyNumber].ResetSequence[i]); + } + DbgPrint("Media Capabilities= %04x\n", Adapter->Phy[PhyNumber].MediaCapabilities); + DbgPrint("NWAY Advertisement= %04x\n", Adapter->Phy[PhyNumber].NwayAdvertisement); + DbgPrint("FD Bit map= %02x\n",Adapter->Phy[PhyNumber].FullDuplexBits); + DbgPrint("TTM Bit map= %02x\n",Adapter->Phy[PhyNumber].TxThresholdModeBits); + DbgPrint("GEP Interrupt mask = %01x\n",Adapter->Phy[PhyNumber].GepInterruptMask); +#endif + + break; + + case TYPE_2: + + MediaCode = *(DataBytePtr) & DC21X4_MEDIA; + if (MediaCode >= MAX_MEDIA_TABLE) { + break; + } + Adapter->MediaCapable |= 1 << MediaCode; + External = *(DataBytePtr++) & EXT; +#if __DBG + DbgPrint("SRom: Media Code= %02x\n", MediaCode); + DbgPrint("SRom: Media Capable= %02x\n", Adapter->MediaCapable); +#endif + + DataWordPtr = (UNALIGNED USHORT *)DataBytePtr; + + if (External) { + + // EXT bit is set : + // overwrite the SIA Registers default values + // with the values stored into the SROM + + Adapter->Media[MediaCode].SiaRegister[0] = + ((ULONG)*(DataWordPtr++) & 0xFFFF); + Adapter->Media[MediaCode].SiaRegister[1] = + ((ULONG)*(DataWordPtr++) & 0xFFFF); + Adapter->Media[MediaCode].SiaRegister[2] = + ((ULONG)*(DataWordPtr++) & 0xFFFF); +#if __DBG + DbgPrint("SRom: EXT= 1:\n"); + DbgPrint("SRom: SiaReg[0]= %08x\n",Adapter->Media[MediaCode].SiaRegister[0]); + DbgPrint("SRom: SiaReg[1]= %08x\n",Adapter->Media[MediaCode].SiaRegister[1]); + DbgPrint("SRom: SiaReg[2]= %08x\n",Adapter->Media[MediaCode].SiaRegister[2]); +#endif + } + Adapter->Media[MediaCode].GeneralPurposeCtrl = + ((ULONG)*(DataWordPtr++) & 0xFFFF); + Adapter->Media[MediaCode].GeneralPurposeData = + ((ULONG)*(DataWordPtr) & 0xFFFF); +#if __DBG + DbgPrint("SRom: Gep Ctrl = %08x\n",Adapter->Media[MediaCode].GeneralPurposeCtrl); + DbgPrint("SRom: Gep Data = %08x\n",Adapter->Media[MediaCode].GeneralPurposeData); +#endif + + *PMediaCode = MediaCode; + + break; + + + default: + +#if __DBG + DbgPrint("Type =%02x unknown... skipping\n", Type ); +#endif + break; + + } + + *MediaBlock = EndOfBlock; + +} + + + + + + + + + + +/*+ + * DC21X4ParseFixedBlock + * + * Routine Description: + * + * This routine is called by the SROM Parser and takes care of the + * parsing of the info block with fixed format (EXT=0) in the 21140's + * info leaf. + * + * Arguments: + * + * Adapter - Pointer to the Data Structure + * DataBytePtr - Pointer to the Serial Rom data. + * GeneralPurposeCtrl - Value of the General Purpose Ctrl + * + * Return Value: + * + * None. + * +-*/ +extern +VOID +DC21X4ParseFixedBlock( + IN PDC21X4_ADAPTER Adapter, + IN OUT UNALIGNED UCHAR **MediaBlock, + IN USHORT GeneralPurposeCtrl, + OUT PUCHAR PMediaCode + ) +{ + UNALIGNED UCHAR *DataBytePtr; + UCHAR MediaCode; + + DataBytePtr = (UNALIGNED CHAR *)(*MediaBlock); + + MediaCode = *(DataBytePtr) & DC21X4_MEDIA; + + if (MediaCode >= MAX_MEDIA_TABLE) { + DataBytePtr += ((2*sizeof(DataBytePtr)) + sizeof(USHORT)); + *MediaBlock = DataBytePtr; + return ; + } + Adapter->MediaCapable |= 1 << MediaCode; + + Adapter->Media[MediaCode].GeneralPurposeCtrl = + (ULONG)GeneralPurposeCtrl; + Adapter->Media[MediaCode].GeneralPurposeData = + (ULONG)(*(++DataBytePtr) & 0xFF); + Adapter->Media[MediaCode].Mode = + GET_MODE(++DataBytePtr); + Adapter->Media[MediaCode].Polarity = + GET_POLARITY(DataBytePtr); + Adapter->Media[MediaCode].SenseMask = + GET_SENSE_MASK(DataBytePtr); + +#if __DBG + DbgPrint("Media Code= %02x\n", MediaCode); + DbgPrint("Media Capable= %02x\n", Adapter->MediaCapable); + DbgPrint("GPData= %02x\n",Adapter->Media[MediaCode].GeneralPurposeData); + DbgPrint("Mode= %02x\n",Adapter->Media[MediaCode].Mode); + DbgPrint("Polarity= %x\n",Adapter->Media[MediaCode].Polarity); + DbgPrint("Sense Mask= %x\n",Adapter->Media[MediaCode].SenseMask); +#endif + + Adapter->Media[MediaCode].Mode |= + (Adapter->Media[MediaCode].Mode & DC21X4_TXM_THRESHOLD_MODE)? + Adapter->Threshold10Mbps : Adapter->Threshold100Mbps; + + if ( Adapter->Media[MediaCode].SenseMask + && MediaCode != Medium10BaseTFd + && MediaCode != Medium100BaseTxFd + && MediaCode != Medium100BaseFxFd){ + + //Add the media code to the MediaPrecedence table + Adapter->MediaPrecedence[Adapter->MediaCount++] = MediaCode; + } + + // Check if default media + if (IF_DEFAULT_MEDIA(DataBytePtr)) { + Adapter->DefaultMediumFlag = TRUE; + Adapter->DefaultMedium = MediaCode; +#if __DBG + DbgPrint("SRom: Default Media = %04x\n",MediaCode); +#endif + } + + + *PMediaCode = MediaCode; + + DataBytePtr += sizeof(USHORT); + *MediaBlock = DataBytePtr; + +} + + + + + + + + + + + +#pragma NDIS_PAGABLE_FUNCTION(DC21X4ParseSRom) + +/* + * DC21X4ParseSRom + * + * Routine Description: + * + * ParseSRom parses the Serial ROM to retrieve the Ethernet Station + * address of the adapter and the adapter's media specific information + * + * Adapter - pointer to adapter structure + * + * Return Value: + * + * Ndis Status + * +-*/ + + +NDIS_STATUS +DC21X4ParseSRom( + IN PDC21X4_ADAPTER Adapter + ) +{ + + PSROM_ID_BLOCK SRomIdBlock; + UNALIGNED ADAPTER_ENTRIES *AdapterEntry; + UNALIGNED UCHAR *DataBytePtr; + UNALIGNED USHORT *DataWordPtr; + PUCHAR SRomData; + + USHORT GeneralPurposeCtrl; + USHORT MediaCount; + USHORT MediaType; + UCHAR MediaCode; + ULONG Offset = 0; + INT Index = 0; + INT i; + + BOOLEAN ExtendedFormat; + + ULONG CheckSum; + UCHAR Tmp[ETH_LENGTH_OF_ADDRESS]; + + UCHAR DC21140Leaf [] = { + 0x00,0x08, // AutoSense + 0x1f, // General Purpose Ctrl + 0x04, // Media Count + 0x00,0x0b,0x8e,0x00, // Tp + 0x03,0x1b,0x6d,0x00, // 100BaseTx + 0x04,0x03,0x8e,0x00, // TpFd + 0x05,0x1b,0x6d,0x00 // 100BaseTxFd + }; + +UCHAR DE500Strng[] = {"DE500-XA"}; + + + NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; + + + // Allocate space to dump the whole SROM + + ALLOC_MEMORY (&NdisStatus, &SRomData, SROM_SIZE); + if (NdisStatus != NDIS_STATUS_SUCCESS) { +#if __DBG + DbgPrint ( "SROM ALLOC_MEMORY FAILED\n"); +#endif + return NdisStatus; + } + + // Read the whole ROM + + if (DC21X4ReadSRom( + Adapter, + &Offset, + SROM_SIZE, + SRomData)) { + + SRomIdBlock = (PSROM_ID_BLOCK)SRomData; + } + else { +#if __DBG + DbgPrint ( "ReadSRom failed\n"); +#endif + FREE_MEMORY(SRomData, SROM_SIZE); + return NDIS_STATUS_HARD_ERRORS; + } + + // Check the Checksum + + CheckSum = CRC32(SRomData,SROM_SIZE-2) & 0xFFFF; + if (CheckSum != *(PUSHORT)&SRomData[SROM_SIZE-2]) { + + // Check if the SROM is a "legacy" formated SROM + // containing only the network address + + if ((Adapter-> DeviceId == DC21140_CFID) + && !IS_NULL_ADDRESS(SRomData) + && VerifyChecksum(SRomData) + ) { + +#if __DBG + DbgPrint ( "Legacy SRom...\n"); +#endif + MOVE_MEMORY ( + &Adapter->PermanentNetworkAddress[0], + &SRomData[0], + ETH_LENGTH_OF_ADDRESS + ); + + Adapter->PermanentAddressValid = TRUE; + + SRomIdBlock->FormatVersion = SROM_LEGACY; + DataBytePtr = &DC21140Leaf[0]; + } + + else { +#if __DBG + DbgPrint ( "Invalid SROM Checksum - Expected:%04x Read:%04x\n", + CheckSum,*(PUSHORT)&SRomData[SROM_SIZE-2]); +#endif + FREE_MEMORY(SRomData, SROM_SIZE); + return NDIS_STATUS_SOFT_ERRORS; + } + } + + // Check the SROM Version + + switch (SRomIdBlock->FormatVersion) { + + default: + +#if __DBG + DbgPrint ("SRom: Unsupported Format Version (%x)!\n", + SRomIdBlock->FormatVersion); +#endif + FREE_MEMORY(SRomData, SROM_SIZE); + return NDIS_STATUS_SOFT_ERRORS; + + case SROM_V1: + case SROM_V3: + + // Parse the Adapter Device Number. +#if __DBG + DbgPrint ("SRom: Version: %2x\n",SRomIdBlock->FormatVersion ); + DbgPrint ("SRom: Adapter Count: %2x\n", SRomIdBlock->AdapterCount); + DbgPrint ("SRom: Network Base Address: %02x-%02x-%02x-%02x-%02x-%02x\n", + SRomIdBlock->NetworkAddress[0],SRomIdBlock->NetworkAddress[1], + SRomIdBlock->NetworkAddress[2],SRomIdBlock->NetworkAddress[3], + SRomIdBlock->NetworkAddress[4],SRomIdBlock->NetworkAddress[5]); +#endif + + AdapterEntry = (PADAPTER_ENTRIES)&SRomData[sizeof(SROM_ID_BLOCK)]; + + if ((INT)SRomIdBlock->AdapterCount > 1) { + + // Parse the Adapter's Device Number. + for (; Index < (INT)SRomIdBlock->AdapterCount; Index++,AdapterEntry++) { + +#if __DBG + DbgPrint ("SRom: DeviceNumber, %2x\n",AdapterEntry->DeviceNumber ); + DbgPrint ("SRom: Offset, %4x\n", AdapterEntry->Offset); +#endif + if (AdapterEntry->DeviceNumber == (UCHAR)Adapter->SlotNumber) { + break; + } + } + } + + if (Index == (INT)SRomIdBlock->AdapterCount) { +#if __DBG + DbgPrint("SRom: Adapter's Device Number %d not found in SROM\n", + Adapter->SlotNumber); +#endif + FREE_MEMORY(SRomData, SROM_SIZE); + return NDIS_STATUS_ADAPTER_NOT_FOUND; + } + + // Check if the Station Address is a NULL Address + + if IS_NULL_ADDRESS(SRomIdBlock->NetworkAddress) { + +#if __DBG + DbgPrint ("SRom: NULL Network Address\n"); +#endif + Adapter->PermanentAddressValid = FALSE; + } + else { + + if (Index !=0) { + + // Add the adapter index to the base network Address + // (The carry is propagated to the 3 lower bytes + // of the address only (the 3 upper bytes are the vendor id)) + + for (i=0;i<3;i++) { + Tmp[i] = SRomIdBlock->NetworkAddress[ETH_LENGTH_OF_ADDRESS-(i+1)]; + } + *(UNALIGNED ULONG *)&Tmp[0] += Index; + for (i=0;i<3;i++) { + SRomIdBlock->NetworkAddress[ETH_LENGTH_OF_ADDRESS-(i+1)] = Tmp[i]; + } + + + } +#if __DBG + DbgPrint ("SRom: Network Address: %02x-%02x-%02x-%02x-%02x-%02x\n", + SRomIdBlock->NetworkAddress[0],SRomIdBlock->NetworkAddress[1], + SRomIdBlock->NetworkAddress[2],SRomIdBlock->NetworkAddress[3], + SRomIdBlock->NetworkAddress[4],SRomIdBlock->NetworkAddress[5]); +#endif + MOVE_MEMORY ( + &Adapter->PermanentNetworkAddress[0], + SRomIdBlock->NetworkAddress, + ETH_LENGTH_OF_ADDRESS + ); + + Adapter->PermanentAddressValid = TRUE; + } + + //Parse the Media Info Blocks. + + DataBytePtr = &(SRomData[AdapterEntry->Offset]); + + case SROM_LEGACY: + + Adapter->MediaCapable = 0; + + switch (Adapter-> DeviceId) { + + case DC21041_CFID: + + // Initialize the Media table with the default values. + + Adapter->Media[Medium10BaseT].SiaRegister[0] = DC21041_SIA0_10BT; + Adapter->Media[Medium10BaseT].SiaRegister[1] = DC21041_SIA1_10BT; + Adapter->Media[Medium10BaseT].SiaRegister[2] = DC21041_SIA2_10BT; + + Adapter->Media[Medium10Base2].SiaRegister[0] = DC21041_SIA0_10B2; + Adapter->Media[Medium10Base2].SiaRegister[1] = DC21041_SIA1_10B2; + Adapter->Media[Medium10Base2].SiaRegister[2] = DC21041_SIA2_10B2; + + Adapter->Media[Medium10Base5].SiaRegister[0] = DC21041_SIA0_10B5; + Adapter->Media[Medium10Base5].SiaRegister[1] = DC21041_SIA1_10B5; + Adapter->Media[Medium10Base5].SiaRegister[2] = DC21041_SIA2_10B5; + + MediaType = *(UNALIGNED USHORT *)DataBytePtr; + DataBytePtr += sizeof(USHORT); + + MediaCount = *(DataBytePtr++); +#if __DBG + DbgPrint("SRom: MediaType= %04x \n", MediaType); + DbgPrint("SRom: Media Count= %d \n", MediaCount); +#endif + for (Index=0; Index < MediaCount; Index++) { + + MediaCode = *DataBytePtr & DC21X4_MEDIA; + + if (MediaCode >= MAX_MEDIA_TABLE) { + DataBytePtr += (sizeof(DataBytePtr) + + ((*DataBytePtr & EXT) ? (3 * sizeof(DataWordPtr)):0)); + continue; + } + + Adapter->MediaCapable |= 1 << MediaCode; +#if __DBG + DbgPrint("SRom: Media Code= %02x\n", MediaCode); + DbgPrint("SRom: Media Capable= %02x\n", Adapter->MediaCapable); +#endif + + if (*(DataBytePtr++) & EXT) { + + // EXT bit is set : + // overwrite the SIA Registers default values + // with the values stored into the SROM + + DataWordPtr = (UNALIGNED USHORT *) DataBytePtr; + Adapter->Media[MediaCode].SiaRegister[0] = + ((ULONG)*(DataWordPtr++) & 0xFFFF); + Adapter->Media[MediaCode].SiaRegister[1] = + ((ULONG)*(DataWordPtr++) & 0xFFFF); + Adapter->Media[MediaCode].SiaRegister[2] = + ((ULONG)*(DataWordPtr++) & 0xFFFF); + DataBytePtr = (UNALIGNED UCHAR *) DataWordPtr; +#if __DBG + DbgPrint("SRom: EXT= 1:\n"); + DbgPrint("SRom: SiaReg[0]= %08x\n",Adapter->Media[MediaCode].SiaRegister[0]); + DbgPrint("SRom: SiaReg[1]= %08x\n",Adapter->Media[MediaCode].SiaRegister[1]); + DbgPrint("SRom: SiaReg[2]= %08x\n",Adapter->Media[MediaCode].SiaRegister[2]); +#endif + } + + } + + break; + + case DC21140_CFID: + + switch (SRomIdBlock->FormatVersion) { + + case SROM_LEGACY: + case SROM_V1: + + if (Adapter->RevisionNumber == DC21140_REV1_1) { + Adapter->DynamicAutoSense = BOARD_SIGNATURE(SRomData); + break; + } + + default: + + //MediaType + + MediaType = *(UNALIGNED USHORT *)DataBytePtr; + Adapter->DynamicAutoSense = ((MediaType & DISABLE_AUTOSENSE) == 0); +#if __DBG + DbgPrint("SRom: MediaType= %04x \n", MediaType); +#endif + } + +#if __DBG + DbgPrint("SRom: Dynamic Autosense %s\n", + Adapter->DynamicAutoSense? "Enabled":"Disabled"); +#endif + + DataBytePtr += sizeof(USHORT); + + GeneralPurposeCtrl = (((USHORT)*(DataBytePtr++) & 0xFF)|(0x100)); + + MediaCount = *(DataBytePtr++); + +#if __DBG + DbgPrint("SRom: General Purpose Control= %08x \n", GeneralPurposeCtrl); + DbgPrint("SRom: MediaCount= %d \n", MediaCount); +#endif + for (Index=0; Index < MediaCount; Index++) { + + ExtendedFormat = (*DataBytePtr & EXTENDED_FORMAT); + + if ((SRomIdBlock->FormatVersion == SROM_V3) && ExtendedFormat) { + DC21X4ParseExtendedBlock( + Adapter, + &DataBytePtr, + GeneralPurposeCtrl, + &MediaCode + ); + } + else { + DC21X4ParseFixedBlock( + Adapter, + &DataBytePtr, + GeneralPurposeCtrl, + &MediaCode + ); + } + + } + + if (!Adapter->DefaultMediumFlag && Adapter->MediaCount>0) { + Adapter->DefaultMedium = + Adapter->MediaPrecedence[Adapter->MediaCount-1]; + } + break; + + case DC21142_CFID: + + if (SRomIdBlock->FormatVersion < SROM_V3) { +#if __DBG + DbgPrint ("SRom: Unsupported Format Version (%x)!\n", + SRomIdBlock->FormatVersion); +#endif + FREE_MEMORY(SRomData, SROM_SIZE); + return NDIS_STATUS_SOFT_ERRORS; + } + + // Initialize the Media table with the default values. + + Adapter->Media[Medium10BaseT].SiaRegister[0] = DC21142_SIA0_10BT; + Adapter->Media[Medium10BaseT].SiaRegister[1] = DC21142_SIA1_10BT; + Adapter->Media[Medium10BaseT].SiaRegister[2] = DC21142_SIA2_10BT; + + Adapter->Media[Medium10Base2].SiaRegister[0] = DC21142_SIA0_10B2; + Adapter->Media[Medium10Base2].SiaRegister[1] = DC21142_SIA1_10B2; + Adapter->Media[Medium10Base2].SiaRegister[2] = DC21142_SIA2_10B2; + + Adapter->Media[Medium10Base5].SiaRegister[0] = DC21142_SIA0_10B5; + Adapter->Media[Medium10Base5].SiaRegister[1] = DC21142_SIA1_10B5; + Adapter->Media[Medium10Base5].SiaRegister[2] = DC21142_SIA2_10B5; + + + MediaType = *(UNALIGNED USHORT *)DataBytePtr; + + Adapter->DynamicAutoSense = ((MediaType & DISABLE_AUTOSENSE) == 0); +#if __DBG + DbgPrint("SRom: Dynamic Autosense %s\n", + Adapter->DynamicAutoSense? "Enabled":"Disabled"); +#endif + DataBytePtr += sizeof(USHORT); + MediaCount = *(DataBytePtr++); +#if __DBG + DbgPrint("SRom: MediaType= %04x \n", MediaType); + DbgPrint("SRom: MediaCount= %d \n", MediaCount); +#endif + + for (Index=0; Index < MediaCount; Index++) { + + DC21X4ParseExtendedBlock( + Adapter, + (PVOID)&DataBytePtr, + (USHORT)NULL, + &MediaCode + ); + } + + if (!Adapter->DefaultMediumFlag && Adapter->MediaCount>0) { + Adapter->DefaultMedium = + Adapter->MediaPrecedence[Adapter->MediaCount-1]; + } + + break; + + default: + + NdisStatus = NDIS_STATUS_DEVICE_FAILED; + } + + break; + + } + + if ( (MediaCount == 1) + && Adapter->MediaCapable + && !Adapter->PhyMediumInSrom + ) { + + //Force MediaType to the single supported medium +#if __DBG + DbgPrint("SRom: One single supported medium: Force MediaType %04x to ",Adapter->MediaType); +#endif + Adapter->MediaType &= ~(MEDIA_MASK | MEDIA_AUTOSENSE); + Adapter->MediaType |= MediaCode; +#if __DBG + DbgPrint("%04x\n",Adapter->MediaType); +#endif + } + + //if no 10Base port is populated, switch Port_Select to 100Base + + if (!(Adapter->MediaCapable & (MEDIUM_10BT | MEDIUM_10B2 | MEDIUM_10B5))) { + Adapter->OperationMode |= DC21X4_PORT_SELECT; + } + + FREE_MEMORY(SRomData, SROM_SIZE); + return NdisStatus; + + +} + + + + + + + + + +#pragma NDIS_PAGABLE_FUNCTION(DC21X4ReadSRom) + +/* + * DC21X4ReadSRom + * + * Routine Description: + * + * ReadSRom is called by DC21X4RegisterAdapter to read the onboard ROM + * for the network address and other parameters. + * This routine reads the required number of bytes from the given + * offset in the ROM. + * + * Arguments: + * + * Adapter - + * + * Offset - byte offset into SROM to start reading from. Must + * be word aligned + * Len - number of bytes to read + * Data - pointer to buffer to read data into. + * if NULL, don't return data + * + * Return Value: + * + * TRUE if success, FALSE if hardware failure encountered. + * +-*/ + + +BOOLEAN +DC21X4ReadSRom( + IN PDC21X4_ADAPTER Adapter, + IN OUT PULONG Offset, + IN USHORT Len, + OUT PUCHAR Buffer + ) +{ + + INT i; + INT j; + ULONG Dbit; + ULONG Dout; + USHORT WOffset; + USHORT WLen; + USHORT WData; + + // Make sure the ROM_Address is EVEN. + + if (*Offset & 1) + { +#if __DBG + DbgPrint ("ReadSRom failure - Offset not word aligned\n"); +#endif + return FALSE; + } + + // Round up the length to multiple of words. + WLen = (Len + 1) / 2; + + // Convert the ROM_Address byte offset to word offset + WOffset = (USHORT)(*Offset >> 1); + + // Make sure the requested read does not exceed the ROM size + + if ( (WOffset + WLen) > SROM_93LC46B_SIZE) { +#if __DBG + DbgPrint ("ReadSRom warning - address range excedes ROM size\n"); +#endif + return FALSE; + } + + + // Switch CSR to work with new SROM interface + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM + ); + + // Make sure SROM is in idle state + // (deliver it enough clocks with CS set, Din = 0). + + for (i = 0; i < SROM_93LC46B_MAX_CYCLES; i++) { + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS | CLK + ); + + NdisStallExecution(SROM_93LC46B_DELAY); + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS + ); + + NdisStallExecution(SROM_93LC46B_DELAY); + + } + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM + ); + + NdisStallExecution(SROM_93LC46B_DELAY); + + + // Read the data + + for (j = 0; j < WLen; j++,WOffset++) { + + //Output the READ command to the SROM + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS | DATA_1 + ); + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS | CLK | DATA_1 + ); + + NdisStallExecution(SROM_93LC46B_DELAY); + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS | DATA_1 + ); + + NdisStallExecution(SROM_93LC46B_DELAY); + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS | DATA_1 + ); + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS | CLK | DATA_1 + ); + + NdisStallExecution(SROM_93LC46B_DELAY); + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS | DATA_1 + ); + + NdisStallExecution(SROM_93LC46B_DELAY); + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS | DATA_0 + ); + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS | CLK | DATA_0 + ); + + NdisStallExecution(SROM_93LC46B_DELAY); + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS | DATA_0 + ); + + NdisStallExecution(SROM_93LC46B_DELAY); + + + // Output the WORD Address of the SROM + + for (i = SROM_93LC46B_ADDRESS_MSB; i>= 0; i--) { + + Dbit = (USHORT)((WOffset >> i) & 1) << 2; + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS | Dbit + ); + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS | CLK | Dbit + ); + + NdisStallExecution(SROM_93LC46B_DELAY); + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS | Dbit + ); + + NdisStallExecution(SROM_93LC46B_DELAY); + + } + + + // Verify that the SROM output data became now 0. + + DC21X4_READ_PORT( + DC21X4_IDPROM, + &Dout + ); + + if (Dout & SROM_93LC46B_VALID_BITMASK) { +#if __DBG + DbgPrint ("ReadSRom failure - SROM didn't become busy in read command\n"); +#endif + return(FALSE); + } + + // Read the data from the SROM + + WData = 0; + for (i = SROM_93LC46B_DATA_MSB; i >= 0; i--) { + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS | CLK + ); + + NdisStallExecution(SROM_93LC46B_DELAY); + + DC21X4_READ_PORT( + DC21X4_IDPROM, + &Dout + ); + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM | CS + ); + + WData |= ((Dout >> SROM_93LC46B_DATA_BIT) & 1) << i; + + NdisStallExecution(SROM_93LC46B_DELAY); + + } + +#if _DBG + DbgPrint("Data = %04x\n",WData); +#endif + + // Put our read data in user buffer + + if (Buffer) { + + if (Len >= 2) { + + *(PUSHORT)Buffer = WData; + Buffer += 2; + Len -= 2; + } + else { + + // Least significant byte only is copied + *Buffer = WData & 0xff; + Buffer++; + Len--; + } + + } + + //Negate the chip select (CS) to end the SROM command + + DC21X4_WRITE_PORT( + DC21X4_IDPROM, + CSR_WRITE | SEL_SROM + ); + + NdisStallExecution(SROM_93LC46B_DELAY); + + } + + *Offset = WOffset << 1; + return TRUE; + +} + -- cgit v1.2.3