/*
 *  Copyright (c) 1996-2007 Digi International Inc., All Rights Reserved
 *
 *  This software contains proprietary and confidential information of Digi
 *  International Inc.  By accepting transfer of this copy, Recipient agrees
 *  to retain this software in confidence, to prevent disclosure to others,
 *  and to make no use of this software other than that for which it was
 *  delivered.  This is an unpublished copyrighted work of Digi International
 *  Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
 *  prohibited.
 *
 *  Restricted Rights Legend
 *
 *  Use, duplication, or disclosure by the Government is subject to
 *  restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
 *  Technical Data and Computer Software clause at DFARS 252.227-7031 or
 *  subparagraphs (c)(1) and (2) of the Commercial Computer Software -
 *  Restricted Rights at 48 CFR 52.227-19, as applicable.
 *
 *  Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
 *
 * Description.
 * ===================================================================
 *    Power On Self Test routines.
 *                                                                        
 *                                                                        
 * Edit Date/Ver   Edit Description
 * ==============  ===================================================
 * JAD  08/30/97   Original
 * JAD  01/23/97   The blink_red and blink_green functions were moved to
 *                 the romstart.c file for the update image since NCC_POST.c
 *                 is not required for the update image.
 * JAD  03/24/97   I corrected a bug in the DMA memory to memory test.  After
 *                 waiting for the DMA completion, the program was comparing
 *                 the source data to the source data (which will never be in
 *                 error).  The program should have instead been comparing the
 *                 source data to the destination data.
 * JAD  04/10/98   I added code to disable the serial port test if there aren't
 *                 any serial ports available on the board.
 * JAD  05/27/98   I corrected some bugs in the Ethernet Loopback Test when 
 *                 running TX/RX DMA using NCC Revision 0.
 * LZ   10/06/99   Ported to NET_OS. Green Hill Software compiler
 *                 add #define OEM_POCKET  to be able to test parallel ports
 *
 * JZW	05/01/00	Version 1.5. Added function prototypes for the following 
 *					functions:
 *					    reset_serial, test_mem_to_mem_dma, test_parallel_ports,
 *					    test_gen_irq
 *
 * LZ  05/11/00    Took out all the #ifdef MENU_SYSTEM and code since we don't support it.
 * LZ  05/22/00    Added comments here and there, took out a lot unused functions.
 * LZ  06/14/00    Added #include <MII.h>.
 * SW  03/04/02    Remove the use of bit field  
 * DXL 04/16/02    Cleaned up variable declared but never reference; warnings generated by new compiler                
 * JFU 08/15/02    Corrected a reference to the bit field for chip id.
 * JZW 05/19/03    Replace all c++-style comments with c-style comments. This
 *                 eliminates GNU compiler warnings
 * JZW 06/23/04   serial loopback for the NS7520 is broken. Added code to ncc_post to
 *                bypass POST for serial if we are running on an NS7520
 *                to support this, added manifest constant IS_AN_NS7520
 * JZW 9/6/05     Fixed serial loopback POST. In test_serial_loopback, malloc the space
 *                for the receive and transmit buffers. Fixed a typeo in the third test, where
 *                character gap timer for channel one was mistakenly being shut off.
 *                In ncc_post_ser make sure that buffer descriptors are set up for interrupt.
 *                Set buffer gap timer to correct value for buffer size.
 * JZW 9/20/05    Added autodoc comments describing LED flashes for POST failures
 *
 */
#include <bsp_sys.h>
#if BSP_POST_TEST

#include <stdlib.h>
#include <reg_def.h>
#include <Dma_def.h>
#include <string.h>
#include <irqhand.h>
#include <MII.h>
#include <ncc_init.h>
#include <ncc_post.h>
#include <gpio_def.h>
#include <init.h>

/*ad*
 *
 * <section>NS7520 Rev A POST LED flash sequences</section>
 * 
 * @image na_post_ns7520.png
 *
 * @external
 * @overview    NS7520 POST 
 * @platform 	ns7520_a            
 * @category    BSP:POST:POST_ns7520_a
 * @since 6.3
 *
 *ad*/


#define  EFE_TX_SIZE_1   256
#define  EFE_TX_SIZE_2   256
#define  EFE_TX_SIZE_DMA 1000

#define  SER_TX_SIZE    4096
#define  SER_TX_NUM_BUF 8

#define EFE_TX_NUM_BUF  30
#define EFE_RX_NUM_BUFA 8
#define EFE_RX_NUM_BUFB 8
#define EFE_RX_NUM_BUFC 8
#define EFE_RX_NUM_BUFD 2
#define EFE_RX_SIZE_BUFA 512
#define EFE_RX_SIZE_BUFB 512
#define EFE_RX_SIZE_BUFC 1600
#define EFE_RX_SIZE_BUFD 1600

#define DO_SERIAL_LOOPBACK


static BOOLEAN memory_test (WORD32 *start, WORD32 *to);
static void restoreVector(void);

volatile WORD32 irqFlag[32];             /* Global flag set in Interrupt*/

volatile fb_buffer_desc_t efe_tx_bd[EFE_TX_NUM_BUF];
volatile fb_buffer_desc_t efe_rx_bd_a[EFE_RX_NUM_BUFA]; 
volatile fb_buffer_desc_t efe_rx_bd_b[EFE_RX_NUM_BUFB]; 
volatile fb_buffer_desc_t efe_rx_bd_c[EFE_RX_NUM_BUFC]; 
volatile fb_buffer_desc_t efe_rx_bd_d[EFE_RX_NUM_BUFD]; 
volatile fb_buffer_desc_t *efe_rx_bd_ptr;
   
volatile mm_buffer_desc_t dma_mm_bd[10][2];

volatile fb_buffer_desc_t ser_tx_bd[2][2], ser_rx_bd[2][2];
volatile fb_buffer_desc_t eni_fifo_bd[2];

volatile fb_buffer_desc_t pc_tx_bd[4][2];
volatile BYTE *pc_rx_buffer[4];
volatile WORD16 pc_rx_index[4];


/* Function prototypes added 05/01/00 */
static int test_mem_to_mem_dma (void);
static int test_parallel_ports (void);
static int test_gen_irq (void);
 


/*
 * This structure is used to store the results of
 * the POST test.
 */
static nccPostResultsType nccPostResults =
{
    POST_PASSED,
    0,
    0
};

 

 

/*  Function: static void ncc_post_dma1_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for DMA Channel 1 (Ethernet Receive DMA).
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_dma1_isr (void)

{

  /*if ((*NCC_DMA).dmasr1a.bits.ncip) */
  if (narm_read_reg (NARM_DSIER_REG, NARM_DSIER1A_ADDR, ncip))    
  {
      *NARM_DSIER1A_ADDR |= 0xf0000000;
    irqFlag[31]++;
  }

  /*if ((*NCC_DMA).dmasr1b.bits.ncip) */
  if (narm_read_reg (NARM_DSIER_REG, NARM_DSIER1B_ADDR, ncip)) 
  {
    *NARM_DSIER1B_ADDR |= 0xf0000000;
    irqFlag[31]++;
  }

  /*if ((*NCC_DMA).dmasr1c.bits.ncip) */
  if (narm_read_reg (NARM_DSIER_REG, NARM_DSIER1C_ADDR, ncip)) 
  {
    *NARM_DSIER1C_ADDR |= 0xf0000000;
    irqFlag[31]++;
  }

  /*if ((*NCC_DMA).dmasr1d.bits.ncip) */
  if (narm_read_reg (NARM_DSIER_REG, NARM_DSIER1D_ADDR, ncip)) 
  {
    *NARM_DSIER1D_ADDR |= 0xf0000000;
    irqFlag[31]++;
  }

  return;

}

/*  Function: static void ncc_post_dma2_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for DMA Channel 2 (Ethernet Receive DMA).
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_dma2_isr (void)

{

  /*if ((*NCC_DMA).dmasr2.bits.ncip) */
  if (narm_read_reg (NARM_DSIER_REG, NARM_DSIER2_ADDR, ncip)) 
  {
    irqFlag[30]++;
    *NARM_DSIER2_ADDR |= 0x80000000;
  }
  else 
    *NARM_DSIER2_ADDR = 0;

  return;

}

/*  Function: static void ncc_post_dma3_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for DMA Channel 3 (Parallel Port 1)
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_dma3_isr (void)

{

  /*if ((*NCC_DMA).dmasr3.bits.ncip) */
  if (narm_read_reg (NARM_DSIER_REG, NARM_DSIER3_ADDR, ncip)) 
    irqFlag[29]++;
  *NARM_DSIER3_ADDR |= 0xf0000000;
  return;

}


/*  Function: static void ncc_post_dma4_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for DMA Channel 4 (Parallel Port 2)
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_dma4_isr (void)

{

  /*if ((*NCC_DMA).dmasr4.bits.ncip) */
  if (narm_read_reg (NARM_DSIER_REG, NARM_DSIER4_ADDR, ncip))   
    irqFlag[28]++;
  *NARM_DSIER4_ADDR |= 0xf0000000;
  return;

}

/*  Function: static void ncc_post_dma5_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for DMA Channel 5 (Parallel Port 3)
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_dma5_isr (void)

{

  /*if ((*NCC_DMA).dmasr5.bits.ncip) */
  if (narm_read_reg (NARM_DSIER_REG, NARM_DSIER5_ADDR, ncip)) 
    irqFlag[27]++;
  *NARM_DSIER5_ADDR |= 0xf0000000;
  return;

}

/*  Function: static void ncc_post_dma6_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for DMA Channel 6 (Parallel Port 4)
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_dma6_isr (void)

{

  /*if ((*NCC_DMA).dmasr6.bits.ncip) */
  if (narm_read_reg (NARM_DSIER_REG, NARM_DSIER6_ADDR, ncip)) 
    irqFlag[26]++;
  *NARM_DSIER6_ADDR |= 0xf0000000;
  return;

}

/*  Function: static void ncc_post_dma7_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for DMA Channel 7 (Serial Channel 1 Receiver)
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_dma7_isr (void)

{

  /*if ((*NCC_DMA).dmasr7.bits.ncip) */
  if (narm_read_reg (NARM_DSIER_REG, NARM_DSIER7_ADDR, ncip)) 
    irqFlag[25]++;
  *NARM_DSIER7_ADDR |= 0xf0000000;
  return;

}

/*  Function: static void ncc_post_dma8_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for DMA Channel 8 (Serial Channel 1 Transmitter)
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_dma8_isr (void)

{

  /* if ((*NCC_DMA).dmasr8.bits.ncip) */
  if (narm_read_reg (NARM_DSIER_REG, NARM_DSIER8_ADDR, ncip)) 
    irqFlag[24]++;
  *NARM_DSIER8_ADDR |= 0xf0000000;
  return;

}

/*  Function: static void ncc_post_dma9_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for DMA Channel 9 (Serial Channel 2 Receiver)
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_dma9_isr (void)

{

  /*if ((*NCC_DMA).dmasr9.bits.ncip) */
  if (narm_read_reg (NARM_DSIER_REG, NARM_DSIER9_ADDR, ncip)) 
    irqFlag[23]++;
  *NARM_DSIER9_ADDR |= 0xf0000000;
  return;

}

/*  Function: static void ncc_post_dma10_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for DMA Channel 10 (Serial Transmitter)
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_dma10_isr (void)

{

  /* if ((*NCC_DMA).dmasr10.bits.ncip) */
  if (narm_read_reg (NARM_DSIER_REG, NARM_DSIER10_ADDR, ncip)) 
    irqFlag[22]++;
  *NARM_DSIER10_ADDR |= 0xf0000000;
  return;

}


/*  Function: static void ncc_post_eni_1_isr (void)
 *
 *  Description:
 *     This routine provides the interrupt service routine handler
 *     while the POST test is running.
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_eni_1_isr (void)

{

  WORD32 temp32;

  irqFlag[21]++;

  /* if ((*NCC_PC).ppcr[0].bits.acki == 1) */
  if (narm_read_reg (NARM_PPCR_REG, NARM_PPCR_ADDR(0), acki) == 1)     
  {

    /* Put channel into input mode */
      temp32 = *NARM_PPCR_ADDR(0);
    temp32 &= 0xffffffef;
    temp32 |= 0x00200000;
    *NARM_PPCR_ADDR(0) = temp32;

    /* Read the Data Value */
    pc_rx_buffer[0][pc_rx_index[0]] = *(char *)NARM_PPDR_ADDR(0); /*(*NCC_PC).ppdr[0].read_data.data*/
    pc_rx_index[0]++;

    /* Put channel into output mode */
    temp32 &= 0xffdfffff;
    *NARM_PPCR_ADDR(0) = temp32;

    /* Acknowledge the data */
    temp32 |= 0x00000010;
    *NARM_PPCR_ADDR(0) = temp32;
  }

  return;

}


/*  Function: static void ncc_post_eni_2_isr (void)
 *
 *  Description:
 *     This routine provides the interrupt service routine handler
 *     while the POST test is running.
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_eni_2_isr (void)

{

  WORD32 temp32;

  irqFlag[20]++;

  /* if ((*NCC_PC).ppcr[1].bits.acki == 1) */
  if (narm_read_reg (NARM_PPCR_REG, NARM_PPCR_ADDR(1), acki) == 1) 
  {

    /* Put channel into input mode */
      temp32 = *NARM_PPCR_ADDR(1);
    temp32 &= 0xffffffef;
    temp32 |= 0x00200000;
    *NARM_PPCR_ADDR(1) = temp32;

    /* Read the Data Value */
    pc_rx_buffer[1][pc_rx_index[1]] = *(char *)NARM_PPDR_ADDR(1);/*(*NCC_PC).ppdr[1].read_data.data*/
    pc_rx_index[1]++;

    /* Put channel into output mode */
    temp32 &= 0xffdfffff;
    *NARM_PPCR_ADDR(1) = temp32;

    /* Acknowledge the data */
    temp32 |= 0x00000010;
    *NARM_PPCR_ADDR(1) = temp32;
  }

  return;

}



/*  Function: static void ncc_post_eni_3_isr (void)
 *
 *  Description:
 *     This routine provides the interrupt service routine handler
 *     while the POST test is running.
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_eni_3_isr (void)

{

  WORD32 temp32;

  irqFlag[19]++;

  /* if ((*NCC_PC).ppcr[2].bits.acki == 1) */
  if (narm_read_reg (NARM_PPCR_REG, NARM_PPCR_ADDR(2), acki) == 1) 
  {

    /* Put channel into input mode */
      temp32 = *NARM_PPCR_ADDR(2);
    temp32 &= 0xffffffef;
    temp32 |= 0x00200000;
    *NARM_PPCR_ADDR(2) = temp32;

    /* Read the Data Value */
    pc_rx_buffer[2][pc_rx_index[2]] = *(char *)NARM_PPDR_ADDR(2);/*(*NCC_PC).ppdr[2].read_data.data*/
    pc_rx_index[2]++;

    /* Put channel into output mode */
    temp32 &= 0xffdfffff;
    *NARM_PPDR_ADDR(2) = temp32;

    /* Acknowledge the data */
    temp32 |= 0x00000010;
    *NARM_PPDR_ADDR(2) = temp32;
  }

  return;

}



/*  Function: static void ncc_post_eni_4_isr (void)
 *
 *  Description:
 *     This routine provides the interrupt service routine handler
 *     while the POST test is running.
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_eni_4_isr (void)

{

  WORD32 temp32;

  irqFlag[18]++;

  /* if ((*NCC_PC).ppcr[3].bits.acki == 1) */
  if (narm_read_reg (NARM_PPCR_REG, NARM_PPCR_ADDR(3), acki) == 1) 
  {

    /* Put channel into input mode */
      temp32 = *NARM_PPCR_ADDR(3);
    temp32 &= 0xffffffef;
    temp32 |= 0x00200000;
    *NARM_PPCR_ADDR(3) = temp32;

    /* Read the Data Value */
    pc_rx_buffer[3][pc_rx_index[3]] = *(char *)NARM_PPDR_ADDR(3);/*(*NCC_PC).ppdr[3].read_data.data*/
    pc_rx_index[3]++;

    /* Put channel into output mode */
    temp32 &= 0xffdfffff;
    *NARM_PPCR_ADDR(3) = temp32;

    /* Acknowledge the data */
    temp32 |= 0x00000010;
    *NARM_PPCR_ADDR(3) = temp32;
  }


  return;

}



/*  Function: static void ncc_post_enet_rx_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for the Ethernet Receiver.
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_enet_rx_isr (void)

{

  irqFlag[17]++;

  return;

}



/*  Function: static void ncc_post_ser_1_rx_isr (void)
 * 
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for the Serial Channel 1 Receiver
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_ser_1_rx_isr (void)

{

  irqFlag[15]++;

  return;

}



/*  Function: static void ncc_post_ser_1_tx_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for the Serial Channel 1 Transmitter
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_ser_1_tx_isr (void)

{

  irqFlag[14]++;

  return;

}



/*  Function: static void ncc_post_ser_2_rx_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for the Serial Channel 2 Receiver
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_ser_2_rx_isr (void)

{

  irqFlag[13]++;

  return;

}



/*  Function: static void ncc_post_ser_2_tx_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for the Serial Channel 2 Transmitter
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_ser_2_tx_isr (void)

{

  irqFlag[12]++;

  return;

}

/*  Function: static void ncc_post_wdog_isr (void)
 *
 *  Description:
 *     This routine provides the POST interrupt service routine handler
 *     for the Watch Dog Timer.
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_wdog_isr (void)

{

  irqFlag[6]++;
  *NARM_GSWSR_ADDR = 0x5a;
  *NARM_GSWSR_ADDR = 0xa5;
  return;

}



/*  Function: static void ncc_post_timer1_isr (void)
 *
 *  Description:
 *     This routine provides the interrupt service routine handler
 *     while the POST test is running.
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_timer1_isr (void)

{

  irqFlag[5]++;

  /* (*NCC_GEN).tsr1.bits.tip = 1; */
  *NARM_T1SR_ADDR |= 0x40000000;
  
  return;

}



/*  Function: static void ncc_post_timer2_isr (void)
 *
 *  Description:
 *     This routine provides the interrupt service routine handler
 *     while the POST test is running.
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      none
 */

static void ncc_post_timer2_isr (void)

{

  irqFlag[4]++;

  /* (*NCC_GEN).tsr2.bits.tip = 1; */
  *NARM_T2SR_ADDR |= 0x40000000;

  return;

}





/*  Function: void report_error (WORD32 test, WORD32 error)
 *
 *  Description:
 *
 *      This function stores the test results into a structure
 *      that is eventually passed back to the application that
 *      started the POST.
 *
 *  Parameters:
 *
 *     test         indicates which test function failed
 *     error        indicates which part of the test function failed.
 *  
 *  Return Value:
 *
 *     none
 *
 */

static void report_error (WORD32 test, WORD32 error)
{
     nccPostResults.ccode = POST_FAILED;
     nccPostResults.testCode = test;
     nccPostResults.subtestCode = error;
}









/*  Function:  BOOLEAN memory_test (WORD32 *from, WORD32 *to)
 *
 *  Description:
 *
 *      Executes a memory test of the memory region passed as parameters
 *
 *  Parameters:
 *      WORD32 *from - starting memory location for testing
 *      WORD32 *to   - ending memory location
 *
 *  Return Values:
 *      0 : Test Pass
 *      1 : Test Fail
 */

static BOOLEAN memory_test (WORD32 *from, WORD32 *to)
{
    volatile WORD32 *ram_addr;
     
    /*  First load an address pattern into ram */
    for (ram_addr = from; ram_addr < to; ram_addr++)
    {
        *ram_addr =(unsigned long) ram_addr;
    }

    /*  Now verify the address pattern and load the inversion */
    for (ram_addr = from; ram_addr < to; ram_addr++) 
    {
        if (*ram_addr != (WORD32) ram_addr)
        {
            return 1;
        }

        *ram_addr = (WORD32)ram_addr ^ 0xffffffff;
    }

    /*  Now verify the inverted address pattern and load zero */
    for (ram_addr = from; ram_addr < to; ram_addr++) 
    {
        if (*ram_addr != ((WORD32)ram_addr ^ 0xffffffff))
        {
            return 1;
        }

        *ram_addr = 0;
    }

    return 0;
}


/*  Function: int test_dma_ram
 *
 *  Description:
 *     This routine executes a simple memory test of the internal DMA RAM block.
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *      POST_PASSED
 *      POST_FAILED
 */

static int test_dma_ram(void)
{  
    WORD32 test = 1;
    WORD32 error;

    /* (*NCC_GEN).scr.bits.dmatst = 1; */
    narm_write_reg (NARM_GSCR_REG, NARM_GSCR_ADDR, dmatst, 1);

    if (memory_test ((WORD32 *)DMA_BASE, (WORD32 *)(DMA_BASE + 0x200)) == TRUE)
    {
        error = 1;
        report_error (test, error);
        narm_write_reg (NARM_GSCR_REG, NARM_GSCR_ADDR, dmatst, 0);
        return POST_FAILED;
    }
      
    /* (*NCC_GEN).scr.bits.dmatst = 0; */
    narm_write_reg (NARM_GSCR_REG, NARM_GSCR_ADDR, dmatst, 0);

    return POST_PASSED;
}








/*
 *
 *  Function: void test_mem_to_mem_dma_stop(void)
 *
 *  Description:
 *
 *      Shut off all DMA channels used by test_mem_to_mem_dma(),
 *      disable interrupts enabled by test, stop timers used
 *      by test.
 *
 *  Parameters:
 *
 *      none
 *
 *  Return Values:
 *
 *      none
 *
 */
static void test_mem_to_mem_dma_stop(void)
{
    /* (*NCC_GEN).i_er.bits.timer_1 = 0; */    /* Disable Interrupts*/
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer1, 0);
    /*(*NCC_GEN).i_er.bits.timer_2 = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer2, 0);
    *NARM_T1CR_ADDR = 0;
    *NARM_T2CR_ADDR = 0;

    /* Shut down the DMA controllers */

    /* (*NCC_GEN).i_er.bits.dma1  = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma1, 0);
    /* (*NCC_GEN).i_er.bits.dma2  = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma2, 0);
    /* (*NCC_GEN).i_er.bits.dma3  = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma3, 0);
    /* (*NCC_GEN).i_er.bits.dma4  = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma4, 0);
    /* (*NCC_GEN).i_er.bits.dma5  = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma5, 0);
    /* (*NCC_GEN).i_er.bits.dma6  = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma6, 0);
    /* (*NCC_GEN).i_er.bits.dma7  = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma7, 0);
    /* (*NCC_GEN).i_er.bits.dma8  = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma8, 0);
    /* (*NCC_GEN).i_er.bits.dma9  = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma9, 0);
    /* (*NCC_GEN).i_er.bits.dma10 = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma10, 0);

    *NARM_DSIER3_ADDR = 0xf0000000;
    *NARM_DSIER4_ADDR = 0xf0000000;
    *NARM_DSIER5_ADDR = 0xf0000000;
    *NARM_DSIER6_ADDR = 0xf0000000;
    *NARM_DSIER7_ADDR = 0xf0000000;
    *NARM_DSIER8_ADDR = 0xf0000000;
    *NARM_DSIER9_ADDR = 0xf0000000;
    *NARM_DSIER10_ADDR = 0xf0000000;

    *NARM_DCR3_ADDR = 0;
    *NARM_DCR4_ADDR = 0;
    *NARM_DCR5_ADDR = 0;
    *NARM_DCR6_ADDR = 0;
    *NARM_DCR7_ADDR = 0;
    *NARM_DCR8_ADDR = 0;
    *NARM_DCR9_ADDR = 0;
    *NARM_DCR10_ADDR = 0;     
}



/*  Function: int test_mem_to_mem_dma
 *
 *  Description:
 *     This routine executes a memory-to-memory dma test using all DMA channels
 *     simultaneously.  A pattern is generated to be moved from one block to 
 *     another.  All destination blocks are verified after the dma operation
 *     is complete.
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *
 *      POST_PASSED
 *      POST_FAILED
 */

static int test_mem_to_mem_dma(void)
{

    register WORD32 timeout;

    WORD32 test  = 2;    
    WORD32 error = 0;
    WORD32 temp32;

    WORD16 i;
    BYTE temp8;

    BYTE     dma_mm_buffer[10][400];

    test_mem_to_mem_dma_stop();

    /* Clear the interrupt flags */
    for (i = 0; i < 32; i++)
      irqFlag[i] = 0;

    /* Allow the timers to operate */
    /* (*NCC_GEN).i_er.bits.timer_1 = 1; */   /* Enable Interrupts*/
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer1, 1);
    *NARM_T1CR_ADDR = 0xd0000010;   /* IRQenable, start timer,~.5ms*/

    /* (*NCC_GEN).i_er.bits.timer_2 = 1;  */  /* Enable Interrupts*/
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer2, 1);
    *NARM_T2CR_ADDR = 0xd0000020;   /* IRQenable, start timer,~1ms*/

    /* First BUILD the DMA buffer descriptors */

    dma_mm_bd[2][0].word_1.bits.wrap   = 0;
    dma_mm_bd[2][0].word_1.bits.intr   = 0;
    dma_mm_bd[2][0].word_1.bits.last   = 1;
    dma_mm_bd[2][0].word_1.bits.sbp    = (unsigned)&dma_mm_buffer[2][0];
    dma_mm_bd[2][0].word_2.bits.status = 0;
    dma_mm_bd[2][0].word_2.bits.full   = 1;
    dma_mm_bd[2][0].word_2.bits.buflen = 100;    
    dma_mm_bd[2][0].ddp                = &dma_mm_buffer[2][200];

    dma_mm_bd[2][1].word_1.bits.wrap   = 1;
    dma_mm_bd[2][1].word_1.bits.intr   = 1;
    dma_mm_bd[2][1].word_1.bits.last   = 1;
    dma_mm_bd[2][1].word_1.bits.sbp    =(unsigned) &dma_mm_buffer[2][100];
    dma_mm_bd[2][1].word_2.bits.status = 0;
    dma_mm_bd[2][1].word_2.bits.full   = 1;
    dma_mm_bd[2][1].word_2.bits.buflen = 100;    
    dma_mm_bd[2][1].ddp                = &dma_mm_buffer[2][300];

    dma_mm_bd[3][0].word_1.bits.wrap   = 0;
    dma_mm_bd[3][0].word_1.bits.intr   = 0;
    dma_mm_bd[3][0].word_1.bits.last   = 1;
    dma_mm_bd[3][0].word_1.bits.sbp    = (unsigned)&dma_mm_buffer[3][0];
    dma_mm_bd[3][0].word_2.bits.status = 0;
    dma_mm_bd[3][0].word_2.bits.full   = 1;
    dma_mm_bd[3][0].word_2.bits.buflen = 99;    
    dma_mm_bd[3][0].ddp                = &dma_mm_buffer[3][200];

    dma_mm_bd[3][1].word_1.bits.wrap   = 1;
    dma_mm_bd[3][1].word_1.bits.intr   = 1;
    dma_mm_bd[3][1].word_1.bits.last   = 1;
    dma_mm_bd[3][1].word_1.bits.sbp    = (unsigned)&dma_mm_buffer[3][100];
    dma_mm_bd[3][1].word_2.bits.status = 0;
    dma_mm_bd[3][1].word_2.bits.full   = 1;
    dma_mm_bd[3][1].word_2.bits.buflen = 99;    
    dma_mm_bd[3][1].ddp                = &dma_mm_buffer[3][300];

    dma_mm_bd[4][0].word_1.bits.wrap   = 0;
    dma_mm_bd[4][0].word_1.bits.intr   = 0;
    dma_mm_bd[4][0].word_1.bits.last   = 1;
    dma_mm_bd[4][0].word_1.bits.sbp    = (unsigned)&dma_mm_buffer[4][2];
    dma_mm_bd[4][0].word_2.bits.status = 0;
    dma_mm_bd[4][0].word_2.bits.full   = 1;
    dma_mm_bd[4][0].word_2.bits.buflen = 98;    
    dma_mm_bd[4][0].ddp                = &dma_mm_buffer[4][202];

    dma_mm_bd[4][1].word_1.bits.wrap   = 1;
    dma_mm_bd[4][1].word_1.bits.intr   = 1;
    dma_mm_bd[4][1].word_1.bits.last   = 1;
    dma_mm_bd[4][1].word_1.bits.sbp    = (unsigned)&dma_mm_buffer[4][102];
    dma_mm_bd[4][1].word_2.bits.status = 0;
    dma_mm_bd[4][1].word_2.bits.full   = 1;
    dma_mm_bd[4][1].word_2.bits.buflen = 98;    
    dma_mm_bd[4][1].ddp                = &dma_mm_buffer[4][302];

    dma_mm_bd[5][0].word_1.bits.wrap   = 0;
    dma_mm_bd[5][0].word_1.bits.intr   = 0;
    dma_mm_bd[5][0].word_1.bits.last   = 1;
    dma_mm_bd[5][0].word_1.bits.sbp    = (unsigned)&dma_mm_buffer[5][3];
    dma_mm_bd[5][0].word_2.bits.status = 0;
    dma_mm_bd[5][0].word_2.bits.full   = 1;
    dma_mm_bd[5][0].word_2.bits.buflen = 97;    
    dma_mm_bd[5][0].ddp                = &dma_mm_buffer[5][203];

    dma_mm_bd[5][1].word_1.bits.wrap   = 1;
    dma_mm_bd[5][1].word_1.bits.intr   = 1;
    dma_mm_bd[5][1].word_1.bits.last   = 1;
    dma_mm_bd[5][1].word_1.bits.sbp    = (unsigned)&dma_mm_buffer[5][103];
    dma_mm_bd[5][1].word_2.bits.status = 0;
    dma_mm_bd[5][1].word_2.bits.full   = 1;
    dma_mm_bd[5][1].word_2.bits.buflen = 97;    
    dma_mm_bd[5][1].ddp                = &dma_mm_buffer[5][303];

    dma_mm_bd[6][0].word_1.bits.wrap   = 0;
    dma_mm_bd[6][0].word_1.bits.intr   = 0;
    dma_mm_bd[6][0].word_1.bits.last   = 1;
    dma_mm_bd[6][0].word_1.bits.sbp    =(unsigned) &dma_mm_buffer[6][3];
    dma_mm_bd[6][0].word_2.bits.status = 0;
    dma_mm_bd[6][0].word_2.bits.full   = 1;
    dma_mm_bd[6][0].word_2.bits.buflen = 97;    
    dma_mm_bd[6][0].ddp                = &dma_mm_buffer[6][203];

    dma_mm_bd[6][1].word_1.bits.wrap   = 1;
    dma_mm_bd[6][1].word_1.bits.intr   = 1;
    dma_mm_bd[6][1].word_1.bits.last   = 1;
    dma_mm_bd[6][1].word_1.bits.sbp    = (unsigned)&dma_mm_buffer[6][103];
    dma_mm_bd[6][1].word_2.bits.status = 0;
    dma_mm_bd[6][1].word_2.bits.full   = 1;
    dma_mm_bd[6][1].word_2.bits.buflen = 97;    
    dma_mm_bd[6][1].ddp                = &dma_mm_buffer[6][303];

    dma_mm_bd[7][0].word_1.bits.wrap   = 0;
    dma_mm_bd[7][0].word_1.bits.intr   = 0;
    dma_mm_bd[7][0].word_1.bits.last   = 1;
    dma_mm_bd[7][0].word_1.bits.sbp    = (unsigned)&dma_mm_buffer[7][3];
    dma_mm_bd[7][0].word_2.bits.status = 0;
    dma_mm_bd[7][0].word_2.bits.full   = 1;
    dma_mm_bd[7][0].word_2.bits.buflen = 97;    
    dma_mm_bd[7][0].ddp                = &dma_mm_buffer[7][203];

    dma_mm_bd[7][1].word_1.bits.wrap   = 1;
    dma_mm_bd[7][1].word_1.bits.intr   = 1;
    dma_mm_bd[7][1].word_1.bits.last   = 1;
    dma_mm_bd[7][1].word_1.bits.sbp    = (unsigned)&dma_mm_buffer[7][103];
    dma_mm_bd[7][1].word_2.bits.status = 0;
    dma_mm_bd[7][1].word_2.bits.full   = 1;
    dma_mm_bd[7][1].word_2.bits.buflen = 97;    
    dma_mm_bd[7][1].ddp                = &dma_mm_buffer[7][303];

    dma_mm_bd[8][0].word_1.bits.wrap   = 0;
    dma_mm_bd[8][0].word_1.bits.intr   = 0;
    dma_mm_bd[8][0].word_1.bits.last   = 1;
    dma_mm_bd[8][0].word_1.bits.sbp    = (unsigned)&dma_mm_buffer[8][3];
    dma_mm_bd[8][0].word_2.bits.status = 0;
    dma_mm_bd[8][0].word_2.bits.full   = 1;
    dma_mm_bd[8][0].word_2.bits.buflen = 97;    
    dma_mm_bd[8][0].ddp                = &dma_mm_buffer[8][203];

    dma_mm_bd[8][1].word_1.bits.wrap   = 1;
    dma_mm_bd[8][1].word_1.bits.intr   = 1;
    dma_mm_bd[8][1].word_1.bits.last   = 1;
    dma_mm_bd[8][1].word_1.bits.sbp    =(unsigned) &dma_mm_buffer[8][103];
    dma_mm_bd[8][1].word_2.bits.status = 0;
    dma_mm_bd[8][1].word_2.bits.full   = 1;
    dma_mm_bd[8][1].word_2.bits.buflen = 97;    
    dma_mm_bd[8][1].ddp                = &dma_mm_buffer[8][303];

    dma_mm_bd[9][0].word_1.bits.wrap   = 0;
    dma_mm_bd[9][0].word_1.bits.intr   = 0;
    dma_mm_bd[9][0].word_1.bits.last   = 1;
    dma_mm_bd[9][0].word_1.bits.sbp    = (unsigned)&dma_mm_buffer[9][3];
    dma_mm_bd[9][0].word_2.bits.status = 0;
    dma_mm_bd[9][0].word_2.bits.full   = 1;
    dma_mm_bd[9][0].word_2.bits.buflen = 97;    
    dma_mm_bd[9][0].ddp                = &dma_mm_buffer[9][203];

    dma_mm_bd[9][1].word_1.bits.wrap   = 1;
    dma_mm_bd[9][1].word_1.bits.intr   = 1;
    dma_mm_bd[9][1].word_1.bits.last   = 1;
    dma_mm_bd[9][1].word_1.bits.sbp    =(unsigned) &dma_mm_buffer[9][103];
    dma_mm_bd[9][1].word_2.bits.status = 0;
    dma_mm_bd[9][1].word_2.bits.full   = 1;
    dma_mm_bd[9][1].word_2.bits.buflen = 97;    
    dma_mm_bd[9][1].ddp                = &dma_mm_buffer[9][303];

    /* Now Generate the Source Data */

    temp8 = 0;

    for (temp32 = 0; temp32 < 200; temp32 = temp32 + 1) {
      dma_mm_buffer[2][temp32] = temp8 + 3;
      dma_mm_buffer[3][temp32] = temp8 + 4;
      dma_mm_buffer[4][temp32] = temp8 + 5;
      dma_mm_buffer[5][temp32] = temp8 + 6;
      dma_mm_buffer[6][temp32] = temp8 + 7;
      dma_mm_buffer[7][temp32] = temp8 + 8;
      dma_mm_buffer[8][temp32] = temp8 + 9;
      dma_mm_buffer[9][temp32] = temp8 + 10;
      temp8++;
      if ((BYTE)temp32 == 0xff)
        temp8++;
    }

    /* Clear the Desination Data*/

    for (temp32 = 200; temp32 < 400; temp32 = temp32 + 1) {
      dma_mm_buffer[2][temp32] = 0;
      dma_mm_buffer[3][temp32] = 0;
      dma_mm_buffer[4][temp32] = 0;
      dma_mm_buffer[5][temp32] = 0;
      dma_mm_buffer[6][temp32] = 0;
      dma_mm_buffer[7][temp32] = 0;
      dma_mm_buffer[8][temp32] = 0;
      dma_mm_buffer[9][temp32] = 0;
    }

    /* (*NCC_GEN).i_er.bits.dma1  = 1; */      /* Enable Interrupts */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma1, 1);
    /* (*NCC_GEN).i_er.bits.dma2  = 1; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma2, 1);
    /* (*NCC_GEN).i_er.bits.dma3  = 1; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma3, 1);
    /* (*NCC_GEN).i_er.bits.dma4  = 1; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma4, 1);
    /* (*NCC_GEN).i_er.bits.dma5  = 1; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma5, 1);
    /* (*NCC_GEN).i_er.bits.dma6  = 1; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma6, 1);
    /* (*NCC_GEN).i_er.bits.dma7  = 1; */      
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma7, 1);
    /* (*NCC_GEN).i_er.bits.dma8  = 1; */      
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma8, 1);
    /* (*NCC_GEN).i_er.bits.dma9  = 1; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma9, 1);
    /* (*NCC_GEN).i_er.bits.dma10 = 1; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma10, 1);

    
    /* Setup the DMA Controllers */

    *NARM_DCR3_ADDR = 0;
    *NARM_DBDP3_ADDR     = (unsigned long )dma_mm_bd[2];
    *NARM_DCR3_ADDR = 0x8a000000;
    *NARM_DSIER3_ADDR = 0xf0500000;

    *NARM_DCR4_ADDR = 0;
    *NARM_DBDP4_ADDR     = (unsigned long )dma_mm_bd[3];
    *NARM_DCR4_ADDR = 0x8a000000;
    *NARM_DSIER4_ADDR = 0xf0500000;

    *NARM_DCR5_ADDR = 0;
    *NARM_DBDP5_ADDR    = (unsigned long )dma_mm_bd[4];
    *NARM_DCR5_ADDR = 0x8a000000;
    *NARM_DSIER5_ADDR = 0xf0500000;

    *NARM_DCR6_ADDR = 0;
    *NARM_DBDP6_ADDR     =(unsigned long ) dma_mm_bd[5];
    *NARM_DCR6_ADDR = 0x8a000000;
    *NARM_DSIER6_ADDR = 0xf0500000;

    *NARM_DCR7_ADDR = 0;
    *NARM_DBDP7_ADDR     = (unsigned long )dma_mm_bd[6];
    *NARM_DCR7_ADDR = 0x8a000000;
    *NARM_DSIER7_ADDR = 0xf0500000;

    *NARM_DCR8_ADDR = 0;
    *NARM_DBDP8_ADDR     = (unsigned long )dma_mm_bd[7];
    *NARM_DCR8_ADDR = 0x8a000000;
    *NARM_DSIER8_ADDR = 0xf0500000;

    *NARM_DCR9_ADDR = 0;
    *NARM_DBDP9_ADDR     = (unsigned long )dma_mm_bd[8];
    *NARM_DCR9_ADDR = 0x8a000000;
    *NARM_DSIER9_ADDR = 0xf0500000;

    *NARM_DCR10_ADDR = 0;
    *NARM_DBDP10_ADDR     =(unsigned long ) dma_mm_bd[9];
    *NARM_DCR10_ADDR = 0x8a000000;
    *NARM_DSIER10_ADDR = 0xf0500000;

    /* Now wait for the Operation to complete */

    timeout = 1500000;
 
    while (  ( !irqFlag[29]
            || !irqFlag[28]
            || !irqFlag[27]
            || !irqFlag[26]
            || !irqFlag[25]
            || !irqFlag[24]
            || !irqFlag[23]
            || !irqFlag[22] ) && timeout)

       timeout--;

   if (!timeout)
    {
      error = 1;
      report_error (test, error);
      test_mem_to_mem_dma_stop();
      return POST_FAILED;
    }

    /* Now Verify the Receive Data */

    for (i = 0; i < 200; i = i + 100)
    {
        temp8 = i + 0;
        for (temp32 = (WORD32)i + 0; temp32 < (WORD32)i + 100; temp32 = temp32 + 1) {
          if (dma_mm_buffer[2][temp32 + 200] != temp8 + 3) {
            error = 2;
            report_error (test, error);
            test_mem_to_mem_dma_stop();
            return POST_FAILED;
          }      
          temp8++;
          if ((BYTE)temp32 == 0xff)
            temp8++;
        }
    
        temp8 = i;
        for (temp32 = (WORD32)i; temp32 < (WORD32)i + 99; temp32 = temp32 + 1) {
          if (dma_mm_buffer[3][temp32 + 200] != temp8 + 4) {
            error = 3;
            report_error (test, error);
            test_mem_to_mem_dma_stop();
            return POST_FAILED;
          }      
          temp8++;
          if ((BYTE)temp32 == 0xff)
            temp8++;
        }
    
        temp8 = i + 2;
        for (temp32 = (WORD32)i + 2; temp32 < (WORD32)i + 100; temp32 = temp32 + 1) {
          if (dma_mm_buffer[4][temp32 + 200] != temp8 + 5) {
            error = 4;
            report_error (test, error);
            test_mem_to_mem_dma_stop();
            return POST_FAILED;
          }      
          temp8++;
          if ((BYTE)temp32 == 0xff)
            temp8++;
        }
    
        temp8 = i + 3;
        for (temp32 = (WORD32)i + 3; temp32 < (WORD32)i + 100; temp32 = temp32 + 1) {
          if (dma_mm_buffer[5][temp32 + 200] != temp8 + 6) {
            error = 5;
            report_error (test, error);
            test_mem_to_mem_dma_stop();
            return POST_FAILED;
          }      
          temp8++;
          if ((BYTE)temp32 == 0xff)
            temp8++;
        }
    
        temp8 = i + 4;
        for (temp32 = (WORD32)i + 4; temp32 < (WORD32)i + 100; temp32 = temp32 + 1) {
          if (dma_mm_buffer[6][temp32 + 200] != temp8 + 7) {
            error = 6;
            report_error (test, error);
            test_mem_to_mem_dma_stop();
            return POST_FAILED;
          }      
          temp8++;
          if ((BYTE)temp32 == 0xff)
            temp8++;
        }
    
        temp8 = i + 5;
        for (temp32 = (WORD32)i + 5; temp32 < (WORD32)i + 100; temp32 = temp32 + 1) {
          if (dma_mm_buffer[7][temp32 + 200] != temp8 + 8) {
            error = 7;
            report_error (test, error);
            test_mem_to_mem_dma_stop();
            return POST_FAILED;
          }      
          temp8++;
          if ((BYTE)temp32 == 0xff)
            temp8++;
        }
    
        temp8 = i + 6;
        for (temp32 = (WORD32)i + 6; temp32 < (WORD32)i + 100; temp32 = temp32 + 1) {
          if (dma_mm_buffer[8][temp32 + 200] != temp8 + 9) {
            error = 8;
            report_error (test, error);
            test_mem_to_mem_dma_stop();
            return POST_FAILED;
          }      
          temp8++;
          if ((BYTE)temp32 == 0xff)
            temp8++;
        }
    
        temp8 = i + 7;
        for (temp32 = (WORD32)i + 7; temp32 < (WORD32)i + 100; temp32 = temp32 + 1) {
          if (dma_mm_buffer[9][temp32 + 200] != temp8 + 10) {
            error = 9;
            report_error (test, error);
            test_mem_to_mem_dma_stop();
            return POST_FAILED;
          }      
          temp8++;
          if ((BYTE)temp32 == 0xff)
            temp8++;
        }
    }

    /* Shut down the timers */

    test_mem_to_mem_dma_stop();

    return POST_PASSED;

}










/*
 *
 *  Function: void test_parallel_ports_cleanup(void)
 *
 *  Description:
 *
 *      Shut down the hardware used by the test_parallel_ports()
 *      function.
 *
 *  Parameters:
 *
 *      none
 *
 *  Return Values:
 *
 *      none
 *
 */

static void test_parallel_ports_cleanup(void)
{
    /* Shut down the timers */
    /* (*NCC_GEN).i_er.bits.timer_1 = 0;  */   /* Disable Interrupts */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer1, 0);
    /* (*NCC_GEN).i_er.bits.timer_2 = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer2, 1);
    *NARM_T1CR_ADDR = 0;
    *NARM_T2CR_ADDR = 0;
    
    /* Shut down the parallel ports */
    /* (*NCC_GEN).i_er.bits.pc1 = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, eni_port1, 0);
    /* (*NCC_GEN).i_er.bits.pc2 = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, eni_port2, 0);
    /* (*NCC_GEN).i_er.bits.pc3 = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, eni_port3, 0);
    /* (*NCC_GEN).i_er.bits.pc4 = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, eni_port4, 0);
    
    *NARM_PPCR_ADDR(0) = 0;
    *NARM_PPCR_ADDR(1) = 0;
    *NARM_PPCR_ADDR(2) = 0;
    *NARM_PPCR_ADDR(3) = 0;
    
    /* Shut down the dma channels */
    /* (*NCC_GEN).i_er.bits.dma3 = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma3, 0);
    /* (*NCC_GEN).i_er.bits.dma4 = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma4, 0);
    /* (*NCC_GEN).i_er.bits.dma5 = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma5, 0);
    /* (*NCC_GEN).i_er.bits.dma6 = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma6, 0);
    
    *NARM_DCR3_ADDR = 0;
    *NARM_DCR4_ADDR = 0;
    *NARM_DCR5_ADDR = 0;
    *NARM_DCR6_ADDR = 0;
}


 

/*  Function: int test_parallel_ports
 *
 *  Description:
 *     This routine executes a loopback test of the Parallel Ports.  A pattern is 
 *     transmitted using internal loopback and verified on the receive side.
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *
 *      POST_PASSED
 *      POST_FAILED
 */

int test_parallel_ports(void)
{


    /* 
     * p_ports 00 = 1 port; 1 = 2 ports; 2 = 3 ports; 3 = 4 ports;
     *
     * we have 2 parallel ports on our development board
     *
     */
    
    int p_ports = 1;
    
    
    /* send data to parallel ports
       NCC Chip Revisions Before Version 4 didnt prevent the STOBE
       signal from being issued during loopback mode.  Therefore, we
       must disable this test for earlier versions of the chip.   
     */

    /* if ((*NCC_PC).gcr.bits.pcmode == 1) */
    if ((*NARM_GCR_ADDR & 0x3) == 1)
    {
       
      register WORD32 timeout;
    
      BYTE     pc_tx_buffer[4][2][400], rx_buffer[4][2][400];

      WORD32 temp32;
      WORD32 test  = 3;
      WORD32 error = 0;
      WORD16 i, j, num_ports;
  
      /* Clear the interrupt flags */
      for (i = 0; i < 32; i++)
        irqFlag[i] = 0;

      /* Allow the timers to operate */
      /* (*NCC_GEN).i_er.bits.timer_1 = 1;  */  /* Enable Interrupts*/
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer1, 1);
      *NARM_T1CR_ADDR = 0xd0000010;   /* IRQenable, start timer,~.5ms*/
    
      /* (*NCC_GEN).i_er.bits.timer_2 = 1; */   /* Enable Interrupts*/
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer2, 1);
      *NARM_T2CR_ADDR = 0xd0000020;   /* IRQenable, start timer,~1ms*/

      /* Enable the EXTERNAL P1284 Control Buffers */
      /* (*NCC_GEN).portc.bits.data &= 0xf7; */
        narm_write_reg (NARM_PORTX_REG, NARM_PORTC_ADDR, data, 
			narm_read_reg (NARM_PORTX_REG, NARM_PORTC_ADDR, data) & 0xf7);	
      /* (*NCC_GEN).portc.bits.dir  |= 0x08; */
      narm_write_reg (NARM_PORTX_REG, NARM_PORTC_ADDR, dir, 
			narm_read_reg (NARM_PORTX_REG, NARM_PORTC_ADDR, dir) | 0x08);
      /* (*NCC_GEN).portc.bits.mode &= 0xf7; */  
      narm_write_reg (NARM_PORTX_REG, NARM_PORTC_ADDR, mode, 
		  narm_read_reg (NARM_PORTX_REG, NARM_PORTC_ADDR, mode) & 0xf7);
      *NARM_PPCR_ADDR(0) = 0;
      *NARM_PPCR_ADDR(1) = 0;
      *NARM_PPCR_ADDR(2) = 0;
      *NARM_PPCR_ADDR(3) = 0;
  
      *NARM_DCR3_ADDR = 0;
      *NARM_DCR4_ADDR = 0;
      *NARM_DCR5_ADDR = 0;
      *NARM_DCR6_ADDR = 0;
  
      /* Build some PRINT data */

      for (i = 0; i < 4; i++)
      {
        for (j = 0; j < 2; j++)
        {  
           for (temp32 = 0; temp32 < sizeof(pc_tx_buffer[i][j]); temp32 ++)
           {
              pc_tx_buffer[i][j][temp32] = (BYTE)(temp32 + j);
           }
        
        }
      }

      /* Initilize the receive buffers */

      for (i = 0; i < 4; i++)
      {
        for (j = 0; j < 2; j++)
        {  
           for (temp32 = 0; temp32 < sizeof(rx_buffer[i][j]); temp32++) 
           {
             rx_buffer[i][j][temp32] = 0;
           }
        
        }
        pc_rx_index[i] = 0;
        pc_rx_buffer[i] =(unsigned char*) rx_buffer[i];
      }

      /* First BUILD the TX buffer descriptors */
      for (i = 0; i < 4; i++)
      {
        for (j = 0; j < 2; j++)
        {  
           pc_tx_bd[i][j].lower_word.bits.wrap   = j;
           pc_tx_bd[i][j].lower_word.bits.intr   = 0;
           pc_tx_bd[i][j].lower_word.bits.last   = 1;
           pc_tx_bd[i][j].lower_word.bits.sbp    =(unsigned) pc_tx_buffer[i][j];
           pc_tx_bd[i][j].upper_word.bits.status = 0;
           pc_tx_bd[i][j].upper_word.bits.full   = 1;
           pc_tx_bd[i][j].upper_word.bits.buflen = sizeof(pc_tx_buffer[i][j]);
        
        }
      }

      /* Now configure and enable the PC TX DMA CHANNELS */
      /* (*NCC_GEN).i_er.bits.dma3 = 1; */
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma3, 1);
      /* (*NCC_GEN).i_er.bits.dma4 = 1; */
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma4, 1);
      /* (*NCC_GEN).i_er.bits.dma5 = 1; */
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma5, 1);
      /* (*NCC_GEN).i_er.bits.dma6 = 1; */
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma6, 1);

      *NARM_DCR3_ADDR = 0;
      *NARM_DBDP3_ADDR     =(unsigned long) pc_tx_bd[0];
      *NARM_DCR3_ADDR = 0x86000000;
      *NARM_DSIER3_ADDR = 0xf0d00000;
  
      *NARM_DCR4_ADDR = 0;
      *NARM_DBDP4_ADDR     = (unsigned long )pc_tx_bd[1];
      *NARM_DCR4_ADDR = 0x86000000;
      *NARM_DSIER4_ADDR = 0xf0d00000;
  
      *NARM_DCR5_ADDR = 0;
      *NARM_DBDP5_ADDR    = (unsigned long )pc_tx_bd[2];
      *NARM_DCR5_ADDR = 0x86000000;
      *NARM_DSIER5_ADDR = 0xf0d00000;
  
      *NARM_DCR6_ADDR = 0;
      *NARM_DBDP6_ADDR     =(unsigned long) pc_tx_bd[3];
      *NARM_DCR6_ADDR = 0x86000000;
      *NARM_DSIER6_ADDR = 0xf0d00000;
  
      *NARM_PPCR_ADDR(0) = 0xd50f0000;
      *NARM_PPCR_ADDR(1) = 0xd50f0000;
      *NARM_PPCR_ADDR(2) = 0xd50f0000;
      *NARM_PPCR_ADDR(3) = 0xd50f0000;
  
      /* (*NCC_GEN).i_er.bits.pc1 = 1; */
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, eni_port1, 1);
      /* (*NCC_GEN).i_er.bits.pc2 = 1; */
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, eni_port2, 1);
      /* (*NCC_GEN).i_er.bits.pc3 = 1; */
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, eni_port3, 1);
      /* (*NCC_GEN).i_er.bits.pc4 = 1; */
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, eni_port4, 1);

      /* Now wait for the TRANSMIT status to come back */
  
      timeout = 1500000;

      while ( (  (irqFlag[29] < 2)
             || ((irqFlag[28] < 2) && (p_ports >= 1)) 
             || ((irqFlag[27] < 2) && (p_ports >= 2)) 
             || ((irqFlag[26] < 2) && (p_ports >= 3)) ) && timeout)
    
         timeout--;

      if (     !timeout 
           || (pc_tx_bd[0][0].upper_word.bits.full   != 0) 
           || (pc_tx_bd[0][0].upper_word.bits.status != 0x0000)
           || (pc_tx_bd[0][1].upper_word.bits.full   != 0) 
           || (pc_tx_bd[0][1].upper_word.bits.status != 0x0000) ) {
        test_parallel_ports_cleanup();
        error = 1;
        test_parallel_ports_cleanup();
        report_error (test, error);
        return POST_FAILED;
      }      

      if (p_ports >= 1) {

        if (     !timeout 
             || (pc_tx_bd[1][0].upper_word.bits.full   != 0) 
             || (pc_tx_bd[1][0].upper_word.bits.status != 0x0000)
             || (pc_tx_bd[1][1].upper_word.bits.full   != 0) 
             || (pc_tx_bd[1][1].upper_word.bits.status != 0x0000)) {
          test_parallel_ports_cleanup();
          error = 2;
          report_error (test, error);
          return POST_FAILED;
        }      
      }      
  
      if (p_ports >= 2) {

        if (     !timeout 
             || (pc_tx_bd[2][0].upper_word.bits.full   != 0) 
             || (pc_tx_bd[2][0].upper_word.bits.status != 0x0000)
             || (pc_tx_bd[2][1].upper_word.bits.full   != 0) 
             || (pc_tx_bd[2][1].upper_word.bits.status != 0x0000)) {
          test_parallel_ports_cleanup();
          error = 3;
          report_error (test, error);
          return POST_FAILED;
        }      
      }      
        
      if (p_ports == 3) {

        if (      !timeout 
             || (pc_tx_bd[3][0].upper_word.bits.full   != 0) 
             || (pc_tx_bd[3][0].upper_word.bits.status != 0x0000)
             || (pc_tx_bd[3][1].upper_word.bits.full   != 0) 
             || (pc_tx_bd[3][1].upper_word.bits.status != 0x0000)) {
          test_parallel_ports_cleanup();
          error = 4;
          report_error (test, error);
          return POST_FAILED;
        }      
      }      

      /* Now verify the RECEIVE DATA */

      num_ports = p_ports + 1;

      for (i = 0; i < num_ports; i++)
      {
        for (j = 0; j < 2; j++)
        {
           for (temp32 = 0; temp32 < sizeof(rx_buffer[i][j]); temp32++) 
           {
             if (pc_tx_buffer[i][j][temp32] != rx_buffer[i][j][temp32]) 
             {
               test_parallel_ports_cleanup();
               error = 5 + i;
               report_error (test, error);
               return POST_FAILED;
             }      
           }
        }
      }

      test_parallel_ports_cleanup();
    }

    return POST_PASSED;

}  







#ifdef DO_SERIAL_LOOPBACK



/*
 *
 *  Function: void ncc_post_ser_dma_stop(void)
 *
 *  Description:
 *
 *      Turn off all DMA channels used by ncc_post_ser().
 *
 *  Parameters:
 *
 *      none
 *
 *  Return Values:
 *
 *      none
 *
 */

static void ncc_post_ser_dma_stop(void)
{
    *NARM_DCR7_ADDR  = 0;
    *NARM_DCR9_ADDR  = 0;
    *NARM_DCR8_ADDR  = 0;
    *NARM_DCR10_ADDR = 0;
}
  
 


/*  Function: static int ncc_post_ser ()  
 *
 *  Description:
 *     The ncc_post_ser routine is responsible for sending two data packets
 *     through the SERIAL ports.  The parameter calls identify the size of the
 *     data packet.  The SERIAL PORTS are assumed to be configured in their 
 *     proper configuration before the call.
 *
 *  Parameters:
 *     test:   RED LED blinks
 *     error:  GREEN LED blinks
 *     size:   packets sizes
 *     ser_tx_buffer: tx buffers
 *     ser_rx_buffer: rx buffers
 *     stat:   status
 *     crc_size: crc size
 *
 *  Return Value:
 *     POST_PASSED
 *     POST_FAILED
 *
 */

static int ncc_post_ser (

   WORD32 test, WORD32 error,  
   WORD32 size[][2],
   BYTE   ser_tx_buffer[2][SER_TX_SIZE],
   BYTE   ser_rx_buffer[2][2][SER_TX_SIZE],
   WORD16 stat[][2],
   WORD16 crc_size

)
/* filled in size of first array size with 2 for rx, tx, were [] [] */

{

    WORD32   temp32, timeout;
    WORD16   i, j;
    BYTE     temp8;



      /* First BUILD the TX buffer descriptors */
  
      for (i = 0; i < 2; i++)
      {
        for (j = 0; j < 2; j++)
    {
          ser_tx_bd[i][j].lower_word.bits.wrap   = j;
          ser_tx_bd[i][j].lower_word.bits.intr   = 1;
          ser_tx_bd[i][j].lower_word.bits.last   = 1;
          if (j == 0)
            ser_tx_bd[i][j].lower_word.bits.sbp    =(unsigned) &ser_tx_buffer[i];
          else
            ser_tx_bd[i][j].lower_word.bits.sbp    =(unsigned) &ser_tx_buffer[i][size[i][0]-size[i][1]];
          ser_tx_bd[i][j].upper_word.bits.status = 0;
          ser_tx_bd[i][j].upper_word.bits.full   = 1;
          ser_tx_bd[i][j].upper_word.bits.buflen = size[i][j];
        }
      }
  
      /* Now BUILD the RX buffer descriptors */
  
      for (i = 0; i < 2; i++)
      {
        for (j = 0; j < 2; j++)
    {
          ser_rx_bd[i][j].lower_word.bits.wrap   = j;
          ser_rx_bd[i][j].lower_word.bits.intr   = 1;
          ser_rx_bd[i][j].lower_word.bits.last   = 1;
          ser_rx_bd[i][j].lower_word.bits.sbp    = (unsigned)&ser_rx_buffer[i][j][0];
          ser_rx_bd[i][j].upper_word.bits.status = 0;
          ser_rx_bd[i][j].upper_word.bits.full   = 0;
          ser_rx_bd[i][j].upper_word.bits.buflen = SER_TX_SIZE + crc_size; 
    }
      }

      /* Clear the receiver buffers */
  
      for (i = 0; i < 2; i++)
      {
        for (j = 0; j < 2; j++)
        {
          for (temp32 = 0; temp32 < SER_TX_SIZE; temp32 = temp32 + 1) 
          {
            ser_rx_buffer[i][j][temp32] = 0;
          }
        }
      }

           
      /* Now generate some TRANSMIT data to send out the
         Serial PORT*/
  
      temp8 = 1;
    
      for (temp32 = 0; temp32 < SER_TX_SIZE; temp32 = temp32 + 1) {
        ser_tx_buffer[0][temp32] = temp8;
        ser_tx_buffer[1][temp32] = temp8 ^ 0xff;
        temp8++;
        if (((BYTE)temp32 == 0xff) || (temp8 == 0xff))
          temp8++;
      }
      ser_tx_buffer[0][SER_TX_SIZE-1] = 0xff;
      ser_tx_buffer[1][SER_TX_SIZE-1] = 0xff ^ 0xff;
  
      
      /* Clear the interrupt flags */
      for (i = 0; i < 32; i++)
        irqFlag[i] = 0;
    
      /* Now configure and enable the SER RX DMA CHANNEL */
  
      *NARM_DCR7_ADDR  = 0;
      *NARM_DBDP7_ADDR      =(unsigned long ) ser_rx_bd[0];
      *NARM_DCR7_ADDR  = 0x80000000;
      *NARM_DSIER7_ADDR  = 0xf0d00000;
    
      *NARM_DCR9_ADDR  = 0;
      *NARM_DBDP9_ADDR      =(unsigned long ) ser_rx_bd[1];
      *NARM_DCR9_ADDR  = 0x80000000;
      *NARM_DSIER9_ADDR  = 0xf0d00000;
    
      /* Now configure and enable the SER TX DMA CHANNEL */
  
      *NARM_DCR8_ADDR  = 0;
      *NARM_DBDP8_ADDR      =(unsigned long ) ser_tx_bd[0];
      *NARM_DCR8_ADDR  = 0x84000000;
      *NARM_DSIER8_ADDR  = 0xf0d00000;
  
      *NARM_DCR10_ADDR = 0;
      *NARM_DBDP10_ADDR     = (unsigned long )ser_tx_bd[1];
      *NARM_DCR10_ADDR = 0x84000000;
      *NARM_DSIER10_ADDR = 0xf0d00000;

      timeout = 1500000*2;
  
      while ( ( (irqFlag[25] < 2)
             || (irqFlag[24] < 2)  
             || (irqFlag[23] < 2)  
             || (irqFlag[22] < 2) ) && timeout)
    
         timeout--;

      /* Now wait for the TRANSMIT status to come back */
  
      if (     !timeout 
           || (ser_tx_bd[0][0].upper_word.bits.full   != 0) 
           || (ser_tx_bd[0][0].upper_word.bits.status != 0x0000)
           || (ser_tx_bd[0][1].upper_word.bits.full   != 0) 
           || (ser_tx_bd[0][1].upper_word.bits.status != 0x0000) ) 
      {
        
        report_error (test, error + 1);
        ncc_post_ser_dma_stop();
        return POST_FAILED;
      }      

      if (    (ser_tx_bd[1][0].upper_word.bits.full   != 0) 
           || (ser_tx_bd[1][0].upper_word.bits.status != 0x0000)
           || (ser_tx_bd[1][1].upper_word.bits.full   != 0) 
           || (ser_tx_bd[1][1].upper_word.bits.status != 0x0000) ) 
      {
        
        report_error (test, error + 2);
        ncc_post_ser_dma_stop();
        return POST_FAILED;
      }      


      
   
      /* Now wait for the RECEIVE status to come back 
         Why do we need to wait a bit here -- because the interrupt flags are set by the first buffer close
         interrupt, when we get here, the second rx buffer may not be finished yet. so we just give it 
         a little time to let the second rx buffer finishes.
        */
      timeout = 15000;
      while (  timeout && ((ser_rx_bd[0][0].upper_word.bits.full   != 1) 
           || (ser_rx_bd[0][0].upper_word.bits.status != stat[0][0])
           || (ser_rx_bd[0][1].upper_word.bits.full   != 1) 
           || (ser_rx_bd[0][1].upper_word.bits.status != stat[0][1])) )
           timeout--;
           
      if(!timeout)         
      {    
        report_error (test, error + 3);
        ncc_post_ser_dma_stop();
        return POST_FAILED;
      }         

      timeout = 15000;
      while (  timeout && ( (ser_rx_bd[1][0].upper_word.bits.full   != 1) 
           || (ser_rx_bd[1][0].upper_word.bits.status != stat[1][0])
           || (ser_rx_bd[1][1].upper_word.bits.full   != 1) 
           || (ser_rx_bd[1][1].upper_word.bits.status != stat[1][1]) )) 
           timeout--;
           
      if(!timeout) 
      {
        
        report_error (test, error + 4);
        ncc_post_ser_dma_stop();
        return POST_FAILED;
      }      

      /* Now verify the RECEIVE DATA */
  
      temp8 = 1;
    
      for (temp32 = 0; temp32 < size[0][0] - 1; temp32 = temp32 + 1) {
        if (ser_rx_buffer[0][0][temp32] != temp8) 
        {
          
          report_error (test, error + 5);
          ncc_post_ser_dma_stop();
          return POST_FAILED;
        }      
        temp8++;
        if (((BYTE)temp32 == 0xff) || (temp8 == 0xff))
          temp8++;
      }
      
      temp8 = size[0][0] - size[0][1] + 1;
  
      for (temp32 = 0; temp32 < size[0][1] - 1; temp32 = temp32 + 1) {
        if (ser_rx_buffer[0][1][temp32] != temp8) 
        {
          
          report_error (test, error + 6);
          ncc_post_ser_dma_stop();
          return POST_FAILED;
        }      
        temp8++;
        if (((BYTE)temp32 == (BYTE)(255 - (size[0][0] - size[0][1]))) || (temp8 == 0xff))
          temp8++;
      }
  
      temp8 = 1;
    
      for (temp32 = 0; temp32 < size[1][0] - 1; temp32 = temp32 + 1) {
        if (ser_rx_buffer[1][0][temp32] != (temp8 ^ 0xff)) 
        {
          
          report_error (test, error + 7);
          ncc_post_ser_dma_stop();
          return POST_FAILED;
        }      
        temp8++;
        if (((BYTE)temp32 == 0xff) || (temp8 == 0xff))
          temp8++;
      }
      
      temp8 = size[1][0] - size[1][1] + 1;
  
      for (temp32 = 0; temp32 < size[1][1] - 1; temp32 = temp32 + 1) {
        if (ser_rx_buffer[1][1][temp32] != (temp8 ^ 0xff)) 
        {
          
          report_error (test, error + 8);
          ncc_post_ser_dma_stop();
          return POST_FAILED;
        }      
        temp8++;
        if (((BYTE)temp32 == (BYTE)(255 - (size[1][0] - size[1][1]))) || (temp8 == 0xff))
          temp8++;
      }

    ncc_post_ser_dma_stop();

    return POST_PASSED;
}



/*
 *
 *  Function: void test_serial_loopback_cleanup(int int_loopback, WORD32 PORTA_save, WORD32 PORTB_save)
 *
 *  Description:
 *
 *      Shut down the H/W used by test_serial_loopback()
 *
 *  Parameters:
 *
 *      int_loopback        indicates if internal loopback is used
 *      PORTA_save          saved settings for port A
 *      PORTB_save          saved settings for port B
 *
 *  Return Values:
 *
 *      none
 *
 */

static void test_serial_loopback_cleanup(int int_loopback, WORD32 PORTA_save, WORD32 PORTB_save)
{
    /* Shut down the timers */
    /* (*NCC_GEN).i_er.bits.timer_1 = 0; */   /* Disable Interrupts */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer1, 0);
    /* (*NCC_GEN).i_er.bits.timer_2 = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer2, 0);
    *NARM_T1CR_ADDR = 0;
    *NARM_T2CR_ADDR = 0;
    
    /* Shut down the Serial Ports */
    *NARM_SC1CRA_ADDR = 0;
    *NARM_SC1CRB_ADDR = 0;
    *NARM_SC2CRA_ADDR = 0;
    *NARM_SC2CRB_ADDR = 0;
    
    /* Shut down the DMA Channels */
    /* (*NCC_GEN).i_er.bits.dma7  = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma7, 0);
    /* (*NCC_GEN).i_er.bits.dma8  = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma8, 0);
    /* (*NCC_GEN).i_er.bits.dma9  = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma9, 0);
    /* (*NCC_GEN).i_er.bits.dma10 = 0; */
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma10, 0);
    
    *NARM_DCR7_ADDR = 0;
    *NARM_DCR8_ADDR = 0;
    *NARM_DCR9_ADDR = 0;
    *NARM_DCR10_ADDR = 0;
  
      /* Now restore the Serial Port connection to the
         outside world.*/
      if (int_loopback)  
      {
	  *NARM_PORTA_ADDR = PORTA_save;
		if (narm_read_reg(NARM_GSSR_REG, NARM_GSSR_ADDR, rev) >= NETA20UM)
		    *NARM_PORTC_ADDR = PORTB_save;
		else
		    *NARM_PORTB_ADDR = PORTB_save;
      }     
}


/*  Function: int test_serial_loopback (BOOLEAN int_loopback)
 *
 *  Description:
 *     This routine executes a loopback test of the Serial Ports.  A pattern is 
 *     transmitted using internal loopback and verified on the receive side.
 *
 *  Parameters:
 *      int_loopback:  1   will do internal loopback test
 *                     0   will not do internal loopback test
 *
 *  Return Values:
 *
 *      POST_PASSED
 *      POST_FAILED
 */

/* The serial register of "11" indicates no serial ports */

static int test_serial_loopback(BOOLEAN int_loopback)
{
    WORD32   test, PORTA_save, PORTB_save, size[2][2];
    WORD16   stat[2][2], i;
	int		 TestStatus = 0;
    
	/* receive and send buffers */
    BYTE * ser_tx_buffer;
	BYTE * ser_rx_buffer;

    ser_tx_buffer = (BYTE *)malloc(2 * SER_TX_SIZE);
	if(ser_tx_buffer == NULL)
	{
	    return POST_FAILED;
	}
	ser_rx_buffer = (BYTE *)malloc(2 * 2 * SER_TX_SIZE);
	if(ser_rx_buffer == NULL)
	{
	    return POST_FAILED;
	}
    
    
    if (TRUE)
    {
      test   = 4;
  
      /* Clear the interrupt flags */
      for (i = 0; i < 32; i++)
        irqFlag[i] = 0;
    
      /* Allow the timers to operate */
      /* (*NCC_GEN).i_er.bits.timer_1 = 1; */   /* Enable Interrupts */
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer1, 1);
      *NARM_T1CR_ADDR = 0xd0000010;   /* IRQenable, start timer,~.5ms */
    
      /* (*NCC_GEN).i_er.bits.timer_2 = 1; */   /* Enable Interrupts */
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer2, 1);
      *NARM_T2CR_ADDR = 0xd0000020;   /* IRQenable, start timer,~1ms */

      /* We must first disconnect the Serial Interface 
         from the outside world for testing*/

      if (int_loopback)  
      {
	  PORTA_save = *NARM_PORTA_ADDR;
		/* (*NCC_GEN).porta.bits.mode = 0; */
	    narm_write_reg (NARM_PORTX_REG, NARM_PORTA_ADDR, mode, 0);

		if (narm_read_reg(NARM_GSSR_REG, NARM_GSSR_ADDR, rev) >= NETA20UM)
		{
		    PORTB_save = *NARM_PORTC_ADDR;
			/* (*NCC_GEN).portc.bits.mode = 0; */
			narm_write_reg (NARM_PORTX_REG, NARM_PORTC_ADDR, mode, 0);
		}
		else
		{
		    PORTB_save = *NARM_PORTB_ADDR; 
			/* (*NCC_GEN).portb.bits.mode = 0; */
			narm_write_reg (NARM_PORTX_REG, NARM_PORTB_ADDR, mode, 0);
		}
      }
  
      *NARM_DCR7_ADDR = 0;
      *NARM_DCR8_ADDR = 0;
      *NARM_DCR9_ADDR = 0;
      *NARM_DCR10_ADDR = 0;
  
      *NARM_SC1CRA_ADDR = 0;
      *NARM_SC2CRA_ADDR = 0;
  
      /* setup registers */
      *NARM_SC1CRA_ADDR = 0x83030101 | (int_loopback << 20);  /* loopback mode */
      *NARM_SC1CRA_ADDR	|= 0x8303FFFF;
      *NARM_SC1CRB_ADDR = 0x80000000;    /* enable data match 1 */
      *NARM_SC1SRA_ADDR  = 0xffffffff;    /* clear the status register */
      *NARM_SC1BRG_ADDR = 0xc1000003;    /* bit rate generator (230000 bps) */
      *NARM_SC1RBT_ADDR = 0x00000000;    /* disable buf gap timer */
      *NARM_SC1RCT_ADDR = 0x00000000;    /* disable char timer */
      *NARM_SC1RMR_ADDR = 0xff000000;    /* match = 0xFF */
      
      *NARM_SC2CRA_ADDR = 0x83030101 | (int_loopback << 20);  /* loopback mode */
      *NARM_SC2CRA_ADDR	|= 0x8303FFFF;
      *NARM_SC2CRB_ADDR = 0x80000000;    /* enable data match 1 */
      *NARM_SC2SRA_ADDR  = 0xffffffff;    /* clear the status register */
      *NARM_SC2BRG_ADDR = 0xc1000003;    /* bit rate generator (230000 bps)*/
      *NARM_SC2RBT_ADDR = 0x00000000;    /* disable buf gap timer */
      *NARM_SC2RCT_ADDR = 0x00000000;    /* disable char timer */
      *NARM_SC2RMR_ADDR = 0x00000000;    /* match = 0xFF */

      /* Enable the DMA Channel interrupts */
      /* (*NCC_GEN).i_er.bits.dma7  = 1; */
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma7, 1);
      /* (*NCC_GEN).i_er.bits.dma8  = 1; */
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma8, 1);
      /* (*NCC_GEN).i_er.bits.dma9  = 1; */
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma9, 1);
      /* (*NCC_GEN).i_er.bits.dma10 = 1; */
      narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, dma10, 1);
      
      stat[0][0] = 0x8000;
      stat[0][1] = 0x8000;
      stat[1][0] = 0x8000;
      stat[1][1] = 0x8000;

      size[0][0] = SER_TX_SIZE;
      size[0][1] = SER_TX_SIZE - 100;
      size[1][0] = SER_TX_SIZE;
      size[1][1] = SER_TX_SIZE - 100;

      if (ncc_post_ser (test, (WORD32) 0x0, size, (BYTE (*) [4096])ser_tx_buffer, (BYTE (*) [2] [4096])ser_rx_buffer, stat, 0) == POST_FAILED)
      {
            test_serial_loopback_cleanup(int_loopback, PORTA_save, PORTB_save);
			TestStatus = -1;
			goto SerialTestEnd;
      }

      /* NCC Revisions above 0 support DMA using the Char and Buffer Timer Gaps */

      /* if ((*NCC_GEN).ssr.bits.rev != 0) */
      if (narm_read_reg (NARM_GSSR_REG, NARM_GSSR_ADDR, rev) != 0)	  
      {

          /*
		   * test criteria
		   * channel 1 buffer gap timer on
		   * channel 2 character gap timer on
		   */


          *NARM_SC1RBT_ADDR = 0x800002c0;    /* enable buf gap timer */
          *NARM_SC1RCT_ADDR = 0x00000000;    /* disable char timer */
          *NARM_SC1CRB_ADDR = 0x08000000;    /* enable buffer timer */
      
          *NARM_SC2RBT_ADDR = 0x00000000;    /* disable buf gap timer */
          *NARM_SC2RCT_ADDR = 0x800000ff;    /* enable char timer */
          *NARM_SC2CRB_ADDR = 0x04000000;    /* enable character timer */


          stat[0][0] = 0x0000;
          stat[0][1] = 0x0800;
          stat[1][0] = 0x0000;
          stat[1][1] = 0x0400;

          size[0][0] = SER_TX_SIZE;
          size[0][1] = SER_TX_SIZE - 99;
          size[1][0] = SER_TX_SIZE;
          size[1][1] = SER_TX_SIZE - 98;

          if (ncc_post_ser (test, (WORD32) 0x0, size, (BYTE (*) [4096])ser_tx_buffer, (BYTE (*) [2] [4096])ser_rx_buffer, stat, 0) == POST_FAILED)
          {
                test_serial_loopback_cleanup(int_loopback, PORTA_save, PORTB_save);
				TestStatus = -1;
				goto SerialTestEnd;
          }

          /* 
		   * Test criteria
		   * channel 1 character gap timer on
		   * channel 2 buffer gap timer on
		   */


          *NARM_SC1RBT_ADDR = 0x00000000;    /* disable buf gap timer */
          *NARM_SC1RCT_ADDR = 0x800000ff;    /* enable char timer */  /* was 800000ff */
          *NARM_SC1CRB_ADDR = 0x04000000;    /* enable character timer */

          *NARM_SC2RBT_ADDR = 0x800002c0;    /* enable buf gap timer */	 /* was 800000ff */
          *NARM_SC2RCT_ADDR = 0x00000000;    /* disable char timer */
          *NARM_SC2CRB_ADDR = 0x08000000;    /* enable buffer timer */
      
          stat[0][0] = 0x0000;
          stat[0][1] = 0x0400;
          stat[1][0] = 0x0000;
          stat[1][1] = 0x0800;

          size[0][0] = SER_TX_SIZE;
          size[0][1] = SER_TX_SIZE - 97;

          size[1][0] = SER_TX_SIZE;
          size[1][1] = SER_TX_SIZE - 96;

          if (ncc_post_ser (test, (WORD32) 0x0, size, (BYTE (*) [4096])ser_tx_buffer, (BYTE (*) [2] [4096])ser_rx_buffer, stat, 0) == POST_FAILED)
          {
                test_serial_loopback_cleanup(int_loopback, PORTA_save, PORTB_save);
				TestStatus = -1;
				goto SerialTestEnd;
          }

      }
      
  
    }       

    test_serial_loopback_cleanup(int_loopback, PORTA_save, PORTB_save);

    SerialTestEnd:
	/* deallocate the transmit and recieve buffers */
	free (ser_tx_buffer);
	free (ser_rx_buffer);

    if(TestStatus == 0)
	{
        return POST_PASSED;
	}
	else
	{
	    return POST_FAILED;
	}
}

#endif


/*
 *
 *  Function: void test_gen_irq_cleanup(void)
 *
 *  Description:
 *
 *      Shut down the hardware used by test_gen_irq(void).
 *
 *  Parameters:
 *
 *      none
 *
 *  Return Values:
 *
 *      none
 *
 */

static void test_gen_irq_cleanup(void)
{
    *NARM_T1CR_ADDR = 0;
    *NARM_T2CR_ADDR = 0;
}





/*  Function: int test_gen_irq
 *
 *  Description:
 *     This routine executes a test of the GEN Module timers.  This test verifies
 *     that each of the timers can generate an interrupt.
 *
 *  Parameters:
 *      none
 *
 *  Return Values:
 *
 *      POST_PASSED
 *      POST_FAILED
 */

static int test_gen_irq(void)
{
    register WORD32 timeout;

    WORD32   error, test; 

    test  = 6;
    error = 0;

    irqFlag[5] = FALSE;                 /* clear flag*/
    irqFlag[4] = FALSE;                 /* clear flag*/

    /* (*NCC_GEN).i_er.bits.timer_1 = 1; */   /* Enable Interrupts*/
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer1, 1);
    *NARM_T1CR_ADDR = 0xd0000010;   /* IRQenable, start timer,~.5ms*/

    /* (*NCC_GEN).i_er.bits.timer_2 = 1; */   /* Enable Interrupts*/
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer2, 1);
    *NARM_T2CR_ADDR = 0xd0000020;   /* IRQenable, start timer,~1ms*/

    timeout = 1500000;

    while ( ( (irqFlag[5] < 20)
           || (irqFlag[4] < 10) ) && timeout)
      timeout--;

    /* (*NCC_GEN).i_er.bits.timer_1 = 0; */    /* Disable Interrupts*/
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer1, 0);
    /* (*NCC_GEN).i_er.bits.timer_2 = 0; */    
    narm_write_reg (NARM_IER_REG, NARM_IER_ADDR, timer2, 0);
    
    if (!timeout || (irqFlag[5] != 20))
    {
        test_gen_irq_cleanup();
        error = 1;               /* NG condition*/
        report_error (test, error);
        return POST_FAILED;
    }

    if (!timeout || (irqFlag[4] != 10))
    {
        test_gen_irq_cleanup();
        error = 2;               /* NG condition*/
        report_error (test, error);
        return POST_FAILED;
    }


    test_gen_irq_cleanup();
    return POST_PASSED;
}


/*  
 * 
 *  
 *  Function: static void restoreVector(void) 
 *
 *  Description:
 *     when use 32 bit flash and cache is on, there are two bits in Memory
 *     Module Configuration Register need to be cleaned upon power up reset, 
 *     so we don't have vector table in reset.s, instead, we restore the 
 *     vector table here, please refer to reset.s
 *
 *  Parameters:
 *     none
 *  
 *  Return Value:
 *     none
 *
 */ 
static void restoreVector(void)
{
  /*

	Since the branch instruction have a limitation in ranch, it must branch to a local location (PC+20)
	From that location it can use the jump instruction to execute the interrupt handler since the range is higher 
	with its 32bit.

	The setup of the vector table is in sync with reset.s, tx_ill.s, and restoreVector() !!
	Any changes made here must be adjusted in those files.

   */
 
      *(WORD32*)(0x0)= 0xe59ff018;
      *(WORD32*)(0x4)= 0xe59ff018;
      *(WORD32*)(0x8)= 0xe59ff018;
      *(WORD32*)(0xc)= 0xe59ff018;
      *(WORD32*)(0x10)= 0xe59ff018;
      *(WORD32*)(0x14)= 0xe59ff018;
      *(WORD32*)(0x18)= 0xe59ff018;
      *(WORD32*)(0x1c)= 0xe59ff018;
      
      
      *(WORD32*)(0x20)= NA_MAIN;
      *(WORD32*)(0x24)= UNDEFINED;
      *(WORD32*)(0x28)= SWI;
      *(WORD32*)(0x2c)= PREFETCH;
      *(WORD32*)(0x30)= ABORT;
      *(WORD32*)(0x34)= RESERVED;
      *(WORD32*)(0x38)= NAIRQ;
      *(WORD32*)(0x3c)= FIQ;

}


/*  Function: nccPostResultsType *ncc_post (void)  
 *
 *  Description:
 *     The PowerOn Self Test (POST) function is responsible for
 *     executing a diagnostic test of the NCC chip and it's
 *     associated peripherals.  When encountering a failure,
 *     the POST will display an LED blink error pattern.  All
 *     fatal errors will cause the blink pattern to repeat 
 *     forever stopping the poweron process.
 *
 *  Parameters:
 *     none
 *  
 *  Return Value:
 *     none
 *
 */


nccPostResultsType *ncc_post (void)
{  
    int ccode;
 
    restoreVector(); /*restore the vector table so we can get interrupt going*/

    /* now re-initialize the irq tables*/
    init_irq_tables();  

    register_irq_handler (5, IRQ_DMA1,     (WORD32)ncc_post_dma1_isr,     0);
    register_irq_handler (4, IRQ_DMA2,     (WORD32)ncc_post_dma2_isr,     0);
    register_irq_handler (2, IRQ_DMA3,     (WORD32)ncc_post_dma3_isr,     0);
    register_irq_handler (2, IRQ_DMA4,     (WORD32)ncc_post_dma4_isr,     0);
    register_irq_handler (2, IRQ_DMA5,     (WORD32)ncc_post_dma5_isr,     0);
    register_irq_handler (2, IRQ_DMA6,     (WORD32)ncc_post_dma6_isr,     0);
    register_irq_handler (2, IRQ_DMA7,     (WORD32)ncc_post_dma7_isr,     0);
    register_irq_handler (2, IRQ_DMA8,     (WORD32)ncc_post_dma8_isr,     0);
    register_irq_handler (2, IRQ_DMA9,     (WORD32)ncc_post_dma9_isr,     0);
    register_irq_handler (2, IRQ_DMA10,    (WORD32)ncc_post_dma10_isr,    0);
    register_irq_handler (1, IRQ_PC1,      (WORD32)ncc_post_eni_1_isr,    0);
    register_irq_handler (1, IRQ_PC2,      (WORD32)ncc_post_eni_2_isr,    0);
    register_irq_handler (1, IRQ_PC3,      (WORD32)ncc_post_eni_3_isr,    0);
    register_irq_handler (1, IRQ_PC4,      (WORD32)ncc_post_eni_4_isr,    0);
    register_irq_handler (4, IRQ_ENET_RX,  (WORD32)ncc_post_enet_rx_isr,  0);
    register_irq_handler (3, IRQ_SER1_RX,  (WORD32)ncc_post_ser_1_rx_isr, 0);
    register_irq_handler (3, IRQ_SER1_TX,  (WORD32)ncc_post_ser_1_tx_isr, 0);
    register_irq_handler (3, IRQ_SER2_RX,  (WORD32)ncc_post_ser_2_rx_isr, 0);
    register_irq_handler (3, IRQ_SER2_TX,  (WORD32)ncc_post_ser_2_tx_isr, 0);
    register_irq_handler (1, IRQ_WATCHDOG, (WORD32)ncc_post_wdog_isr,     0);
    register_irq_handler (1, IRQ_TIMER1,   (WORD32)ncc_post_timer1_isr,   0);
    register_irq_handler (1, IRQ_TIMER2,   (WORD32)ncc_post_timer2_isr,   0);
	 
    ccode = test_dma_ram();
      
    if (ccode == POST_PASSED)
    {
        ccode = test_mem_to_mem_dma();
    }
 
    if ((ccode == POST_PASSED) && (narm_read_reg(NARM_GSSR_REG, NARM_GSSR_ADDR, rev) < NETA20UM) )
    {
		 if ((narm_read_reg (NARM_GCR_REG, NARM_GCR_ADDR, enimode) == 1) 
    		&& (narm_read_reg (NARM_GSSR_REG, NARM_GSSR_ADDR, gen_id1) >= 4))
		{
			ccode = test_parallel_ports();
		}
	 }
          
  
    if (ccode == POST_PASSED)
    {
        ccode = test_gen_irq();
    }    
    
     
    #ifdef DO_SERIAL_LOOPBACK
        if (ccode == POST_PASSED)
        {
            ccode = test_serial_loopback(TRUE);
        }
    #endif
  
    /* restore irq tables*/
    init_irq_tables(); 
 
    return &nccPostResults;
}
#endif /* BSP_POST_TEST */


