diff options
Diffstat (limited to 'private/ntos/fw/mips/sonictst.c')
-rw-r--r-- | private/ntos/fw/mips/sonictst.c | 822 |
1 files changed, 822 insertions, 0 deletions
diff --git a/private/ntos/fw/mips/sonictst.c b/private/ntos/fw/mips/sonictst.c new file mode 100644 index 000000000..30741fc32 --- /dev/null +++ b/private/ntos/fw/mips/sonictst.c @@ -0,0 +1,822 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + sonictst.c + +Abstract: + + This module implements the SONIC ethernet test for the selftest. + The test consist in transmiting packets in loopback mode. + +Author: + + Lluis Abello (lluis) 19-Feb-1991 + +Environment: + + +Revision History: + +--*/ + +#include "fwp.h" +#include "sonictst.h" +#include "iodevice.h" +#include "ioaccess.h" +#include "fwstring.h" +#ifdef DUO +#include "duoint.h" +#endif + +extern volatile ULONG TimerTicks; +extern UCHAR * TranslationTable; + +VOID +MapDma( + ULONG VirtualAddress, + ULONG LogicalAddress, + ULONG Pages + ) +/*++ + +Routine description: + + This routine performs the I/O address maping by setting the + translation table. + + Physical and Logical Addresses must be page aligned. + +Arguments: + + VirtualAddress - Specifies the R4000 VirtualAddress. + + Logical Address will be mapped to the physical + address that this Virtual Address Maps. + + LogicalAdress - Address to map + + Pages - Number of pages to map + +Return value: + + None. +--*/ +{ +PTRANSLATION_ENTRY TranslationTable; +ULONG PageFrameNumber,LogicalPage,PhysicalAddress; +ULONG i; + PhysicalAddress=VirtualAddress&0x0FFFFFFF; // Extract Physical Address from KSEG0-1 + TranslationTable= (PTRANSLATION_ENTRY)((READ_REGISTER_ULONG(&DMA_CONTROL->TranslationBase.Long)) | 0xA0000000); + + // Initialize pointer to base + // of Table to write the new entries. + // Make physical address virtual + // Non cached because we want it + // to be written to memory + LogicalPage= LogicalAddress>>12; + PageFrameNumber=PhysicalAddress&0x03FFF000; + for (i=0;i < Pages;i++) { + TranslationTable[LogicalPage+i].PageFrame=PageFrameNumber; + PageFrameNumber+=0x1000; // next page starts after 4Kb more + TranslationTable[LogicalPage+i].Fill=0; + } + WRITE_REGISTER_ULONG(&DMA_CONTROL->TranslationLimit.Long,(LogicalPage+i) << 3); +} +VOID +AllocateReceiveDescriptors( + ) +/*++ + +Routine Description: + + This routine allocates and initializes a chain of 3 Receive Descriptors. + The Receive Descriptors are linked in a circular queue so that the + pointers don't need to be changed any more. The last Receive descriptor + points to the first but it has the EOL flag set so it's the last on the + queue and therefore sonic will not use the following descriptor (first one) + until we free it. Once we process a received packet, the EOL flag must be + rotated to the next descriptor to make a new descriptor available. + + In order to be able to use the link field from both physical (system soft) + and logical (sonic) address spaces the receive descriptors must have + the same alignment for both physical and logical addresses. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ +ULONG Link,i; +ULONG LogicalReceiveDscr; + ReceiveDscrQueue.Base = (PRECEIVE_DESCRIPTOR) PHYS_RECEIVE_DSCR_ADDRESS; + LogicalReceiveDscr = LOGICAL_RECEIVE_DSCR_ADDRESS; + MapDma((ULONG)ReceiveDscrQueue.Base, // R4000 Address + LogicalReceiveDscr, // Logical Address + 1 // 1 page + ); + //get 16 lower bits of address or offset + ReceiveDscrQueue.Current=Link=(ULONG)ReceiveDscrQueue.Base & 0xFFFF; + // + // Link first descriptor to the second one. + // + for (i=0;i<2;i++) { + Link += sizeof(RECEIVE_DESCRIPTOR); + (ReceiveDscrQueue.Base[i]).Link.Data=Link; // Link to next RD + (ReceiveDscrQueue.Base[i]).InUse.Data=AVAILABLE; // Make it avilable + } + // + // Link last descriptor to the first but mark it as EOL + // + (ReceiveDscrQueue.Base[2]).Link.Data=ReceiveDscrQueue.Current | EOL; + // + // Make it avilable + // + (ReceiveDscrQueue.Base[2]).InUse.Data=AVAILABLE; + ReceiveDscrQueue.Last=Link; // Keep track of the last one. + // we need only the upper bits to access a descriptor as Base | First + ReceiveDscrQueue.Base = (PRECEIVE_DESCRIPTOR)((ULONG) ReceiveDscrQueue.Base & 0xFFFF0000); + // + // Initialize sonic Receive descriptor pointers with the logical address + // of the descriptors. + // + WRITE_REGISTER_USHORT(&SONIC->URDA.Reg,(USHORT) (LogicalReceiveDscr >> 16)); + WRITE_REGISTER_USHORT(&SONIC->CRDA.Reg,ReceiveDscrQueue.Current); +} +VOID +AllocateReceiveResources( + ) +/*++ + +Routine Description: + + This routine allocates and initializes the Receive Resource area. + Two resources are allocated. + The pointer of each entry points to the Receive Buffers which are + also allocated by this routine. And the size of each buffer is also + set in the Recieve Resource word count entry. + + Receive Buffers allocated are RBA_SIZE bytes long. + + It also allocate room for the CAM descriptors. The CAM descriptor pointer + is pointed by CamDescriptor and resides inside the URRA segment. + + The mapping Logical <-> Physical spaces is also done. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ +ULONG i; +ULONG ReceivePhysBuffer; // Temporay pointer to a receive buffer area. +ULONG ReceiveLogBuffer; // Temporary pointer to a logical address. +// +//Allocate memory for the receive descriptors + CAM Addresses + CAM enable. +// + ReceivePhysRsrc = (PRECEIVE_RESOURCE) RECEIVE_PHYS_RSRC_ADDRESS; + ReceiveLogRsrc = (PRECEIVE_RESOURCE) RECEIVE_LOG_RSRC_ADDRESS; + MapDma((ULONG)ReceivePhysRsrc, + (ULONG)ReceiveLogRsrc, + 1 + ); +// +// Allocate Receive buffers in physical and logical spaces and map them. +// + ReceivePhysBuffer= (ULONG) RECEIVE_PHYS_BUFFER_ADDRESS; + ReceiveLogBuffer= (ULONG) RECEIVE_LOG_BUFFER_ADDRESS; + MapDma(ReceivePhysBuffer,ReceiveLogBuffer,2); +// +// The Receive Buffers are contiguos in memory. Sonic will write +// the logical address of the packets received. To translate this +// logical address to a physical one what we do is to keep the +// offset between these physical and logical addresses and then +// we just need to add this offset to the logical address to +// convert it to physical. +// + ReceiveBufferTranslationOffset =ReceivePhysBuffer-ReceiveLogBuffer; +// +// for each receive resource, Write the logical +// address of the receive buffer in the physical Receive resource. +// + for (i=0; i < 3; i++) { + ReceivePhysRsrc[i].BufferPtr0.Data=ReceiveLogBuffer & 0xFFFF; //16 lower bits + ReceivePhysRsrc[i].BufferPtr1.Data=ReceiveLogBuffer >> 16; //16 upper bits + ReceivePhysRsrc[i].WordCount0.Data=((RBA_SIZE >>1) & 0xFFFF); //16 lower bits + ReceivePhysRsrc[i].WordCount1.Data=(RBA_SIZE >> 17); //16 upper bits + ReceiveLogBuffer += RBA_SIZE; + } +// +// Initialize the CamDescriptor to point to the end of the RRA +// + PhysCamDescriptor=(PCAM_DESCRIPTOR)(&ReceivePhysRsrc[3]); + LogCamDescriptor=(PCAM_DESCRIPTOR)(&ReceiveLogRsrc[3]); +// +// Initialize sonic Resource Area pointers with the logical address mapped +// to the physical Area. +// + WRITE_REGISTER_USHORT(&SONIC->URRA.Reg,(USHORT) ((ULONG)ReceiveLogRsrc >> 16)); + WRITE_REGISTER_USHORT(&SONIC->RSA.Reg,(ULONG)ReceiveLogRsrc & 0xFFFF); + WRITE_REGISTER_USHORT(&SONIC->REA.Reg,(ULONG)(&ReceiveLogRsrc[3]) & 0xFFFF); + WRITE_REGISTER_USHORT(&SONIC->RRP.Reg,(ULONG)ReceiveLogRsrc & 0xFFFF); + WRITE_REGISTER_USHORT(&SONIC->RWP.Reg,(ULONG)(&ReceiveLogRsrc[2]) & 0xFFFF); + +// +// Set the lower boundary of the RBA to the maximum packet size. +// + WRITE_REGISTER_USHORT(&SONIC->EOBC.Reg,MAX_PACKET_SIZE >> 1); +// +// Set The receive control register. +// + WRITE_REGISTER_USHORT(&SONIC->ReceiveControl.Reg,RCR_ENDEC | RCR_RNT); +} +VOID +SetCamDescriptor( + ) +/*++ + +Routine Description: + + This routine Initializes the CAM descriptor area allocated by + "AllocateReceiveResources" and being pointed by PhysCamDescriptor. + + The Address loaded in the CAM is the one fetched from the NVRAM. + + It leaves everything ready to issue the Load CAM command. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ +ULONG i; +// +// Initialize CAM descriptor area. +// + PhysCamDescriptor[0].EntryPointer.Data=0; + PhysCamDescriptor[0].Port0.Data=(StationAddress[1] << 8) | + (StationAddress[0]); + PhysCamDescriptor[0].Port1.Data=(StationAddress[3] << 8) | + (StationAddress[2]); + PhysCamDescriptor[0].Port2.Data=(StationAddress[5] << 8) | + (StationAddress[4]); +// Set CAM Enable. + PhysCamDescriptor[1].EntryPointer.Data=1; // enable entry zero. + + WRITE_REGISTER_USHORT(&SONIC->CamDscrCount.Reg,1); // only one entry. +// Lower 16 bits offset from URRA + WRITE_REGISTER_USHORT(&SONIC->CamDscrPtr.Reg,(ULONG)LogCamDescriptor & 0xFFFF); +} +VOID +AllocateTransmitDescriptors( + ) +/*++ + +Routine Description: + + This routine allocates and initializes a pool of Transmit Descriptors. + The Transmit Descriptors are set to be used one for each packet as they + have only room for one fragment. + + The Descriptor fragment pointers are initialized to point to the + Transmit Buffer Area which is also allocated. + There is enough room allocated for each buffer for the bigest + ethernet packet. + + To keep the physical addresses of the TBA we use the upper 16 bits + of the SONIC_ENTRY this is the field called 'Fill'. + This way we don't ahve any restriction in these pointers but we + have to deal with both, physical and logical. + + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ +ULONG i; +ULONG PhysTbaPtr,LogTbaPtr; // Transmit Buffer Area pointers +// +// Allocate memory for transmit descriptors and map it +// + PhysTransmitDscr = (PTRANSMIT_DESCRIPTOR) PHYS_TRANSMIT_DSCR_ADDRESS; + LogicalTransmitDscr = (PTRANSMIT_DESCRIPTOR) LOGICAL_TRANSMIT_DSCR_ADDRESS; + MapDma((ULONG) PhysTransmitDscr, + (ULONG) LogicalTransmitDscr, + 1 + ); +// +// Allocate memory for Transmit Buffer are and map it. +// + PhysTbaPtr = PHYS_TBA_ADDRESS; + LogTbaPtr = LOG_TBA_ADDRESS; + MapDma(PhysTbaPtr,LogTbaPtr,1); + +// Initialize fragment count to 1 (packets won't be scatered) + + PhysTransmitDscr->FragCount.Data = 1; +// +// Initialize Logical pointers to TBA +// + PhysTransmitDscr->FragPtr0.Data = LogTbaPtr & 0xFFFF;// lower 16 bits + PhysTransmitDscr->FragPtr1.Data = LogTbaPtr >> 16; // upper 16 bits +// +// Initialize Physical pointer to TBA +// + PhysTransmitDscr->FragPtr0.Fill = PhysTbaPtr & 0xFFFF;// lower 16 bits + PhysTransmitDscr->FragPtr1.Fill = PhysTbaPtr >> 16; // upper 16 bits +// +// Unlink the packets, we will transmit one at a time. +// + PhysTransmitDscr->Link.Data = EOL; + PhysTransmitDscr->Config.Data = TCR_POWC; + +// +// Initialize UTDA register. This can be done here because the base address +// of the Transmit Descriptor Area will not change. +// CTDA must be set after a new packet is ready to be sent. +// + WRITE_REGISTER_USHORT(&SONIC->UTDA.Reg,(USHORT)((ULONG)LogicalTransmitDscr>>16)); +} +VOID +ComposeMessage( + ULONG Size, + UCHAR FirstValue + ) +/*++ + +Routine Description: + + This routine composes a message of the specified size. + It places the message in the buffer especified by the Transmit + Descriptor, and initializes the descriptor. + +Arguments: + + Size - Size of the message in bytes, must be <= MAX_PACKET_SIZE + FirstValue - value of first Data byte in the packet. + +Return Value: + + None. + +--*/ +{ +register ULONG i,j=0; +PUCHAR MsgPtr; // Temporary pointer to the message area. +// +// Load pointer to packet +// + MsgPtr= (PUCHAR) ((PhysTransmitDscr->FragPtr1.Fill << 16) | (PhysTransmitDscr->FragPtr0.Fill)); + + + for (i=0; i<6; i++) { + MsgPtr[j]=StationAddress[i]; // copy Destination address to packet + MsgPtr[j+6]=StationAddress[i]; // copy Source address to packet + j++; + } + j+=6; +// +// Set size of message +// + MsgPtr[j++] = Size >> 8; // upper 8 bits + MsgPtr[j++] = Size & 0xFF; // lower 8 bits +// +// Compose message +// + for (i=0; i < Size; i++) { + MsgPtr[j++] = FirstValue++; + } +// +// Initialize other Transmit descriptor fields. +// + PhysTransmitDscr->PktSize.Data = Size+6+6+2; + PhysTransmitDscr->FragSize.Data = Size+6+6+2; +// +// Initialize TDA registers with logical address. +// + WRITE_REGISTER_USHORT(&SONIC->CTDA.Reg,((ULONG) LogicalTransmitDscr) & 0xFFFF); +} +VOID +SonicCheckError( + ) +/*++ + +Routine Description: + + This routine checks and reports error conditions after an interrupt. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ +ULONG ErrorValue; + SonicErrors++; + if (SonicStatus.InterruptID & INT_BR) { // Bus Retry. + ErrorValue= READ_REGISTER_ULONG(&DMA_CONTROL->Errortype.Long); +// +// Clear error by writing back the contents of the register. +// + WRITE_REGISTER_ULONG(&DMA_CONTROL->Errortype.Long,ErrorValue); +// +// Read error registers to clear them +// + ErrorValue= READ_REGISTER_ULONG(&DMA_CONTROL->MemoryFailedAddress.Long); + ErrorValue= READ_REGISTER_ULONG(&DMA_CONTROL->RemoteFailedAddress.Long); +#ifndef DUO + ErrorValue= READ_REGISTER_ULONG(&DMA_CONTROL->ParityDiagnosticLow.Long); +#else + ErrorValue= READ_REGISTER_ULONG(&DMA_CONTROL->EccDiagnostic); +#endif + + } +} +BOOLEAN +WaitForSonicInterrupt( + ) +/*++ + +Routine Description: + + This routine waits for a sonic interrupt by polling the Semaphore + It sets the TimerTicks variable to 20 and if it becomes zero + (at least 20 millisecond has passed) it time-out. + +Arguments: + + None + +Return Value: + + FALSE if the interrupt ocurred. + TRUE otherwise. + +--*/ +{ +ULONG i; + TimerTicks=20; + while (TimerTicks) { // check for timeout + if (SonicIntSemaphore==0) { // if interrupt has ocurred + return FALSE; // return to process + } + } + return TRUE; // return if timeout. +} +VOID +InitSonic( + ) +/*++ + +Routine Description: + + This routine initializes the SONIC chip. + +Arguments: + + None + +Return Value: + + None + +--*/ +{ + +#ifdef DUO +// +// Enable sonic interrupts in altera +// + USHORT InterruptMask; + + InterruptMask = READ_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable); + WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,InterruptMask | (1 << 3)); + +#endif + + + +// +// Software Reset +// + WRITE_REGISTER_USHORT(&SONIC->Command.Reg,CR_RST); +// Set Hardware dependent configuration. + WRITE_REGISTER_USHORT(&SONIC->DataConfiguration.Reg,DATA_CONFIGURATION); +// Clear Reset + WRITE_REGISTER_USHORT(&SONIC->Command.Reg,0); + +// +// Initialize all these messy tables of descriptors... +// + AllocateReceiveDescriptors(); + AllocateReceiveResources(); + SetCamDescriptor(); + AllocateTransmitDescriptors(); +// +// Set Interrupt Mask +// + WRITE_REGISTER_USHORT(&SONIC->InterruptMask.Reg,( INT_BR | + INT_LCD | + INT_PKTRX | + INT_TXDN | + INT_TXER | + INT_RDE | + INT_RBE | + INT_RBAE | + INT_RFO)); +// +//Issue Load CAM Command and wait for this interrupt. +// + SonicStatus.ExpectedInt = INT_LCD; // Expect an INT_LCD interrupt. + SonicIntSemaphore=1; + WRITE_REGISTER_USHORT(&SONIC->Command.Reg,CR_LCAM); + if (WaitForSonicInterrupt()) { + FwPrint("Timeout waiting for sonic int\r\n"); + SonicErrors++; + return; + } + if (SonicStatus.Status==DONE) { + SonicStatus.ExpectedInt=0; // clear expected interrupts. + } else { + FwPrint("Sonic status not DONE\r\n"); + SonicErrors++; + } +// +// Issue the RRA Read Command +// + WRITE_REGISTER_USHORT(&SONIC->Command.Reg,CR_RRA); + while (READ_REGISTER_USHORT(&SONIC->Command.Reg) & CR_RRA) { // Wait until the command is processed. + } +// +// Enable Reception. +// + WRITE_REGISTER_USHORT(&SONIC->Command.Reg,CR_RXEN); + while (READ_REGISTER_USHORT(&SONIC->Command.Reg) & CR_RXDIS) { // wait until reception is enabled. + } +} +VOID +SonicInterrupt( + ) +/*++ + +Routine Description: + + This routine is the SONIC port service interrupt. It will be called from + the Trap Handler when getting an interrupt from the SONIC. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ +register USHORT InterruptStatus,NotCleared; +// +// Read Interrupt Status register +// + InterruptStatus= READ_REGISTER_USHORT(&SONIC->InterruptStatus.Reg); +// +// clear interrupt writing it back +// + WRITE_REGISTER_USHORT(&SONIC->InterruptStatus.Reg,InterruptStatus); + InterruptStatus= InterruptStatus & (~INT_HBL); // clear HBL bit. + if (EXPECTED_INT && NO_OTHER_INT) { + if (InterruptStatus & INT_TXDN) { + // + // Packet Transmited + // + SonicStatus.ExpectedInt &= ~INT_TXDN; // clear expected bit. + // check if it was properly sent. + SonicStatus.TransmitControl=READ_REGISTER_USHORT(&SONIC->TransmitControl.Reg); + if (SonicStatus.TransmitControl & (TCR_BCM | TCR_EXC | TCR_FU | TCR_EXD)) { + //Error Transmiting + SonicStatus.Status=ERROR; + SonicStatus.InterruptID = InterruptStatus; + SonicIntSemaphore = 0; // signal that the interrupt occurred. + return; + } + } + if (InterruptStatus & INT_PKTRX) { // packet received + SonicStatus.ExpectedInt &= ~INT_PKTRX; // clear interrupt + } + if (InterruptStatus & INT_LCD) { // load cam interrupt + SonicStatus.ExpectedInt &= ~INT_LCD; // clear interrupt + } + if (SonicStatus.ExpectedInt) { // we still want another interrupt + return; + } else { + SonicStatus.Status=DONE; + SonicIntSemaphore = 0; // signal that the interrupt occurred. + return; + } + } else { // we got an interrupt not expected. + SonicStatus.InterruptID=InterruptStatus; + SonicStatus.TransmitControl=READ_REGISTER_USHORT(&SONIC->TransmitControl.Reg); + SonicStatus.Status=ERROR; + SonicIntSemaphore = 0; // signal that the interrupt ocurred. + return; + } +} +ULONG +SonicCheckReception( + ) +/*++ + +Routine Description: + + This routine compares the sent packet with the received one. + Makes the used Receive Descriptor available, and if the Receive Buffer + is full it makes the used receive resurce available. + +Arguments: + + None. + +Return Value: + + ERROR - If errors are found + DONE - If no errors + +--*/ +{ +PUCHAR SentMsg,ReceivedMsg; +USHORT ReceiveStatus,TransmitControl; +ULONG PktSize,i; + if(CURRENT_DESCRIPTOR->InUse.Data) { + FwPrint("Descriptor in use\r\n"); + SonicErrors++; + return ERROR; + } + ReceiveStatus=CURRENT_DESCRIPTOR->Status.Data; + if (ReceiveStatus & (RCR_MC | RCR_BC | RCR_COL | RCR_CRCR | RCR_FAER)) { + FwPrint("Receive status %lx \r\n",ReceiveStatus); + SonicErrors++; + return ERROR; + } + // + // Get ptr to packet and add the offset between Logical and Physical + // to obtain the physical ptr. + // + ReceivedMsg=(PUCHAR) (( (CURRENT_DESCRIPTOR->PktPtr1.Data << 16) | + (CURRENT_DESCRIPTOR->PktPtr0.Data)) + + ReceiveBufferTranslationOffset); + + SentMsg=(PUCHAR) ( + (PhysTransmitDscr->FragPtr1.Fill << 16) | + PhysTransmitDscr->FragPtr0.Fill + ); + PktSize=CURRENT_DESCRIPTOR->ByteCount.Data; + PktSize -=4; // don't check FCS field. + for (i=0;i<PktSize;i++) { + if (ReceivedMsg[i] != SentMsg[i]) { + FwPrint("\r\n Data mismatch, expected %02lx received %02lx \r\n",SentMsg[i],ReceivedMsg[i]); + SonicErrors++; + return ERROR; + } + } + // + // If we get here is because the packet was successfully received. + // Set the descriptor tables ready for the next packet. + // + if (ReceiveStatus & RCR_LPKT) { // last packet in RBA. + // + // Advance the RWP to free the used Rba again. + // + if (READ_REGISTER_USHORT(&SONIC->RWP.Reg)+sizeof(RECEIVE_RESOURCE) == + READ_REGISTER_USHORT(&SONIC->REA.Reg)) {//if it's the last one + WRITE_REGISTER_USHORT(&SONIC->RWP.Reg,READ_REGISTER_USHORT(&SONIC->RSA.Reg)); + // the new RWP points at the starting address. + } else { + WRITE_REGISTER_USHORT(&SONIC->RWP.Reg,READ_REGISTER_USHORT(&SONIC->RWP.Reg)+sizeof(RECEIVE_RESOURCE)); + } + } + // + // Free Used Receive Descripor + // + CURRENT_DESCRIPTOR->InUse.Data=AVAILABLE; // make used desc available + ReceiveDscrQueue.Current=CURRENT_DESCRIPTOR->Link.Data; // First is the next + LAST_DESCRIPTOR->Link.Data &= NOT_EOL; // Last is not EOL any more. + ReceiveDscrQueue.Last=LAST_DESCRIPTOR->Link.Data; // Last is next one. + LAST_DESCRIPTOR->InUse.Data |= EOL; // New Last is EOL. + return DONE; +} +VOID +RomXTOA( + IN ULONG number, + OUT PSZ string + ) +/*++ + +Routine Description: + + This routine converts an ULONG to ASCII. + The conversion is done in HexaDecimal. + +Arguments: + + number - Supplies the ULONG to convert. + string - PSZ where the result is placed. + +Return Value: + + None. + +--*/ +{ +ULONG i; + for (i=7;i >= 0; i--) { + string[i]=TranslationTable[number&0xF]; + number = number >> 4; + } + string[8]='\0'; +} +ULONG +RomSonicLoopBackTest( + ) +/*++ + +Routine Description: + + This routine implements the SONIC loopback test for the selftest. + The Ethernet Controller is tested using a Loopback in the MAC. + +Arguments: + + None. + +Return Value: + + Returns 0 if no errors are found. + +--*/ +{ +// +// Note Packets are set to be 32 byte long so that they fit in the fifo. +// This is done because at this point interrupts are dispatched trough +// the Bootstrap Vector, reads from PROM take so long that the SONIC +// will get Bus retry Errors. +// +ULONG i,MsgLength=MIN_DATA_LENGTH-32; +CHAR String[64]; + SonicErrors=0; + InitSonic(); + if (SonicErrors) { + return SonicErrors; + } + for (i=0;i<16;i++) { + ComposeMessage(MsgLength,(UCHAR)i); + SonicStatus.ExpectedInt=INT_TXDN | INT_PKTRX; + // Issue the Transmit command. + SonicIntSemaphore=1; + WRITE_REGISTER_USHORT(&SONIC->Command.Reg,CR_TXP); + if (WaitForSonicInterrupt()) { + FwPrint("Timeout waiting for sonic int 2\r\n"); + SonicErrors++; + return SonicErrors; + } + if (SonicStatus.Status==DONE) { // a packet has been sent and received. + if (SonicCheckReception()==ERROR) { + FwPrint(ST_RECEIVED_MSG); + return SonicErrors; + } else { + FwPrint("."); + } + } else { + SonicCheckError(); + FwPrint("\r\nInt:%x Tx:%x",SonicStatus.InterruptID,SonicStatus.TransmitControl); + return SonicErrors; + } + } + return SonicErrors; +} |