mac-rom/OS/StartMgr/UnivTestEnv/SONIC_Loopback.c
Elliot Nunn 4325cdcc78 Bring in CubeE sources
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.
2017-12-26 09:52:23 +08:00

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);
}