Subversion Repositories factorylink.mb_plus

Rev

Blame | Last modification | View Log | Download

/*
 ******************************************************************************
 *  Copyright 1995 DeltaLink b.v. All Rights Reserved.
 ******************************************************************************
 *
 * DeltaLink Mailbox Communication Interface
 *
 * File         :   mcids.c
 *
 * Version      :   3.00
 * 
 * Developed by :   Leon Westervoort.
 *
 */

#include  <stdlib.h>
#include  <string.h>
#include  <stdio.h>
#include  <stdarg.h>

#include  <flib.h>                  /* FactoryLink definitions */

#include  <mci3.h>                   /* Mailbox Communication Interface definitions */
#include  <mci3_int.h>               /* Mailbox Communication Interface definitions */
#include  <format3.h>                /* Mailbox Communication Interface definitions */

/*
 * FUNCTION:  Mci_Ds_Register
 *
 * PURPOSE:    Register a dataset to the MCI library. All information of the dataset must be 
 *            set on the dataset structure first.
 *
 */

MCIDS *Mci_Ds_Register( MCIDS *ds )
{
  TAG l_ctrl;
  MSG *hdr;

  /*
   * check if this is the first dataset to register and if so the register also
   * the MCI mailbox
   */
  if( !_Mci_num_ds) {

    /* allocate the first elements of the tag arrays */

    if( ( _Mci_R_ds = ( TAG *)calloc( 1, sizeof( TAG))) == ( TAG *)0) 
      return NULL;

    if( ( _Mci_R_station_id = ( char *)calloc( 1, sizeof( char))) == ( char *)0)
      return NULL;

    if( ( _Mci_L_ds = ( TAG *)calloc( 1, sizeof( TAG))) == ( TAG *)0) 
      return NULL;

    if( ( _Mci_ds = ( MCIDS **)calloc( 1, sizeof( MCIDS *))) == ( MCIDS **)0)
      return NULL;

    if( ( _Mci_ds[ 0] = ( MCIDS *)calloc( 1, sizeof( MCIDS))) == ( MCIDS *)0)
      return NULL;

    if( ( _Mci_fnc = ( MCI_FNC_ATYPE)calloc( 1, sizeof( MCI_FNC_TYPE) )) == ( MCI_FNC_ATYPE)0)
      return NULL;
           

    /* update the values in the dataset control tag arrays */

    memcpy( _Mci_L_ds, ( char *)&Mci_Sys_Get_Mbx( &_Mci_system ), sizeof( TAG));
    memcpy( _Mci_R_ds, ( char *)&Mci_Sys_Get_Mbx( &_Mci_system ), sizeof( TAG));

    _Mci_fnc[ 0] = Mci_Event_Mbx;

    _Mci_num_ds = 1;
  }

  /*
   * resize the arrays which hold the internal dataset information
   */

  if( ( _Mci_R_ds = ( TAG *)realloc( _Mci_R_ds, (_Mci_num_ds +1) * sizeof( TAG))) == ( TAG *)0) 
    return NULL;

  if( ( _Mci_R_station_id = ( char *)realloc( _Mci_R_station_id, (_Mci_num_ds +1) * sizeof( char))) == ( char *)0) 
    return NULL;

  if( ( _Mci_L_ds = ( TAG *)realloc( _Mci_L_ds, (_Mci_num_ds +1) * sizeof( TAG))) == ( TAG *)0) 
    return NULL;

  if( ( _Mci_ds = ( MCIDS **)realloc( _Mci_ds, (_Mci_num_ds +1) * sizeof( MCIDS *))) == ( MCIDS **)0)
    return NULL;

  if( ( _Mci_ds[ _Mci_num_ds] = ( MCIDS *)calloc( 1, sizeof( MCIDS))) == ( MCIDS *)0)
    return NULL;

  if( ( _Mci_fnc = ( MCI_FNC_ATYPE)realloc( _Mci_fnc, (_Mci_num_ds +1) * sizeof( MCI_FNC_TYPE))) == ( MCI_FNC_ATYPE)0 )
    return NULL;

  _Mci_fnc[ _Mci_num_ds] = Mci_Event_Ds;

  /* copy the total user dataset to the new allocated dataset */

  memcpy( _Mci_ds[ _Mci_num_ds], ds, sizeof( MCIDS));


  /* initialize the remote dataset control tag list */

  _Mci_R_ds[ _Mci_num_ds].t_type = ( u16)FL_BAD_TYPE;
  _Mci_R_ds[ _Mci_num_ds].t_data = ( u16)FL_BAD_TYPE;

  /* initialize the remote station id to local */

  _Mci_R_station_id[ _Mci_num_ds] = Mci_Sys_Get_Station_Id( &_Mci_system );

  /* initialize the local dataset control tag */

  memcpy( &_Mci_L_ds[ _Mci_num_ds], Mci_Get_Ds_Ctrl( _Mci_ds[ _Mci_num_ds]), sizeof( TAG));

  /* check if the dataset control tag existst on this system */

  if( Mci_name2tag( Mci_Get_Name( ds), &l_ctrl) == ERROR)
    return NULL;

  if( MCI_CMPTAG( Mci_Get_Ds_Ctrl( ds), &l_ctrl) != GOOD)
    return NULL;

  /* initialize the dataset information */

  hdr = Mci_Get_T_Buffer( _Mci_ds[ _Mci_num_ds]);

  if( hdr->m_ptr) {

    _Mci_ds[ _Mci_num_ds]->start        = Mci_Get_Start        ( _Mci_ds[ _Mci_num_ds]);    /* start address */
    _Mci_ds[ _Mci_num_ds]->len          = Mci_Get_Len          ( _Mci_ds[ _Mci_num_ds]);    /* length of data depending on boundary */

    _Mci_ds[ _Mci_num_ds]->boundary      = Mci_Get_Boundary    ( _Mci_ds[ _Mci_num_ds]);   /* boundary addressing */
    _Mci_ds[ _Mci_num_ds]->bnd_dir      = Mci_Get_Bnd_Dir      ( _Mci_ds[ _Mci_num_ds]);   /* direction of boundary data */
    _Mci_ds[ _Mci_num_ds]->bit_dir      = Mci_Get_Bit_Dir      ( _Mci_ds[ _Mci_num_ds]);   /* direction of bit data */
    _Mci_ds[ _Mci_num_ds]->bnd_offset    = Mci_Get_Bnd_Offset  ( _Mci_ds[ _Mci_num_ds]);    /* addressing offset of boundary data */
    _Mci_ds[ _Mci_num_ds]->bit_offset    = Mci_Get_Bit_Offset  ( _Mci_ds[ _Mci_num_ds]);   /* addressing offset of bit data */
  }

  _Mci_ds[ _Mci_num_ds]->msg.snd_mbx  = Mci_Get_Snd_Mbx      ( _Mci_ds[ _Mci_num_ds]);     /*  mailbox tag to send to */

  Mci_Set_Index( _Mci_ds[ _Mci_num_ds], 0);                                               /* set the index in the queue of message */
  Mci_Reset_Buffer( _Mci_ds[ _Mci_num_ds]);                                               /* reset the actual buffer */

  /* set the index into the dataset control tag array */

  _Mci_ds[ _Mci_num_ds]->ds_index     = _Mci_num_ds;

  return _Mci_ds[ _Mci_num_ds++];
}

/*
 * FUNCTION:  Mci_Ds_Prepare
 *
 * PURPOSE:    Prepares a dataset before sending into the MCI mailbox. All the default
 *            values which were passed when the dataset was registered will be loaded.
 *            In case the user wants to change some values specific MCI function can be 
 *            called after this function.
 *
 */

int Mci_Ds_Prepare( MCIDS *ds, MSG *buffer)
{
  /* before restoring the registered values set the buffer */

  if( buffer != NULL)
  {
    buffer->m_len = sizeof( MCIHDR );

    Mci_Set_T_Buffer      ( ds, buffer );                /* buffer with MCI data */
  }
  else
  {
    /* set the buffer parameters set at registering time */

    Mci_Set_T_Buffer      ( ds, Mci_Get_R_Buffer( ds ));

    ds->msg.mbx.mm_msg.m_len = sizeof( MCIHDR );
  }

  /* initialize the dataset information */

  Mci_Set_Version       ( ds, MCI_VERSION);

  Mci_Set_Org_Host_Dir  ( ds, HOST_DIRECTION);
  Mci_Set_Station_Id    ( ds, Mci_Sys_Get_Station_Id( &_Mci_system ));

  Mci_Set_Ds_Ctrl       ( ds, _Mci_L_ds[ ds->ds_index]);  /* set the local dataset control tag */

  Mci_Set_Start         ( ds, ds->start);                 /* start address */
  Mci_Set_Len           ( ds, ds->len);                   /* length of data depending on boundary */

  Mci_Set_Boundary      ( ds, ds->boundary);              /* boundary addressing */
  Mci_Set_Bnd_Dir       ( ds, ds->bnd_dir);               /* direction of boundary data */
  Mci_Set_Bit_Dir       ( ds, ds->bit_dir);               /* direction of bit data */
  Mci_Set_Bnd_Offset    ( ds, ds->bnd_offset);            /* addressing offset of boundary data */
  Mci_Set_Bit_Offset    ( ds, ds->bit_offset);            /* addressing offset of bit data */

  /*Mci_Set_Index        ( ds, 0);                        /* set the index in the queue of message */

  return GOOD;
}

/*
 * FUNCTION:  Mci_Ds_R_Search
 *
 * PURPOSE:    Search for a registered dataset and return the pointer to the dataset.
 *
 */

MCIDS  *Mci_Ds_R_Search( TAG *ds_ctrl) {

  uint  i;

  /* search for the registered dataset by comparing the dataset control tags */

  for( i = 0; i < _Mci_num_ds; i++) {

    if( MCI_CMPTAG( ds_ctrl, &_Mci_L_ds[ i]) == GOOD)
      return _Mci_ds[ i];
  }

  return NULL;
}

/*
 * FUNCTION:  Mci_Ds_Query
 *
 * PURPOSE:    This function send a query request of the dataset to the remote
 *            task. Only tasks which don't have dataset information should
 *            execute this command such as decoders.
 *
 */

int Mci_Ds_Query( MCIDS *ds) {

  int    ret;
  MSG    q;

  /* set the type of message to QUERY */

  Mci_Set_Type( ds, MCI_QUERY_CMD);

  /* allocate space for the header and the tag name */

  q.m_max = ( u16)( strlen( ds->name) +1);

  if( ( ret = Mci_Buffer_Alloc( &q)) != GOOD ) return ret;

  /* set the lenght in the MCI header portion */

  Mci_Set_Ds_Ctrl    ( ds, _Mci_L_ds[ ds->ds_index]);

  Mci_Set_T_Buffer  ( ds, &q);
  Mci_Set_Len        ( ds, ( u16)strlen( Mci_Get_Name( ds)));

  /* set the name of the dataset control tag */

  strcpy( Mci_Get_U_Buffer( ds), Mci_Get_Name( ds));

  /* send the request for dataset information to the other task */

  ret = Mci_Send( &_Mci_system, ds);

  free( q.m_ptr);

  Mci_Reset_Buffer( ds);                                               

  return ret;
}

/*
 * FUNCTION:  Mci_Ds_Queried
 *
 * PURPOSE:    This function checks wether a dataset has been queried already 
 *            or not.
 */

int Mci_Ds_Queried( MCIDS *ds) {

  return  ( _Mci_R_ds[ ds->ds_index].t_type == 0xFFFF) &&
          ( _Mci_R_ds[ ds->ds_index].t_data == 0xFFFF);
}

/*
 * FUNCTION:  Mci_Ds_Trigger
 *
 * PURPOSE:    Trigger a dataset which means that a datasets must be read. The function
 *            either triggers the dataset control tag if the dataset remains on the local
 *            system or generates a MCI read message.
 *
 */
int Mci_Ds_Trigger( MCISYSTEM *system , MCIDS *ds )
{
  DIG dig = 1;
  int  ret;

  /*
   * check first if this dataset remains on the local. If not the generate an
   * MCI message otherwise just trigger the dataset
   */
  if( _Mci_R_station_id[ ds->ds_index] != Mci_Sys_Get_Station_Id( system ) )
  {
    /* initialize the dataset */

    Mci_Ds_Prepare( ds, NULL );

    /* send the request for reading the dataset to the remote system */

    Mci_Set_Type( ds, MCI_READ_REQ);

    if( ( ret = Mci_Send( system, ds)) != GOOD) return ret;

  }
  else
  {
    /* trigger the DataSet Control Tag with a forced write */

    if( fl_forced_write( Mci_Sys_Get_Task_Id( system ), 
                          &_Mci_L_ds[ ds->ds_index],
                          1, 
                          &dig) != GOOD )
      return fl_errno( Mci_Sys_Get_Task_Id( system ));
  }

  return GOOD;
}

/*
 * FUNCTION:  Mci_Ds_Remove
 *
 * PURPOSE:    Removes all datasets with the same MCI function and dataset control tag from
 *            the mailbox queue. The function check which type the dataset has and removes
 *            all function related messages.
 *
 */
int Mci_Ds_Remove( MCISYSTEM *system , MCIDS *ds ) {

  int      ret;
  MCIDS    tmp_ds;

  /*
   * check first if there are active messages pending
   */
  if( !_Mci_q_num_active ) return GOOD;

  memset( &tmp_ds, 0x00, sizeof( MCIDS ));

  /*
   * copy the dataset information to the temporary dataset
   */
  memcpy( ( char *)&tmp_ds.msg, ( char *)&ds->msg, sizeof( MCIMSG));

  /* initialize the temporary dataset structure */

  Mci_Set_Index( &tmp_ds, 0);
  Mci_Reset_Buffer( &tmp_ds);

  /*
   * search the active dataset queue for datasets with the same
   *  dataset control tag and functionality group
   */
  for( ; ; ) {

    if( Mci_Q_Ds_Srch( system, &tmp_ds )) {

      /*
       * check if this message is of the same function
       */
      if( ( ret = Mci_Q_Query( system, &tmp_ds)) != GOOD)
        return ret;

      /* check if the type types are identical */

      if( Mci_Get_Type( &tmp_ds) == Mci_Get_Type( ds)) {

        /* send an error message to the remote system if necessary */

        switch( Mci_Get_Type( &tmp_ds) ) {

          case MCI_QUERY_CMD    :            /* MCI info message */
          case MCI_READ_REQ     :            /* read request */
          case MCI_WRITE_REQ    :            /* write request */
          case MCI_RCV_RDY      :            /* unsolicited receive ready */

            Mci_Send_Error( system, &tmp_ds, MCI_MSG_REJECTED);
          break;
        }

        /* remove the message from the queue */

        if( ( ret = Mci_Recv( system, &tmp_ds)) != GOOD)
          return ret;
      }
      else
        Mci_Set_Index( &tmp_ds, Mci_Get_Index( &tmp_ds) + 1);

    }
    else
      break;
  }

  return GOOD;
}

/*
 * FUNCTION: Mci_Ds_Adjust
 *
 * PURPOSE:  This functions adjusts a MCI message to the lowest possible boundary. This
 *           will be done by checking the CDE code against the boundary. The lowest boundary
 *           will be a byte boundary.
 *
 *           In case of bit boundary an error will be returned because it cannot be processed.
 *           A bit boundary cannot be checked against the CDE code because it must always
 *           be a block write.   
 *
 *           In case the CDE operation is smaller than the boundary then the data is always
 *           in the format of the HOST.
 *
 *           In case the CDE operation is equal or greater than the boundary then the data
 *           will be in the rigth format for the destination. The sender of the MCI dataset 
 *           has this responsibility.  
 */
int Mci_Ds_Adjust( MCIDS *ds) {

  u16 bit = 0xFFFF;

  /*
   * check first if a bit boundary is specified or a block write command
   */
  if( (Mci_Get_Boundary( ds) == MCI_BIT_BND) || (Mci_Get_CDE( ds) == CDE_BLOCK)) 
    return MCI_BLOCK;

  /*
   * check the CDE operation against the boundary
   */
  switch( Mci_Get_Boundary( ds)) {

    case MCI_BYTE_BND:

      if( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) < CDE_BYTE) {
        /*
         * set bit value for the minimal boundary
         */
        if( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) < CDE_NIBBLE)         /* set boundary according to bits */
          bit = ( u16)( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) - CDE_B0_15);
        else
          bit = ( u16)( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) - CDE_NIBBLE);
      }

      break;
    case MCI_WORD_BND:

      if( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) < CDE_SIGNED) {
        /*
         * set bit value for the minimal boundary
         */
        if( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) < CDE_NIBBLE)         /* set boundary according to bits */
          bit = ( u16)( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) - CDE_B0_15);
        else if( Mci_Get_CDE( ds) < CDE_BYTE)
          bit = ( u16)( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) - CDE_NIBBLE);
        else 
          bit = ( u16)( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) - CDE_BYTE);
      }

      break;
    case MCI_LONG_BND:

      if( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) < CDE_LONG) {
        /*
         * set bit value for the minimal boundary
         */
        if( Mci_Get_CDE( ds) < CDE_NIBBLE)         /* set boundary according to bits */
          bit = ( u16)( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) - CDE_B0_15);
        else if( Mci_Get_CDE( ds) < CDE_BYTE)
          bit = ( u16)( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) - CDE_NIBBLE);
        else if( Mci_Get_CDE( ds) < CDE_SIGNED)
          bit = ( u16)( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) - CDE_BYTE);
        else 
          bit = ( u16)( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) - CDE_SIGNED);
      }

      break;
    case MCI_DBL_BND:

      if( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) < CDE_DOUBLE_IEEE_FLT) {
        /*
         * set bit value for the minimal boundary
         */
        if( Mci_Get_CDE( ds) < CDE_NIBBLE)         /* set boundary according to bits */
          bit = ( u16)( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) - CDE_B0_15);
        else if( Mci_Get_CDE( ds) < CDE_BYTE)
          bit = ( u16)( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) - CDE_NIBBLE);
        else if( Mci_Get_CDE( ds) < CDE_SIGNED)
          bit = ( u16)( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) - CDE_BYTE);
        else if( Mci_Get_CDE( ds) < CDE_LONG)
          bit = ( u16)( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) - CDE_SIGNED);
        else
          bit = ( u16)( Mci_Get_CDE( ds) - Mci_Get_Bit_Offset( ds ) - CDE_LONG);
      }
      break;

    default:
      return MCI_UNKNOWN_BOUND;
  }

  /*
   * in case the bit value is not -1 then the CDE < boundary. In this case the bit number
   * contains the number of bits of the variable.
   */
  if( bit != 0xFFFF) {

    /*
     * check first if the data direction is the same as the HOST data direction. If not
     * then only one data boundary element has to be mirrored
     * THIS HAPPENS IN MCI_CAST !!!!!! 
     */
    /*if( Mci_Get_Bound_Dir( ds) != HOST_DIRECTION) {*/
    
    /*  #ifdef DEBUG*/
    /*  printf("\nMCI: adjust: mirror the data");*/
    /*  #endif*/
    
    /*  mirror( Mci_Get_Buffer( ds), Mci_Get_Boundary( ds));*/
    /*  Mci_Set_Bound_Dir( ds, HOST_DIRECTION);*/
    /*}*/

    /* set the boundary to a minimal value */

    if( bit < 8) {

      Mci_Cast( ds, MCI_BYTE_BND);

      Mci_Set_Len( ds, MCI_BYTE_BND);
      Mci_Set_Boundary( ds, MCI_BYTE_BND);
    }
    else if( bit < 16) {

      Mci_Cast( ds, MCI_WORD_BND);

      Mci_Set_Len( ds, MCI_WORD_BND);
      Mci_Set_Boundary( ds, MCI_WORD_BND);
    }
    else if( bit < 32) {

      Mci_Cast( ds, MCI_LONG_BND);

      Mci_Set_Len( ds, MCI_LONG_BND);
      Mci_Set_Boundary( ds, MCI_LONG_BND);
    }
    else if( bit < 64) {

      Mci_Cast( ds, MCI_DBL_BND);

      Mci_Set_Len( ds, MCI_DBL_BND);
      Mci_Set_Boundary( ds, MCI_DBL_BND);
    }
    else
      return MCI_CDE_SIZE;
  }
  else {

    /* CDE >= boundary:
     * in this case the boundary can be minimalized to byte boundary. The data format is
     * assumed OK
     */
    Mci_Set_Len( ds, ( u16)( Mci_Get_Boundary( ds) * Mci_Get_Len( ds)));
    Mci_Set_Boundary( ds, MCI_BYTE_BND);  
  }

  return GOOD;
}

/*-----------------------------------------------------------------------------
 * FUNCTION: int Mci_Ds Evaluate_Write( MCIDS *)
 *
 * PUPRPOSE: Evaluates the MCI dataset if it is possible to write this message
 *           and if this is the case if it will be a real exception write (reading
 *           before writing) or a block write.
 *
 -----------------------------------------------------------------------------*/

int Mci_Ds_Evaluate_Write( MCIDS *ds) {

  int ret;

  /*  
   *  first try to convert the boundary to the lowest possible so we have the most 
   *  chance to do the write at once 
   */
  if(  ( ret = Mci_Ds_Adjust( ds)) != GOOD) return ret;

  /*
   * check first if the destination boundary (of dataset) is a bit boundary. If this
   * is the case then the data is already in the correct state (Mci_Adjust_Msg) and
   * only the length needs to be adjusted
   */
  if( ds->boundary == MCI_BIT_BND) {

    /*
     * this will always be a block write. In this case only the lowest CDE is possible
     * of every type
     */
    switch( Mci_Get_CDE( ds)) {

      case CDE_B0_15:                     /* write one bit */

        Mci_Set_Len( ds, 1);
        break;

      case CDE_BYTE:                      /* convert to block write of 8 bits */
      case CDE_UBYTE:

        Mci_Set_Len( ds, 8);
        break;

      case CDE_SIGNED:                    /* convert to block write of 16 bits */
      case CDE_UNSIGNED:

        Mci_Set_Len( ds, 16);
        break;

      case CDE_LONG:                      /* convert to block write of 32 bits */
      case CDE_ULONG:

        Mci_Set_Len( ds, 32);
        break;

      case CDE_DOUBLE_IEEE_FLT:           /* convert to block write of 64 bits */

        Mci_Set_Len( ds, 64);
        break;

      default:

        /* another addressing type on bit boundary is not possible */

        return MCI_BIT_ADDRESSING;
    }

    /* set the type to block write */

    Mci_Set_CDE( ds, CDE_BLOCK);

    return MCI_BLOCK;
  }

  /*
   * in case the MCI boundary is greater than the dataset boundary then it is not
   * possible to write the element.
   */
  if( Mci_Get_Boundary( ds) > ds->boundary) return MCI_X_WRITE;


  /*
   * MCI boundary <= dataset boundary
   *
   * in this case check the CDE against the dataset boundary. If the CDE is smaller
   * then this is a real exception write, otherwise it will be a block write
   */

  switch( ds->boundary) {

    case MCI_BYTE_BND:

      if( Mci_Get_CDE( ds) >= CDE_BYTE) {             /* exception write ? */

        /* adjust the boundary and length to the dataset */

        Mci_Set_CDE( ds, CDE_BLOCK);
      }

      break;
    case MCI_WORD_BND:

      if( Mci_Get_CDE( ds) < CDE_SIGNED) {             /* exception write ? */
        /*
         * expand the data of the ds message to the dataset boundary if 
         * boundary is not equal
         */
        if( Mci_Get_Boundary( ds) < MCI_WORD_BND)
          Mci_Cast( ds, MCI_WORD_BND);
      }
      else                                              /* adjust the CDE code to block write */
        Mci_Set_CDE( ds, CDE_BLOCK);

      break;

    case MCI_LONG_BND:

      if( Mci_Get_CDE( ds) < CDE_LONG) {               /* exception write ? */
        /*
         * expand the data of the ds message to the dataset boundary if
         * boundary is not equal
         */
        if( Mci_Get_Boundary( ds) < MCI_LONG_BND) 
          Mci_Cast( ds, MCI_LONG_BND);
      }
      else                                              /* adjust the CDE code to block write */ 
        Mci_Set_CDE( ds, CDE_BLOCK);
      break;

    case MCI_DBL_BND:

      if( Mci_Get_CDE( ds) < CDE_DOUBLE_IEEE_FLT) {    /* exception write ? */
        /*
         * expand the data of the ds message to the dataset boundary if
         * boundary is not equal
         */
        if( Mci_Get_Boundary( ds) < MCI_DBL_BND) 
          Mci_Cast( ds, MCI_DBL_BND);

      }
      else                                              /* adjust the CDE code to block write */ 
        Mci_Set_CDE( ds, CDE_BLOCK);

      break;
  }

  if( Mci_Get_CDE( ds) == CDE_BLOCK) {
   
    Mci_Set_Len( ds, ( u16)( (Mci_Get_Len( ds) * Mci_Get_Boundary( ds)) / ds->boundary));

    /* set the boundary to the dataset boundary */

    Mci_Set_Boundary( ds, ds->boundary);

    /*
     * check the direction of the data
     */
    if( Mci_Get_Bnd_Dir( ds) != ds->bnd_dir) {

      Mci_Mirror( Mci_Get_U_Buffer( ds), ( u16)( Mci_Get_Len( ds) * Mci_Get_Boundary( ds)));
      Mci_Set_Bnd_Dir( ds, ds->bnd_dir);
    }

    return MCI_BLOCK;
  }
  else {

    Mci_Set_Len( ds, 1);                           /* set to the length of one element */

    /* set the boundary to the dataset boundary */

    Mci_Set_Boundary( ds, ds->boundary);

    /*
     * set the data on the right place in case of an exception write
     */
    Mci_Place_Data( ds, ds->bnd_dir);

    Mci_Set_Bnd_Dir( ds, ds->bnd_dir);

    return GOOD;
  }
}

/*-----------------------------------------------------------------------------
 * FUNCTION: int Mci_Equal_Data( MCIDS *)
 *
 * PUPRPOSE: This function equalizes the direction of the current data on the
 *           dataset with the registered and true data direction of the dataset
 *
 -----------------------------------------------------------------------------*/
#ifdef NODIG
int Mci_Equal_Data( MCIDS *ds) {

  void  *data;


  /* check if the registered data direction differs from the actual direction */

  if( Mci_Get_Bnd_Dir( ds) == ds->bnd_dir)
    return GOOD;

  /* adjust the data to the registered direction */

  /*
   * bit operation smaller than nibble
   */
  if( Mci_Get_CDE( ds) < CDE_NIBBLE)
  {
    return GOOD;
  }
  /*
   * nibble exception write in a byte
   */
  else if( Mci_Get_CDE( ds) < CDE_BYTE)
  {
    return -1; /* not supported at the moment  */
  }
  /*
   * byte exception write in a word
   */
  else if( Mci_Get_CDE( ds) < CDE_SIGNED)
  {
    /* swap the bytes in the word */

    swab( Mci_Get_U_Buffer( ds), Mci_Get_U_Buffer( ds), 2);
  }
  /*
   * word exception write in a long
   */
  else if( Mci_Get_CDE( ds) < CDE_LONG)
  {
    /* reverse the bytes in a long */

    ( u32 *)data = ( u32 *)Mci_Get_U_Buffer( ds);

    *( u32 *)(data) = (( *( u32 *)data >> 24) & 0x000000ff) |
                      (( *( u32 *)data >> 8)  & 0x0000ff00) |
                      (( *( u32 *)data << 8 ) & 0x00ff0000) |
                      (( *( u32 *)data << 24) & 0xff000000);

  }

  return GOOD;
}
#endif