mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-01 11:29:27 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
698 lines
24 KiB
C
698 lines
24 KiB
C
/*
|
|
File: SONIC_Loopback.c
|
|
|
|
Contains: This is the source file for the SONIC Loopback subtest.
|
|
This test performs a loopback test of the SONIC in a variety
|
|
of modes, as determined by the test modifier. This test can
|
|
operate in either a polled or interrupt driven mode, as determined
|
|
by the subtest modifier.
|
|
|
|
Written by: Joe Smyth
|
|
|
|
Copyright: © 1990, 1992 by Apple Computer, Inc., all rights reserved.
|
|
|
|
Change History (most recent first):
|
|
|
|
<SM2> 5/2/92 kc Roll in Horror. Comments follow:
|
|
<H2> 3/6/92 AL Upgraded to CTE v2.1 (copied over from XXTest project).
|
|
|
|
*/
|
|
|
|
//
|
|
// SONIC_Loopback.c
|
|
//
|
|
//
|
|
// 4/16/91 SW Changed the last byte of the DATACONFIG register from a C to a 9 per the instructions of
|
|
// Jano Banks and Sean Findley -- Sean
|
|
//
|
|
|
|
#include <SupportFunctions.h>
|
|
#include <SONIC_Loopback.h>
|
|
#include <SONIC_Common.h>
|
|
|
|
|
|
|
|
|
|
SubtestErr SONIC_Loopback( CTEInfo *info,
|
|
SONIC_Loopback_Params *params,
|
|
SONIC_Loopback_Results *results)
|
|
{
|
|
#pragma unused (debugstring)
|
|
SONIC_Loopback_Err err = SONIC_Loopback_Err_Unexpected ;
|
|
UWORD temp_register ;
|
|
UWORD NumOfCollisions ;
|
|
UWORD *handy_pointer ;
|
|
ULONG temp_data_address_scalar ;
|
|
int i;
|
|
ExceptionInfo exceptionInfo ;
|
|
ExceptionArg exceptionArg ;
|
|
int originalInterruptLevel ;
|
|
char debugstring[100] ;
|
|
|
|
#if defined (useMacsBug)
|
|
if (params->debug_mode)
|
|
{
|
|
sprintf ( debugstring , "Now at start of Loopback Subtest") ;
|
|
DebugStr( c2pstr(debugstring) ) ;
|
|
}
|
|
|
|
sprintf ( debugstring , "Now at start of Bitwalk Subtest") ;
|
|
DebugStr( c2pstr(debugstring) ) ;
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// Return the Silicon Revision to the Results block
|
|
//
|
|
results->Silicon_Rev = *(params->Sonic->regsArray[S_VERSION]);
|
|
|
|
|
|
|
|
//
|
|
// Put Sonic into software reset and disable reception
|
|
//
|
|
*(params->Sonic->regsArray[S_COMMAND]) = 0x0094 ;
|
|
if(*(params->Sonic->regsArray[S_COMMAND]) != 0x0094) // Check that we are in reset
|
|
{
|
|
err = SONIC_Loopback_Err_on_Reset;
|
|
goto ErrorExit ;
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set up new configuration register for revs greater than 3
|
|
// I changed the last byte of the S_DATACONFIG register from C to 9 according to instrutions from
|
|
// HW guys -- Sean
|
|
|
|
if (results->Silicon_Rev > 3)
|
|
{
|
|
*(params->Sonic->regsArray[S_DATACONFIG2]) = 0x0000 ;
|
|
if (params->align_flag)
|
|
*(params->Sonic->regsArray[S_DATACONFIG]) = 0x8329 ;
|
|
else
|
|
*(params->Sonic->regsArray[S_DATACONFIG]) = 0x8309 ;
|
|
|
|
}
|
|
else
|
|
{
|
|
if (params->align_flag)
|
|
*(params->Sonic->regsArray[S_DATACONFIG]) = 0x0329 ;
|
|
else
|
|
*(params->Sonic->regsArray[S_DATACONFIG]) = 0x0309 ;
|
|
}
|
|
|
|
//
|
|
// Clear interrupt status register and disable the interrupts
|
|
//
|
|
*(params->Sonic->regsArray[S_INTMASK]) = 0x0000 ; // Disable all interrupts
|
|
if(0 != *(params->Sonic->regsArray[S_INTMASK]))
|
|
{
|
|
err = SONIC_Loopback_Err_disabling_interrupts;
|
|
goto ErrorExit ;
|
|
}
|
|
|
|
*(params->Sonic->regsArray[S_INTSTATUS]) = 0x7FFF ;
|
|
if(0 != *(params->Sonic->regsArray[S_INTSTATUS]))
|
|
{
|
|
err = SONIC_Loopback_Err_clearing_Interrupt_Status ;
|
|
goto ErrorExit ;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// If we want to install interrupts then do it here
|
|
//
|
|
|
|
if (params->interrupt_mode)
|
|
{
|
|
exceptionArg.params = params ;
|
|
exceptionArg.results = results ;
|
|
originalInterruptLevel = SUP_SetInterruptLevel(info,7) ;
|
|
params->interrupt_install_function(info, &exceptionInfo, &exceptionArg) ; // Install the interrupt handler.
|
|
SUP_SetInterruptLevel(info, params->interrupt_level - 1) ; // set interrupt mask to SONIC level -1. Interrupts will be
|
|
// serviced now if generated.
|
|
*(params->Sonic->regsArray[S_INTMASK]) = 0x7FFF ; // Enable all SONIC interrupts
|
|
|
|
|
|
*(params->Sonic->regsArray[S_TXCONTROL]) &= 0x7FFF ; // Clear the PINT bit
|
|
*(params->Sonic->regsArray[S_TXCONTROL]) |= 0x8000 ; // Set the PINT bit thus generating a programmable interrupt
|
|
}
|
|
|
|
//
|
|
// Clear reset
|
|
//
|
|
|
|
temp_register = *(params->Sonic->regsArray[S_COMMAND]) ;
|
|
*(params->Sonic->regsArray[S_COMMAND]) = (temp_register & 0xFF7F) ; // Clear reset
|
|
|
|
//
|
|
// Initialise the End of buffer word count register to maximum packet size: 760 words
|
|
//
|
|
|
|
*(params->Sonic->regsArray[S_EOBC]) = 0x02F8 ;
|
|
|
|
|
|
//
|
|
// Initialise the first Receive Descriptor Area and the Upper Receive Descriptor Address
|
|
//
|
|
|
|
temp_data_address_scalar = (ULONG)params->RDA1_physical_ptr ;
|
|
*(params->Sonic->regsArray[S_URDA]) = (UWORD)((temp_data_address_scalar & 0xFFFF0000)>>bitshift16) ;
|
|
results->URDA_value = *(params->Sonic->regsArray[S_URDA]) ;
|
|
|
|
temp_data_address_scalar = (ULONG)params->RDA1_physical_ptr ;
|
|
*(params->Sonic->regsArray[S_CRDA]) = (UWORD)(temp_data_address_scalar & 0x0000FFFF) ;
|
|
results->CRDA_value = *(params->Sonic->regsArray[S_CRDA]) ;
|
|
|
|
temp_data_address_scalar = (ULONG)params->RDA2_physical_ptr ;
|
|
params->RDA1_logical_ptr->RXpkt_link = (temp_data_address_scalar & 0x0000FFFE) ; // initialise RXpkt.link/EOL EOL = 0, there is another RDA
|
|
params->RDA1_logical_ptr->RXpkt_in_use = 0xFFFF ; // avail the RDA to Sonic: RXpkt_in_use -> non-zero
|
|
params->RDA1_logical_ptr->RXpkt_status = 0 ; // The rest of the RDA is initialised to zero as it will be filled in by SONIC
|
|
params->RDA1_logical_ptr->RXpkt_byte_count = 0 ; // as it receives a packet
|
|
params->RDA1_logical_ptr->RXpkt_ptr0 = 0 ;
|
|
params->RDA1_logical_ptr->RXpkt_ptr1 = 0 ;
|
|
params->RDA1_logical_ptr->RXpkt_seq_no = 0 ;
|
|
|
|
//
|
|
// Initialise the second Receive Descriptor Area
|
|
//
|
|
|
|
temp_data_address_scalar = (ULONG)params->RDA3_physical_ptr ;
|
|
params->RDA2_logical_ptr->RXpkt_link = ((temp_data_address_scalar & 0x0000FFFF) | 0x00000001); // initialise RXpkt.link/EOL EOL = 1, this is the last RDA until we get the RDE
|
|
// interrupt at which time we will allow SONIC to reuse RDA1.
|
|
params->RDA2_logical_ptr->RXpkt_in_use = 0xFFFF ; // avail the RDA to Sonic: RXpkt_in_use -> non-zero
|
|
params->RDA2_logical_ptr->RXpkt_status = 0 ; // The rest of the RDA is initialised to zero as it will be filled in by SONIC
|
|
params->RDA2_logical_ptr->RXpkt_byte_count = 0 ; // as it receives a packet
|
|
params->RDA2_logical_ptr->RXpkt_ptr0 = 0 ;
|
|
params->RDA2_logical_ptr->RXpkt_ptr1 = 0 ;
|
|
params->RDA2_logical_ptr->RXpkt_seq_no = 0 ;
|
|
|
|
|
|
//
|
|
// Initialise the third Receive Descriptor Area
|
|
//
|
|
|
|
temp_data_address_scalar = (ULONG)params->RDA1_physical_ptr ;
|
|
params->RDA3_logical_ptr->RXpkt_link = ((temp_data_address_scalar & 0x0000FFFF) | 0x00000001); // initialise RXpkt.link/EOL EOL = 1, this is the last RDA
|
|
|
|
params->RDA3_logical_ptr->RXpkt_in_use = 0xFFFF ; // avail the RDA to Sonic: RXpkt_in_use -> non-zero
|
|
params->RDA3_logical_ptr->RXpkt_status = 0 ; // The rest of the RDA is initialised to zero as it will be filled in by SONIC
|
|
params->RDA3_logical_ptr->RXpkt_byte_count = 0 ; // as it receives a packet
|
|
params->RDA3_logical_ptr->RXpkt_ptr0 = 0 ;
|
|
params->RDA3_logical_ptr->RXpkt_ptr1 = 0 ;
|
|
params->RDA3_logical_ptr->RXpkt_seq_no = 0 ;
|
|
|
|
//
|
|
// Initialise the Receive Resource Area
|
|
//
|
|
|
|
temp_data_address_scalar = (ULONG)params->RRA_physical_ptr ;
|
|
*(params->Sonic->regsArray[S_URRA]) = (UWORD)((temp_data_address_scalar & 0xFFFF0000)>>bitshift16) ; // load upper Receive Resource Address
|
|
|
|
temp_data_address_scalar = (ULONG)params->RRA_physical_ptr ;
|
|
*(params->Sonic->regsArray[S_RSA]) = (UWORD)(temp_data_address_scalar & 0x0000FFFF) ; // load Receive Resource Start Address
|
|
*(params->Sonic->regsArray[S_RRP]) = (UWORD)(temp_data_address_scalar & 0x0000FFFF) ; // load Receive Resource Read Pointer
|
|
|
|
temp_data_address_scalar = (ULONG)params->RRA_physical_ptr ;
|
|
*(params->Sonic->regsArray[S_REA]) = (UWORD)((temp_data_address_scalar + sizeof(Receive_Resource_Area)) & 0x0000FFFF) ; // load Receive Resource End Address
|
|
|
|
temp_data_address_scalar = (ULONG)(&((*params->RRA_physical_ptr)[2].RXrsc_ptr0)) ;
|
|
*(params->Sonic->regsArray[S_RWP]) = (UWORD)(temp_data_address_scalar & 0x0000FFFF) ; // load Resource Write Pointer
|
|
|
|
//
|
|
// Load the Receive Buffer information into the RRA
|
|
//
|
|
|
|
// First for the Receive Buffer Area 1
|
|
|
|
temp_data_address_scalar = (ULONG)params->RBA1_physical_ptr ;
|
|
(*params->RRA_logical_ptr)[0].RXrsc_ptr1 = ((temp_data_address_scalar & 0xFFFF0000)>>bitshift16) ; // Store the RXrsrc.buff_ptr1 for RBA1 in the RRA
|
|
|
|
temp_data_address_scalar = (ULONG)params->RBA1_physical_ptr ;
|
|
(*params->RRA_logical_ptr)[0].RXrsc_ptr0 = (temp_data_address_scalar & 0x0000FFFF) ; // Store the RXrsrc.buff_ptr0 for RBA1 in the RRA
|
|
|
|
(*params->RRA_logical_ptr)[0].RXrsc_wc0 = 800 ; // Our buffer size is 800 words
|
|
(*params->RRA_logical_ptr)[0].RXrsc_wc1 = 0 ;
|
|
|
|
// And for Receive Buffer Area 2
|
|
|
|
temp_data_address_scalar = (ULONG)params->RBA2_physical_ptr ;
|
|
(*params->RRA_logical_ptr)[1].RXrsc_ptr1 = ((temp_data_address_scalar & 0xFFFF0000)>>bitshift16) ; // Store the RXrsrc.buff_ptr1 for RBA2 in the RRA
|
|
|
|
temp_data_address_scalar = (ULONG)params->RBA2_physical_ptr ;
|
|
(*params->RRA_logical_ptr)[1].RXrsc_ptr0 = (temp_data_address_scalar & 0x0000FFFF) ; // Store the RXrsrc.buff_ptr0 for RBA2 in the RRA
|
|
|
|
(*params->RRA_logical_ptr)[1].RXrsc_wc0 = 800 ; // Our buffer size is 800 words
|
|
(*params->RRA_logical_ptr)[1].RXrsc_wc1 = 0 ;
|
|
|
|
// And finally for Receive Buffer Area 3
|
|
|
|
temp_data_address_scalar = (ULONG)params->RBA3_physical_ptr ;
|
|
(*params->RRA_logical_ptr)[2].RXrsc_ptr1 = ((temp_data_address_scalar & 0xFFFF0000)>>bitshift16) ; // Store the RXrsrc.buff_ptr1 for RBA3 in the RRA
|
|
|
|
temp_data_address_scalar = (ULONG)params->RBA3_physical_ptr ;
|
|
(*params->RRA_logical_ptr)[2].RXrsc_ptr0 = (temp_data_address_scalar & 0x0000FFFF) ; // Store the RXrsrc.buff_ptr0 for RBA3 in the RRA
|
|
|
|
(*params->RRA_logical_ptr)[2].RXrsc_wc0 = 800 ; // Our buffer size is 800 words.
|
|
(*params->RRA_logical_ptr)[2].RXrsc_wc1 = 0 ;
|
|
|
|
|
|
|
|
//
|
|
// Load the first block of RRA data into the Sonic Registers by invoking the Read RRA command
|
|
// This is subsequently done automatically by SONIC as receive buffers are exhausted, until the RRA is
|
|
// empty.
|
|
// Note :This is the first DMA of the loopback DTM.
|
|
//
|
|
|
|
temp_register = *(params->Sonic->regsArray[S_COMMAND]) ;
|
|
*(params->Sonic->regsArray[S_COMMAND]) = (temp_register & 0xFF7F) ; // Clear the Sonic Software reset
|
|
|
|
temp_register = *(params->Sonic->regsArray[S_COMMAND]) ;
|
|
*(params->Sonic->regsArray[S_COMMAND]) = (temp_register | 0x0100) ; // Invoke Read RRA
|
|
|
|
|
|
results->CRBA0_value = *(params->Sonic->regsArray[S_CRBA0]) ; // Report what we actually loaded
|
|
results->CRBA1_value = *(params->Sonic->regsArray[S_CRBA1]) ;
|
|
results->RBWC0_value = *(params->Sonic->regsArray[S_RBWC0]) ;
|
|
results->RBWC1_value = *(params->Sonic->regsArray[S_RBWC1]) ;
|
|
|
|
|
|
|
|
//
|
|
// Initialise the receive buffers
|
|
//
|
|
|
|
for ( i = 0; i < sizeof(bufferArea); i++)
|
|
{
|
|
(*params->RBA1_logical_ptr)[i] = InitialData1;
|
|
|
|
(*params->RBA2_logical_ptr)[i] = InitialData2;
|
|
}
|
|
|
|
//
|
|
// Initialise the Transmit Descriptor Areas
|
|
//
|
|
|
|
// First pkt1TDA
|
|
|
|
temp_data_address_scalar = (ULONG)params->TDA_physical_ptr ;
|
|
*(params->Sonic->regsArray[S_UTDA]) = (UWORD)((temp_data_address_scalar & 0xFFFF0000)>>bitshift16) ;
|
|
|
|
temp_data_address_scalar = (ULONG)params->TDA_physical_ptr ;
|
|
*(params->Sonic->regsArray[S_CTDA]) = (UWORD)(temp_data_address_scalar & 0x0000FFFF) ;
|
|
|
|
params->TDA_logical_ptr->pkt1TDA.TXpkt_status = 0 ;
|
|
params->TDA_logical_ptr->pkt1TDA.TXpkt_config = 0x0000 ; // configure the SONIC Transmitter with Programmable Interrupt, CRC on
|
|
// and "Out of Window Collision Timer" begins at first bit of Preamble
|
|
params->TDA_logical_ptr->pkt1TDA.TXpkt_size = 1500 ;
|
|
params->TDA_logical_ptr->pkt1TDA.TXpkt_frag_count = 1 ;
|
|
|
|
temp_data_address_scalar = (ULONG)params->TBA1_physical_ptr ;
|
|
params->TDA_logical_ptr->pkt1TDA.TXpkt_frag_ptr0 = (temp_data_address_scalar & 0x0000FFFF) ;
|
|
|
|
temp_data_address_scalar = (ULONG)params->TBA1_physical_ptr ;
|
|
params->TDA_logical_ptr->pkt1TDA.TXpkt_frag_ptr1 = ((temp_data_address_scalar & 0xFFFF0000)>>bitshift16) ;
|
|
|
|
params->TDA_logical_ptr->pkt1TDA.TXpkt_frag_size = 1500 ;
|
|
|
|
temp_data_address_scalar = (ULONG)(&(params->TDA_physical_ptr->pkt2TDA.TXpkt_status)) ;
|
|
if (params->loopback_mode == MACMode)
|
|
temp_data_address_scalar = (temp_data_address_scalar | 0x00000001) ; // If its MAC loopback mode only transmit 1 packet ie make this the last TDA
|
|
else
|
|
temp_data_address_scalar = (temp_data_address_scalar & 0x0000FFFE) ; // Otherwise tell SONIC there's another to follow. This is because MAC loopback
|
|
// is too fast for the receive cct to keep up with multiple packets.
|
|
|
|
params->TDA_logical_ptr->pkt1TDA.TXpkt_link = (UWORD)(temp_data_address_scalar & 0x0000FFFF) ;
|
|
|
|
// and now pkt2TDA
|
|
|
|
params->TDA_logical_ptr->pkt2TDA.TXpkt_status = 0 ;
|
|
params->TDA_logical_ptr->pkt2TDA.TXpkt_config = 0x0000 ; // configure the SONIC Transmitter with Programmable Interrupt, CRC on
|
|
// and "Out of Window Collision Timer" begins at first bit of Preamble
|
|
params->TDA_logical_ptr->pkt2TDA.TXpkt_size = 1500 ;
|
|
params->TDA_logical_ptr->pkt2TDA.TXpkt_frag_count = 2 ;
|
|
|
|
temp_data_address_scalar = (ULONG)params->TBA2_physical_ptr ;
|
|
params->TDA_logical_ptr->pkt2TDA.TXpkt_frag1_ptr0 = (temp_data_address_scalar & 0x0000FFFF) ;
|
|
|
|
temp_data_address_scalar = (ULONG)params->TBA2_physical_ptr ;
|
|
params->TDA_logical_ptr->pkt2TDA.TXpkt_frag1_ptr1 = ((temp_data_address_scalar & 0xFFFF0000)>>bitshift16) ;
|
|
|
|
params->TDA_logical_ptr->pkt2TDA.TXpkt_frag1_size = 750 ;
|
|
|
|
|
|
temp_data_address_scalar = (ULONG)(&((*params->TBA2_physical_ptr)[800])) ;
|
|
params->TDA_logical_ptr->pkt2TDA.TXpkt_frag2_ptr0 = (temp_data_address_scalar & 0x0000FFFF) ;
|
|
|
|
temp_data_address_scalar = (ULONG)(&((*params->TBA2_physical_ptr)[800])) ;
|
|
params->TDA_logical_ptr->pkt2TDA.TXpkt_frag2_ptr1 = ((temp_data_address_scalar & 0xFFFF0000)>>bitshift16) ;
|
|
|
|
params->TDA_logical_ptr->pkt2TDA.TXpkt_frag2_size = 750 ;
|
|
|
|
temp_data_address_scalar = (ULONG)(&(params->TDA_physical_ptr->pkt1TDA.TXpkt_status)) ;
|
|
params->TDA_logical_ptr->pkt2TDA.TXpkt_link = ((temp_data_address_scalar & 0x0000FFFF) | 0x00000001) ; // This is the last TDA, so EOL = 1
|
|
|
|
|
|
//
|
|
// Initialise the transmit buffer data, but only the used fragments
|
|
//
|
|
|
|
for ( i = 0; i < 1500; i++)
|
|
(*params->TBA1_logical_ptr)[i] = ExpectedData1 ;
|
|
|
|
for ( i = 1500; i < 1600; i++)
|
|
(*params->TBA1_logical_ptr)[i] = 0 ;
|
|
|
|
for ( i = 0; i < 750; i++)
|
|
(*params->TBA2_logical_ptr)[i] = ExpectedData2 ;
|
|
|
|
for ( i = 750; i < 800; i++)
|
|
(*params->TBA2_logical_ptr)[i] = 0 ;
|
|
|
|
for ( i = 800; i < 1550; i++)
|
|
(*params->TBA2_logical_ptr)[i] = ExpectedData3 ;
|
|
|
|
for ( i = 1550; i < 1600; i++)
|
|
(*params->TBA2_logical_ptr)[i] = 0 ;
|
|
|
|
|
|
//
|
|
// Prepare Sonic pointers for Load CAM instruction
|
|
//
|
|
*(params->Sonic->regsArray[S_CAMDC]) = (UWORD)params->CAM_Data_logical_ptr->number_of_CAM_entries ;
|
|
|
|
temp_data_address_scalar = (ULONG)params->CAM_Data_physical_ptr->CAM_data;
|
|
*(params->Sonic->regsArray[S_URRA]) = (UWORD)((temp_data_address_scalar & 0xFFFF0000)>>bitshift16) ;
|
|
|
|
temp_data_address_scalar = (ULONG)params->CAM_Data_physical_ptr->CAM_data;
|
|
*(params->Sonic->regsArray[S_CAMDP]) = (UWORD)(temp_data_address_scalar & 0x0000FFFF) ;
|
|
|
|
//
|
|
// Issue load CAM command
|
|
//
|
|
|
|
temp_register = *(params->Sonic->regsArray[S_COMMAND]) ;
|
|
*(params->Sonic->regsArray[S_COMMAND]) = (temp_register & 0xFF7F) ; // Clear reset
|
|
|
|
|
|
temp_register = *(params->Sonic->regsArray[S_COMMAND]) ;
|
|
*(params->Sonic->regsArray[S_COMMAND]) = (temp_register | 0x0200) ; // Invoke load CAM
|
|
|
|
|
|
// Call the test specified Timeout Function.
|
|
|
|
if (params->interrupt_mode ? handy_pointer = &results->interrupts_serviced : handy_pointer = params->Sonic->regsArray[S_INTSTATUS]) ;
|
|
if (err = params->timeoutMethod(info,handy_pointer, 0x1000,params->timeout_factor ))
|
|
{
|
|
err = SONIC_Loopback_Err_LCAM_timeout ;
|
|
results->interrupt_status = *(params->Sonic->regsArray[S_INTSTATUS]);
|
|
goto ErrorExit ;
|
|
}
|
|
results->interrupt_status = *(params->Sonic->regsArray[S_INTSTATUS]);
|
|
|
|
if (results->interrupt_error)
|
|
{
|
|
err = SONIC_Loopback_Err_Interrupt ;
|
|
goto ErrorExit ;
|
|
}
|
|
|
|
|
|
//
|
|
// Configure the receive control register
|
|
//
|
|
|
|
switch( params->loopback_mode )
|
|
{
|
|
case MACMode:
|
|
*(params->Sonic->regsArray[S_RXCONTROL]) = 0xFA00 ;
|
|
break;
|
|
|
|
case ENDECMode:
|
|
*(params->Sonic->regsArray[S_RXCONTROL]) = 0xFC00 ;
|
|
break;
|
|
|
|
case TransceiverMode:
|
|
*(params->Sonic->regsArray[S_RXCONTROL]) = 0xFE00 ;
|
|
break;
|
|
|
|
default:
|
|
err = SONIC_Loopback_Err_no_loopback_mode_specified ;
|
|
goto ErrorExit;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Enable receiver
|
|
//
|
|
|
|
*(params->Sonic->regsArray[S_COMMAND]) = 0x0008 ;
|
|
|
|
//
|
|
// Start transmission
|
|
//
|
|
|
|
*(params->Sonic->regsArray[S_COMMAND]) = 0x000A ;
|
|
|
|
//
|
|
// Call the test specified Timeout Function for the 1st packet.
|
|
//
|
|
results->CRBA0_value = *(params->Sonic->regsArray[S_CRBA0]) ; // Report what receive buffer is been used
|
|
results->CRBA1_value = *(params->Sonic->regsArray[S_CRBA1]) ;
|
|
results->RBWC0_value = *(params->Sonic->regsArray[S_RBWC0]) ;
|
|
results->RBWC1_value = *(params->Sonic->regsArray[S_RBWC1]) ;
|
|
results->pkt_number = 1 ;
|
|
|
|
handy_pointer = (UWORD *)(&(params->RDA1_logical_ptr->RXpkt_status)) ;
|
|
if (err = params->timeoutMethod(info,handy_pointer, 0x0002, params->timeout_factor )) // The mask 2 is the LBK (loopback packet received)
|
|
{ // bit of the RDA status register.
|
|
err = SONIC_Loopback_Err_timeout_receiving_1st_pkt ;
|
|
results->Pkt1_Receive_Status = (UWORD)(params->RDA1_logical_ptr->RXpkt_status) ;
|
|
results->Pkt1_Transmit_Status = (UWORD)(params->TDA_logical_ptr->pkt1TDA.TXpkt_status) ;
|
|
|
|
goto ErrorExit ;
|
|
}
|
|
results->Pkt1_Receive_Status = (UWORD)(params->RDA1_logical_ptr->RXpkt_status) ; // Only lower word is valid
|
|
//
|
|
// Check for other errors
|
|
//
|
|
results->Pkt1_Transmit_Status = (UWORD)(params->TDA_logical_ptr->pkt1TDA.TXpkt_status) ; // Only lower word is valid
|
|
if (results->Pkt1_Transmit_Status & 0x044E) // Check only error bits
|
|
{
|
|
err = SONIC_Loopback_Err_transmitting_1st_pkt ;
|
|
goto ErrorExit ;
|
|
}
|
|
|
|
|
|
if (results->Pkt1_Receive_Status & 0x000C) // Check only error bits
|
|
{
|
|
err = SONIC_Loopback_Err_receiving_1st_pkt ;
|
|
goto ErrorExit ;
|
|
}
|
|
|
|
|
|
//
|
|
// Compare received data with transmitted data for the first packet
|
|
//
|
|
|
|
for (i = 0; i < 1500; i++)
|
|
{
|
|
results->transmitted_data = (*params->TBA1_logical_ptr)[i] ;
|
|
results->received_data = (*params->RBA1_logical_ptr)[i];
|
|
|
|
results->offset_of_byte_in_err = i ;
|
|
|
|
if ((results->received_data != results->transmitted_data) || (results->received_data == 0) || (results->transmitted_data == 0)) // Sanity check, make sure we`re not transmitting and receiving zero`s
|
|
{
|
|
err = SONIC_Loopback_Err_in_1st_pkt_data ;
|
|
goto ErrorExit ;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we are doing a MAC loopback then end here
|
|
//
|
|
if (params->loopback_mode == MACMode)
|
|
goto MAC_Loopback_Exit ;
|
|
|
|
|
|
//
|
|
// Call the test specified Timeout Function for 2nd packet.
|
|
//
|
|
|
|
results->CRBA0_value = *(params->Sonic->regsArray[S_CRBA0]) ; // Report what receive buffer is been used
|
|
results->CRBA1_value = *(params->Sonic->regsArray[S_CRBA1]) ;
|
|
results->RBWC0_value = *(params->Sonic->regsArray[S_RBWC0]) ;
|
|
results->RBWC1_value = *(params->Sonic->regsArray[S_RBWC1]) ;
|
|
results->pkt_number = 2 ;
|
|
results->offset_of_byte_in_err = 0 ; // reset values for second packet
|
|
results->transmitted_data = 0 ;
|
|
results->received_data = 0 ;
|
|
|
|
handy_pointer = (UWORD *)(&(params->RDA2_logical_ptr->RXpkt_status)) ;
|
|
if (err = params->timeoutMethod(info,handy_pointer, 0x0002, params->timeout_factor )) // The mask 2 is the LBK (loopback packet received)
|
|
{ // bit of the TDA status register.
|
|
err = SONIC_Loopback_Err_timeout_receiving_2nd_pkt ;
|
|
results->Pkt2_Receive_Status = (UWORD)(params->RDA2_logical_ptr->RXpkt_status) ;
|
|
results->Pkt2_Transmit_Status = (UWORD)(params->TDA_logical_ptr->pkt2TDA.TXpkt_status) ;
|
|
goto ErrorExit ;
|
|
}
|
|
|
|
|
|
//
|
|
// Check for other errors in 2nd pkt
|
|
//
|
|
results->Pkt2_Receive_Status = (UWORD)(params->RDA2_logical_ptr->RXpkt_status) ;
|
|
results->Pkt2_Transmit_Status = (UWORD)(params->TDA_logical_ptr->pkt2TDA.TXpkt_status) ;
|
|
|
|
if (results->Pkt2_Transmit_Status & 0x044E)
|
|
{
|
|
err = SONIC_Loopback_Err_transmitting_2nd_pkt ;
|
|
goto ErrorExit ;
|
|
}
|
|
|
|
|
|
if (results->Pkt2_Receive_Status & 0x000C)
|
|
{
|
|
err = SONIC_Loopback_Err_receiving_2nd_pkt ;
|
|
goto ErrorExit ;
|
|
}
|
|
|
|
//
|
|
// Compare received data with transmitted data for the second packet
|
|
//
|
|
|
|
for (i = 0; i < 750; i++)
|
|
{
|
|
results->transmitted_data = (*params->TBA2_logical_ptr)[i] ;
|
|
results->received_data = (*params->RBA2_logical_ptr)[i] ;
|
|
|
|
results->offset_of_byte_in_err = i ;
|
|
|
|
if ((results->received_data != results->transmitted_data) || (results->received_data == 0) || (results->transmitted_data == 0))
|
|
{
|
|
err = SONIC_Loopback_Err_in_2nd_pkt_1st_fragment_data ;
|
|
goto ErrorExit ;
|
|
}
|
|
}
|
|
|
|
|
|
for (i = 750; i < 1500; i++)
|
|
{
|
|
results->transmitted_data = (*params->TBA2_logical_ptr)[i + 50] ; // Fragment 2 begins at location 800 in the TBA, thus the offset of 50
|
|
results->received_data = (*params->RBA2_logical_ptr)[i] ;
|
|
|
|
results->offset_of_byte_in_err = i ;
|
|
|
|
if ((results->received_data != results->transmitted_data) || (results->received_data == 0) || (results->transmitted_data == 0))
|
|
{
|
|
err = SONIC_Loopback_Err_in_2nd_pkt_2nd_fragment_data ;
|
|
goto ErrorExit ;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Prepare the first TDA for another transmission so we can generate an RBA Exceeded interrupt
|
|
// then link TDA2 back to it by setting the EOL bit of the link field to 0.
|
|
// TDA2 link already points to TDA1 from the initial set up.
|
|
//
|
|
|
|
if ((params->interrupt_mode) & (params->loopback_mode != MACMode))
|
|
{
|
|
params->TDA_logical_ptr->pkt1TDA.TXpkt_status = 0 ;
|
|
params->TDA_logical_ptr->pkt1TDA.TXpkt_link |= 0x0001 ; // Make the TDA1 the last one in the list
|
|
|
|
params->TDA_logical_ptr->pkt2TDA.TXpkt_link &= 0xFFFE ; // enable TDA2 to link back to TDA1
|
|
*(params->Sonic->regsArray[S_COMMAND]) = 0x000A ; // Start Transmission
|
|
|
|
results->CRBA0_value = *(params->Sonic->regsArray[S_CRBA0]) ; // Report what receive buffer is been used
|
|
results->CRBA1_value = *(params->Sonic->regsArray[S_CRBA1]) ;
|
|
results->RBWC0_value = *(params->Sonic->regsArray[S_RBWC0]) ;
|
|
results->RBWC1_value = *(params->Sonic->regsArray[S_RBWC1]) ;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// If we get to here then all is OK, so return no error.
|
|
//
|
|
MAC_Loopback_Exit :
|
|
err = SONIC_Loopback_Err_Ok;
|
|
|
|
//
|
|
// Do a final check that there were no interrupt errors and that we got all the interrupts we expected
|
|
//
|
|
if (params->interrupt_mode)
|
|
{
|
|
SUP_SetInterruptLevel(info,7) ; // Disable external interrupts.
|
|
*(params->Sonic->regsArray[S_INTMASK]) = 0x0000 ; // Disable all SONIC interrupts
|
|
params->interrupt_remove_function(info, &exceptionInfo, &exceptionArg) ;
|
|
SUP_SetInterruptLevel(info,originalInterruptLevel) ; // Enable external interrupts.
|
|
|
|
if (results->interrupt_error)
|
|
{
|
|
err = SONIC_Loopback_Err_Interrupt ;
|
|
goto ErrorExit ;
|
|
}
|
|
|
|
switch( params->loopback_mode )
|
|
{
|
|
case MACMode:
|
|
temp_register = results->interrupts_serviced ;
|
|
if (!(temp_register &= 0x1E00)) // Only check for what we really are sure of.
|
|
{
|
|
err = SONIC_Loopback_Err_Expected_Interrupt_not_received ;
|
|
goto ErrorExit ;
|
|
}
|
|
break;
|
|
|
|
case ENDECMode:
|
|
case TransceiverMode:
|
|
temp_register = results->interrupts_serviced ;
|
|
if (!(temp_register &= 0x1E60)) // Only check for what we really are sure of.
|
|
{
|
|
err = SONIC_Loopback_Err_Expected_Interrupt_not_received ;
|
|
goto ErrorExit ;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
err = SONIC_Loopback_Err_no_loopback_mode_specified ;
|
|
goto ErrorExit;
|
|
break;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
ErrorExit :
|
|
|
|
// Fill the Collision Count into the NumOfCollisionsDetected result field
|
|
NumOfCollisions = (results->Pkt1_Transmit_Status & 0xF800) ;
|
|
results->NumOfCollisionsDetected = (NumOfCollisions >> 11) ; // Only bits 11 thru 15 are valid
|
|
|
|
NumOfCollisions = (results->Pkt2_Transmit_Status & 0xF800) ;
|
|
results->NumOfCollisionsDetected += (NumOfCollisions >> 11) ; // Only bits 11 thru 15 are valid
|
|
|
|
// If we installed an interrupt handler earlier, now would be a good time to remove it.
|
|
|
|
if ((err) && (params->interrupt_mode)) // if there is no error then it is already removed
|
|
{
|
|
SUP_SetInterruptLevel(info,7) ; // Disable external interrupts.
|
|
*(params->Sonic->regsArray[S_INTMASK]) = 0x0000 ; // Disable all SONIC interrupts
|
|
params->interrupt_remove_function(info, &exceptionInfo, &exceptionArg) ;
|
|
SUP_SetInterruptLevel(info,originalInterruptLevel) ; // Enable external interrupts.
|
|
}
|
|
|
|
|
|
|
|
return(err);
|
|
}
|
|
|