/*****************************************************************
 *
 * 	SCSI DIAGNOSTICS
 *
 * This module contains SCSI diagnostic tests
 *
 * History:
 *   +----------+------------+-----------------------------------+
 *   |   Date   |     by     |     Description                   |
 *   +----------+------------+-----------------------------------+
 *   |          | GARY       | Written                           |
 *   +----------+------------+-----------------------------------+
 *
 *   All tests are done in enhanced and loop back mode.
 *   The tests check the SCSI control status and data registers
 *   and the interrupt mechanism.
 *   In its current state this test only check NATIONAL Semi Con`s
 *   DP8490 SCSI in non dma mode.
 *
 ****************************************************************/

#include "cc_def.h"
#include "diag.h"
#if (BOARD == VECTOR)
#include <asis.h>
#endif

#pragma interrupt (chk_scsi_int);


/* SCSI memory mapped I/O addresses definitions */
/************************************************/

#define   ODR_REG		*((byte *) 0xff600000) /* Output Data Reg   */
#define   CSD_REG		*((byte *) 0xff600000) /* Current Scsi Data */
#define   ICR_REG		*((byte *) 0xff600001) /* Initiat Com` Reg  */
#define   MR2_REG		*((byte *) 0xff600002) /* Mode Reg 2	    */
#define   TCR_REG		*((byte *) 0xff600003) /* Target Com Reg    */
#define   SER_REG		*((byte *) 0xff600004) /* Select Enable Reg */
#define   CSB_REG		*((byte *) 0xff600004) /* Current Scsi Bus  */
#define   BSR_REG		*((byte *) 0xff600005) /* Bus Status Reg    */
#define   SDS_REG		*((byte *) 0xff600005) /* Start Dna Send    */
#define   SDT_REG		*((byte *) 0xff600006) /* Start Dma Target  */
#define   IDR_REG		*((byte *) 0xff600006) /* Input Data Reg    */
#define   SDI_REG		*((byte *) 0xff600007) /* Start Dma Initiat */
#define   RPI_REG		*((byte *) 0xff600007) /* Rst Parity/Int    */
#define   EMR_REG		*((byte *) 0xff600007) /* Enhanced Mode Reg */
#define   ISR_REG		*((byte *) 0xff600007) /* Int Status Reg    */
#define   IMR_REG		*((byte *) 0xff600007) /* Int Mask Reg      */

/* SCSI registers set up definitions */
/*************************************/


#define   INITI_COM	0x5e		/* command to initiator		*/
#define   TARGET_COM    0x0f   		/* command to target		*/
#define   SCSI_STAT	0x7e		/* expected SCSI status		*/
#define   BUS_STAT	0x0b		/* expected bus status		*/
#define   ASSERT_DATA	0x41		/* assert data signal		*/
#define   PARITY_CHEC	0x30		/* check parity error bit	*/
#define   ENABLE_ISR    0x3e		/* enhanced func` bits in EMR   */
#define   RST_LATCH     0x1a		/* 				*/
#define   REMOVE_RST    0x18		/* 				*/
#define   E_MODE	0x40		/* enhanced mode configuration  */
#define   LOOP_BACK	0x08		/* test mode configuration	*/
#define   PARITY_BIT    0x80		/* 				*/
#define   ARB_INT       0x01		/* ARB int` bit in EMR,ISR,IMR  */ 

/* Forward private functions. */
/******************************/

private char * test_control();
private char * test_data();
private char * test_int();

/********************************************************************
 *
 *	test_control()
 *
 *  The test sets information to the INITIATOR and TARGET control registers.
 *  The SCSI and BUS status registers should reflect this information.
 *
 *******************************************************************/

private char * test_control()
{
    ICR_REG = E_MODE;				/* set SCSI to E mode	  */
    EMR_REG = LOOP_BACK;			/* set SCSI to test mode  */

    ICR_REG = INITI_COM;			/* set com` to initiator  */
    TCR_REG = TARGET_COM;			/* set com` to target	  */

    if ((CSB_REG == SCSI_STAT) && (BSR_REG == BUS_STAT)) {
	if (debug_flag) {
	strcpy(msg__, "SCSI CONTROL DRIVING/MONITORING PASSED ");
	print_str (msg__);
	}
	return NULL;
    }
    else {
	strcpy(error, "FAILURE: CONTROL PATH ERROR IN LOOP-BACK MODE");
	return error;
    }
}

/********************************************************************
 *
 *	test_data()
 *
 *  Data is writen to the data register.
 *  The `current scsi data` register should reflect this data.
 *  The `scsi parity error bit` in the `interupt status register` 
 *  is checked.
 *
 *******************************************************************/

private char * test_data()
{
    ICR_REG = E_MODE;

    EMR_REG = RST_LATCH;			       /* reset int` latch */
    EMR_REG = REMOVE_RST;

    ICR_REG = ASSERT_DATA;			   /* enable SCSI data bus */
    MR2_REG = PARITY_CHEC;		/* enable parity check & intterupt */
    ODR_REG = 0xa5;					/* write a pattern */
    if (CSD_REG != 0xa5) {				/* if data error   */
        EMR_REG = ENABLE_ISR; 				/* enable ISR read */
	if ((ISR_REG & PARITY_BIT) != 0) {		/* if parity error */
	    strcpy(error, "FAILURE: DATA PATH ERROR IN LOOP-BACK MODE");
	    return error;
	}
    }
    EMR_REG = RST_LATCH;				/* reset int` latch */
    EMR_REG = REMOVE_RST;

    ICR_REG = ASSERT_DATA;
    MR2_REG = PARITY_CHEC;
    ODR_REG = 0x5a;
    if (CSD_REG != 0x5a) {
	EMR_REG = ENABLE_ISR;
	if ((ISR_REG & PARITY_BIT) != 0) {
	    strcpy(error, "FAILURE: DATA PATH ERROR IN LOOP-BACK MODE");
	    return error;
	}
    }
    if (debug_flag) {
    strcpy(msg__, "SCSI DATA PASSED ");
    print_str (msg__);
    }
    return NULL;
}

/********************************************************************
 *
 *	test_int()
 *
 *
 *******************************************************************/

private char scsi_int_src;
private char scsi_int_flag;

void chk_scsi_int()
{
    EMR_REG = ENABLE_ISR;                       /* enable ISR access     */
    scsi_int_src = ISR_REG;			/* SCSI int status       */
    EMR_REG = 0x1a;				/* Reset int` latch	 */
    EMR_REG = 0x18;				/* Dummy write after rst */
    scsi_int_flag = 1;
    strcpy(msg__, "SCSI INTERRUPT !!!!!");
    print_str (msg__);
}


private char * test_int()
{
    scsi_int_flag = 0;
    scsi_int_src = 0;

    ICR_REG = E_MODE;				/* set SCSI to E mode    */
    EMR_REG = LOOP_BACK;			/* set SCSI to test mode */

    set_handler__(9,chk_scsi_int);		/* set int handler       */
    unmask_interrupt__(9);			/* unmask SCSI int in ICU */
    _interrupt_enable();			/* enable ICU int        */

    ICR_REG = 0x49;
    MR2_REG = 0x4a;
    TCR_REG = 0x08;
    			/*  ODR_REG = 0xa5;   */

    /* wait(10000);				 wait for an interrupt */
    EMR_REG = ENABLE_ISR;			/* enable IMR access     */
    IMR_REG = 0xff;				/* mask all int		 */

    mask_interrupt__(9);			/* unmask SCSI int in ICU */
    _interrupt_disable();			/* disable ICU int        */

    if (NOT scsi_int_flag) {
	strcpy(error, "FAILURE: NO INTERRUPT GENERATED");
	return error;
    }
    if (scsi_int_src != ARB_INT) {
	strcpy(error, "FAILURE: UNEXPECTED INTERRUPT");
	return error;
    }
    if (debug_flag) {
        strcpy(msg__, "SCSI INTERRUPT PASSED ");
        print_str (msg__);
    }
    return NULL;
}


/*********************************************************************
 *
 *	main scsi routine.
 *
 *  This is the main test routine.
 *
 ********************************************************************/

public char * test_scsi__()
{
    char * chp;


    if ((chp = test_control()) == NULL)
#ifdef NEVER
	if ((chp = test_data()) == NULL)
	    chp = test_int();
#else
	chp = test_data();
#endif
    return chp;
}
