/*****************************************************************************/
/* Copyright 1991 to 1999 MBARI                                              */
/*****************************************************************************/
/* Summary  : IP Octal SIO32 UART Driver for vxWorks                         */
/* Filename : ipOctal.c                                                      */
/* Author   : Andrew Pearce                                                  */
/* Project  : Tiburon ROV                                                    */
/* Version  : Version 1.0                                                    */
/* Created  : 06/21/91                                                       */
/* Modified : 06/04/99                                                       */
/* Archived :                                                                */
/*****************************************************************************/

#include "vxWorks.h"                /* vxWorks system declarations           */
#include "iosLib.h"                 /* vxWorks IO system declarations        */
#include "semLib.h"                 /* vxWorks Semaphore declarations        */
#include "memLib.h"                 /* vxWorks Memory allocation declarations*/
#include "rngLib.h"                 /* vxWorks ring buffer library           */
#include "taskLib.h"                /* vxWorks Task Libarary support decls   */
#include "vxLib.h"                  /* vxWorks vxTas routine definition      */

#include "mbariTypes.h"             /* MBARI style guide type declarations   */
#include "mbariConst.h"             /* Miscellaneous constants               */
#include "ModNum.h"                 /* MBARI module numbers for error code   */
#include "sio32Drv.h"               /* SIO32 Driver information              */
#include "scc2698.h"                /* SCC2698 hardware definitions          */
#include "mv162-ip.h"               /* Motorola MV162 Board IP Module defs   */
#include "ipOctal.h"                /* IP Octal Board hardware information   */

#include "arch/mc68k/ivMc68k.h"     /* vxWorks 68K definitions               */

/****************************************************************************/
/* Function    : configureMV162IP                                           */
/* Purpose     : Configures MV162 Industry Pack Interface Registers         */
/* Inputs      : IP Module Identifier                                       */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    Void
configureMV162IP (ipModuleId ipModule)
{
    switch (ipModule)
    {
      case IP_MODULE_A:            /* Configure IP Module A at 0xc0000000   */
        *(Word *) (IPIC_IP_A_MEM_BASE_HI) = 0xc000;
        *(IPIC_IP_A_MEM_SIZE)             = IPIC_IP_MEM_SIZE_8MB;

        *(IPIC_IP_A_INT0_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
           IPIC_IP_INT_DISABLE | IPIC_IP_INT_LVL5;

        *(IPIC_IP_A_INT1_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
          IPIC_IP_INT_DISABLE  | IPIC_IP_INT_LVL5;

        *(IPIC_IP_A_GEN_CTRL)  = IPIC_IP_REC_TIME_0_USEC |
         IPIC_IP_MEM_WIDTH_16_BIT | IPIC_IP_MEM_SPACE_ENABLE;

        break;

      case IP_MODULE_B:            /* Configure IP Module A at 0xc0800000   */
        *(Word *) (IPIC_IP_B_MEM_BASE_HI) = 0xc080;
        *(IPIC_IP_B_MEM_SIZE)             = IPIC_IP_MEM_SIZE_8MB;

        *(IPIC_IP_B_INT0_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
          IPIC_IP_INT_DISABLE  | IPIC_IP_INT_LVL5;

        *(IPIC_IP_B_INT1_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
          IPIC_IP_INT_DISABLE  | IPIC_IP_INT_LVL5;

        *(IPIC_IP_B_GEN_CTRL)  = IPIC_IP_REC_TIME_0_USEC |
          IPIC_IP_MEM_WIDTH_16_BIT | IPIC_IP_MEM_SPACE_ENABLE;

        break;

      case IP_MODULE_C:           /* Configure IP Module C at 0xc1000000   */
        *(Word *) (IPIC_IP_C_MEM_BASE_HI) = 0xc100;
        *(IPIC_IP_C_MEM_SIZE)             = IPIC_IP_MEM_SIZE_8MB;

        *(IPIC_IP_C_INT0_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
          IPIC_IP_INT_DISABLE  | IPIC_IP_INT_LVL5;

        *(IPIC_IP_C_INT1_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
          IPIC_IP_INT_DISABLE  | IPIC_IP_INT_LVL5;

        *(IPIC_IP_C_GEN_CTRL)  = IPIC_IP_REC_TIME_0_USEC |
          IPIC_IP_MEM_WIDTH_16_BIT | IPIC_IP_MEM_SPACE_ENABLE;

        break;

      case IP_MODULE_D:           /* Configure IP Module D at 0xc1800000   */
        *(Word *) (IPIC_IP_D_MEM_BASE_HI) = 0xc180;
        *(IPIC_IP_D_MEM_SIZE)             = IPIC_IP_MEM_SIZE_8MB;

        *(IPIC_IP_D_INT0_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
          IPIC_IP_INT_DISABLE  | IPIC_IP_INT_LVL5;

        *(IPIC_IP_D_INT1_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
          IPIC_IP_INT_DISABLE  | IPIC_IP_INT_LVL5;

        *(IPIC_IP_D_GEN_CTRL)  = IPIC_IP_REC_TIME_0_USEC |
          IPIC_IP_MEM_WIDTH_16_BIT | IPIC_IP_MEM_SPACE_ENABLE;

        break;
    } /* switch */
} /* configureMV162IP() */

/****************************************************************************/
/* Function    : IPModuleInterruptEnable                                    */
/* Purpose     : Enable IP Module Interrupt                                 */
/* Inputs      : IP Module Identifier                                       */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    Void
IPModuleConfigureInterrupt(ipModuleId ipModule, Nat16 intLevel)
{
    switch (ipModule)
    {
      case IP_MODULE_A:
        *(IPIC_IP_A_INT0_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
           IPIC_IP_INT_DISABLE | intLevel;

        *(IPIC_IP_A_INT1_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
           IPIC_IP_INT_DISABLE | intLevel;

        *(IPIC_IP_A_INT0_CTRL) |= IPIC_IP_INT_ENABLE;
        *(IPIC_IP_A_INT1_CTRL) |= IPIC_IP_INT_ENABLE;
        break;

      case IP_MODULE_B:
        *(IPIC_IP_B_INT0_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
           IPIC_IP_INT_DISABLE | intLevel;

        *(IPIC_IP_B_INT1_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
           IPIC_IP_INT_DISABLE | intLevel;

        *(IPIC_IP_B_INT0_CTRL) |= IPIC_IP_INT_ENABLE;
        *(IPIC_IP_B_INT1_CTRL) |= IPIC_IP_INT_ENABLE;
        break;

      case IP_MODULE_C:
        *(IPIC_IP_C_INT0_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
           IPIC_IP_INT_DISABLE | intLevel;

        *(IPIC_IP_C_INT1_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
           IPIC_IP_INT_DISABLE | intLevel;

        *(IPIC_IP_C_INT0_CTRL) |= IPIC_IP_INT_ENABLE;
        *(IPIC_IP_C_INT1_CTRL) |= IPIC_IP_INT_ENABLE;
        break;

      case IP_MODULE_D:
        *(IPIC_IP_D_INT0_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
           IPIC_IP_INT_DISABLE | intLevel;

        *(IPIC_IP_D_INT1_CTRL) = IPIC_IP_INT_NEGATIVE | IPIC_IP_INT_LEVEL_TRIG |
           IPIC_IP_INT_DISABLE | intLevel;

        *(IPIC_IP_D_INT0_CTRL) |= IPIC_IP_INT_ENABLE;
        *(IPIC_IP_D_INT1_CTRL) |= IPIC_IP_INT_ENABLE;
        break;
    } /* switch */
} /* IPModuleInterruptEnable() */

    Void
IPModuleInterruptEnable(ipModuleId ipModule)
{
    switch (ipModule)
    {
      case IP_MODULE_A:
        *(IPIC_IP_A_INT0_CTRL) |= IPIC_IP_INT_ENABLE;
        *(IPIC_IP_A_INT1_CTRL) |= IPIC_IP_INT_ENABLE;
        break;

      case IP_MODULE_B:
        *(IPIC_IP_B_INT0_CTRL) |= IPIC_IP_INT_ENABLE;
        *(IPIC_IP_B_INT1_CTRL) |= IPIC_IP_INT_ENABLE;
        break;

      case IP_MODULE_C:
        *(IPIC_IP_C_INT0_CTRL) |= IPIC_IP_INT_ENABLE;
        *(IPIC_IP_C_INT1_CTRL) |= IPIC_IP_INT_ENABLE;
        break;

      case IP_MODULE_D:
        *(IPIC_IP_D_INT0_CTRL) |= IPIC_IP_INT_ENABLE;
        *(IPIC_IP_D_INT1_CTRL) |= IPIC_IP_INT_ENABLE;
        break;
    } /* switch */
} /* IPModuleInterruptEnable() */

/****************************************************************************/
/* Function    : IPModuleInterruptDisable                                   */
/* Purpose     : Disable IP Module Interrupt                                */
/* Inputs      : IP Module Identifier                                       */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    Void
IPModuleInterruptDisable(ipModuleId ipModule)
{
    switch (ipModule)
    {
      case IP_MODULE_A:
        *(IPIC_IP_A_INT0_CTRL) &= ~IPIC_IP_INT_ENABLE;
        *(IPIC_IP_A_INT1_CTRL) &= ~IPIC_IP_INT_ENABLE;
        break;

      case IP_MODULE_B:
        *(IPIC_IP_B_INT0_CTRL) &= ~IPIC_IP_INT_ENABLE;
        *(IPIC_IP_B_INT1_CTRL) &= ~IPIC_IP_INT_ENABLE;
        break;

      case IP_MODULE_C:
        *(IPIC_IP_C_INT0_CTRL) &= ~IPIC_IP_INT_ENABLE;
        *(IPIC_IP_C_INT1_CTRL) &= ~IPIC_IP_INT_ENABLE;
        break;

      case IP_MODULE_D:
        *(IPIC_IP_D_INT0_CTRL) &= ~IPIC_IP_INT_ENABLE;
        *(IPIC_IP_D_INT1_CTRL) &= ~IPIC_IP_INT_ENABLE;
        break;
    } /* switch */
} /* IPModuleInterruptDisable() */

/****************************************************************************/
/* Function    : IPModuleIntVecSet                                          */
/* Purpose     : Writes Interrupt Vector to IP-Octal Module                 */
/* Inputs      : IP Module Identifier and Interrupt Vector Number           */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
IPModuleIntVecSet(ipModuleId ipModule, Byte ipIntVector)
{
    *(mv162IPModuleMap[ipModule].ipIntVectReg) = (char) ipIntVector;
} /* IPModuleIntVecSet() */

/****************************************************************************/
/* Function    : IPModuleIntVecGet                                          */
/* Purpose     : Reads Interrupt Vector from IP-Octal Module                */
/* Inputs      : IP Module Identifier                                       */
/* Outputs     : None                                                       */
/****************************************************************************/
    char
IPModuleIntVecGet(ipModuleId ipModule)
{
    return (*(mv162IPModuleMap[ipModule].ipIntVectReg));
} /* IPModuleIntVecGet() */

/****************************************************************************/
/* Function    : IPModuleReset                                              */
/* Purpose     : Asserts IP Module RESET signal                             */
/* Inputs      : None                                                       */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
IPModuleReset( Void )
{
    *(IPIC_IP_RESET_REG) = IPIC_IP_RESET;
    taskDelay(sysClkRateGet() / 5);             /* 200 mSec Delay           */
    *(IPIC_IP_RESET_REG) = ~IPIC_IP_RESET;
} /* IPModuleReset() */

/****************************************************************************/
/* Function    : sio32BoardProbe                                            */
/* Purpose     : checks for the presence of a telemetry board               */
/* Inputs      : NONE                                                       */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    STATUS
sio32BoardProbe(Nat32 uart, MBool sio32Debug)
{
    ipModuleId ipModule;
    char        probeVal;           /* location used by vxMemProbe          */

    ipModule = sio32IPModuleMap[uart];

                                    /* Look for Vector Register Address     */
    if (vxMemProbe ((char *) mv162IPModuleMap[ipModule].ipIntVectReg,
         VX_READ, sizeof(probeVal), &probeVal) != OK)
    {
        if (sio32Debug)
            printf("IP Module %s not found at 0x%x\n",
                 mv162IPModuleName[ipModule],
                 mv162IPModuleMap[ipModule].ipIntVectReg);

        errnoSet(ESIO32_NO_CARD);     /* Set task error number              */
        return (ERROR);
    } /* if */

    if ((vxMemProbe ((char*) mv162IPModuleMap[ipModule].ipIDSpaceAddr +
         IP_MODEL_OFFSET, VX_READ, sizeof(probeVal), &probeVal) != OK) ||
         (probeVal != IP_OCTAL_RS232_ID))
    {
        if (sio32Debug)
            printf("IP Module %s found at 0x%x is not an IP Octal RS232\n",
                 mv162IPModuleName[ipModule],
                 mv162IPModuleMap[ipModule].ipIntVectReg);

        errnoSet(ESIO32_NO_CARD);     /* Set task error number              */
        return (ERROR);
    } /* if */

                                    /* Look for memory at UART address      */
    if (vxMemProbe ((char*) mv162IPModuleMap[ipModule].ipIOSpaceAddr +
        IP_MODULE_UART_OFSFET, VX_READ, sizeof(probeVal), &probeVal) != OK)
    {
        if (sio32Debug)
            printf("IP Module %s: Missing UART at 0x%x\n",
                 mv162IPModuleName[ipModule],
                 mv162IPModuleMap[ipModule].ipIOSpaceAddr + 1);

        errnoSet(ESIO32_NO_CARD);     /* Set task error number              */
        return (ERROR);
    } /* if */

    if (sio32Debug)               /* Everything checks out OK               */
        printf("IP Octal Module %s found at 0x%x\n",
            mv162IPModuleName[ipModule],
            mv162IPModuleMap[ipModule].ipIntVectReg);
    return(OK);                   /* So return OK                           */
} /* sio32BoardProbe() */

/*****************************************************************************/
/* Function    : sio32InitInterrupts                                         */
/* Purpose     : Initialize and enable hardware interrupts                   */
/* Inputs      : uart, interrupt vector and interrupt level                  */
/* Outputs     : None                                                        */
/*****************************************************************************/
    Void
sio32InitInterrupts(Nat32 uart, Nat16 intVec, Nat16 intLevel)
{
    ipModuleId ipModule = sio32IPModuleMap[uart];

                                    /* Attach interrupt handlers for hardware*/
    intConnect(INUM_TO_IVEC((Char) intVec), sio32Interrupt, uart);

                                    /* Set Interrupt Vector on IP Module     */
    IPModuleIntVecSet(ipModule, intVec);
                                    /* Enable interrupts IP Module           */
    IPModuleConfigureInterrupt(ipModule, intLevel); 
} /* sio32InitInterrupts() */


