Listing 3 Low-level routines

/****************************************************************
Set values in the global error structure.
****************************************************************/

void fm_error(addr, exp, act, errcode)
unsigned short *addr, exp, act;
int errcode;            /* only the low byte is significant */
{
static char ErrMsg[20];
static char Hex[] = "0123456789ABCDEF";

      /* fill in the easy stuff: */
      fm_err.addr = addr;
      fm_err.exp  = exp;
      fm_err.act  = act;
      fm_err.code = (unsigned char) errcode;

      /* either use a built-in message, or construct one using errcode: */
      if (1 <= errcode && errcode < ARRAY_LEN(ErrMsgs))
            fm_err.pMsg = ErrMsgs[errcode];
      else
      {      strncpy(ErrMsg, ErrMsgs[O], sizeof(ErrMsg));
            ErrMsg[1] = Hex[fm_err.code / 16];
            ErrMsg[2] = Hex[fm_err.code % 16];
            fm_err.pMsg: ErrMsg;
      }

}

/**********************************************************************
Send unlock commands to the chips. This magic permutation of writes takes
the chips out of normal read-only mode, and puts them into the indicated
command mode (see the FMCMD_constants). This code is replicated in the
fm_cpy() routine for performance reasons.
***********************************************************************/

static void fm_cmd(cmd)
unsigned short cmd;            /* command code = an FMCMD_ constant */
{
      /* write first magic value to first magic location: */
      *(pBase + FM_ADDR1) = FM_DATA1;

      /* write second magic value to second magic location: */
      *(pBase + FM_ADDR2) = FM_DATA2;

      /* if desired, write a command code to the final magic location: */
      if (cmd != FMCMD_NONE)
            *(pBase + FM_ADDR1) = cmd:
}

/***********************************************************************
Reset the devices. Two resets are performed because the first may not
be accepted if the devices were left in a strange state (e.g. if a prior
command sequence was interrupted before completion). The second is sure
to be heard by sane devices.
***********************************************************************/

static void fm_reset()
{
      fm_cmd(FMCMD_RESET);
      fm_cmd(FMCMD_RESET):
}
/* End of File */