OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [rdi-share/] [hostchan.c] - Diff between revs 107 and 1765

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 107 Rev 1765
/*
/*
 * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
 * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
 *
 *
 * This software may be freely used, copied, modified, and distributed
 * This software may be freely used, copied, modified, and distributed
 * provided that the above copyright notice is preserved in all copies of the
 * provided that the above copyright notice is preserved in all copies of the
 * software.
 * software.
 */
 */
 
 
/* -*-C-*-
/* -*-C-*-
 *
 *
 * $Revision: 1.1.1.1 $
 * $Revision: 1.1.1.1 $
 *     $Date: 2001-05-18 11:16:42 $
 *     $Date: 2001-05-18 11:16:42 $
 *
 *
 *
 *
 * hostchan.c - Semi Synchronous Host side channel interface for Angel.
 * hostchan.c - Semi Synchronous Host side channel interface for Angel.
 */
 */
 
 
#include <stdio.h>
#include <stdio.h>
 
 
#ifdef HAVE_SYS_TIME_H
#ifdef HAVE_SYS_TIME_H
#  include <sys/time.h>
#  include <sys/time.h>
#else
#else
#  include "winsock.h"
#  include "winsock.h"
#  include "time.h"
#  include "time.h"
#endif
#endif
#include "hsys.h"
#include "hsys.h"
#include "host.h"
#include "host.h"
#include "logging.h"
#include "logging.h"
#include "chandefs.h"
#include "chandefs.h"
#include "chanpriv.h"
#include "chanpriv.h"
#include "devclnt.h"
#include "devclnt.h"
#include "buffers.h"
#include "buffers.h"
#include "drivers.h"
#include "drivers.h"
#include "adperr.h"
#include "adperr.h"
#include "devsw.h"
#include "devsw.h"
#include "hostchan.h"
#include "hostchan.h"
 
 
#ifndef UNUSED
#ifndef UNUSED
#define UNUSED(x) (x = x)  /* Silence compiler warnings for unused arguments */
#define UNUSED(x) (x = x)  /* Silence compiler warnings for unused arguments */
#endif
#endif
 
 
#define HEARTRATE 5000000
#define HEARTRATE 5000000
 
 
/*
/*
 * list of available drivers, declared in drivers.c
 * list of available drivers, declared in drivers.c
 */
 */
extern DeviceDescr *devices[];
extern DeviceDescr *devices[];
 
 
static DeviceDescr *deviceToUse = NULL;
static DeviceDescr *deviceToUse = NULL;
 
 
static struct Channel {
static struct Channel {
    ChannelCallback callback;
    ChannelCallback callback;
    void *callback_state;
    void *callback_state;
} channels[CI_NUM_CHANNELS];
} channels[CI_NUM_CHANNELS];
 
 
static unsigned char HomeSeq;
static unsigned char HomeSeq;
static unsigned char OppoSeq;
static unsigned char OppoSeq;
 
 
/*
/*
 * Handler for DC_APPL packets
 * Handler for DC_APPL packets
 */
 */
static DC_Appl_Handler dc_appl_handler = NULL;
static DC_Appl_Handler dc_appl_handler = NULL;
 
 
/*
/*
 * slots for registered asynchronous processing callback procedures
 * slots for registered asynchronous processing callback procedures
 */
 */
#define MAX_ASYNC_CALLBACKS 8
#define MAX_ASYNC_CALLBACKS 8
static unsigned int             num_async_callbacks = 0;
static unsigned int             num_async_callbacks = 0;
static Adp_Async_Callback       async_callbacks[MAX_ASYNC_CALLBACKS];
static Adp_Async_Callback       async_callbacks[MAX_ASYNC_CALLBACKS];
 
 
/*
/*
 * writeQueueRoot is the queue of write requests pending acknowledgement
 * writeQueueRoot is the queue of write requests pending acknowledgement
 * writeQueueSend is the queue of pending write requests which will
 * writeQueueSend is the queue of pending write requests which will
 * be a subset of the list writeQueueRoot
 * be a subset of the list writeQueueRoot
 */
 */
static Packet *writeQueueRoot = NULL;
static Packet *writeQueueRoot = NULL;
static Packet *writeQueueSend = NULL;
static Packet *writeQueueSend = NULL;
static Packet *resend_pkt = NULL;
static Packet *resend_pkt = NULL;
static int resending = FALSE;
static int resending = FALSE;
 
 
/* heartbeat_enabled is a flag used to indicate whether the heartbeat is
/* heartbeat_enabled is a flag used to indicate whether the heartbeat is
 * currently turned on, heartbeat_enabled will be false in situations
 * currently turned on, heartbeat_enabled will be false in situations
 * where even though a heartbeat is being used it is problematical or
 * where even though a heartbeat is being used it is problematical or
 * dis-advantageous to have it turned on, for instance during the
 * dis-advantageous to have it turned on, for instance during the
 * initial stages of boot up
 * initial stages of boot up
 */
 */
unsigned int heartbeat_enabled = FALSE;
unsigned int heartbeat_enabled = FALSE;
/* heartbeat_configured is set up by the device driver to indicate whether
/* heartbeat_configured is set up by the device driver to indicate whether
 * the heartbeat is being used during this debug session.  In contrast to
 * the heartbeat is being used during this debug session.  In contrast to
 * heartbeat_enabled it must not be changed during a session.  The logic for
 * heartbeat_enabled it must not be changed during a session.  The logic for
 * deciding whether to send a heartbeat is: Is heartbeat_configured for this
 * deciding whether to send a heartbeat is: Is heartbeat_configured for this
 * session? if and only if it is then if heartbeat[is currently]_enabled and
 * session? if and only if it is then if heartbeat[is currently]_enabled and
 * we are due to send a pulse then send it
 * we are due to send a pulse then send it
 */
 */
unsigned int heartbeat_configured = TRUE;
unsigned int heartbeat_configured = TRUE;
 
 
void Adp_initSeq( void ) {
void Adp_initSeq( void ) {
  Packet *tmp_pkt = writeQueueSend;
  Packet *tmp_pkt = writeQueueSend;
 
 
  HomeSeq = 0;
  HomeSeq = 0;
  OppoSeq = 0;
  OppoSeq = 0;
  if ( writeQueueSend != NULL) {
  if ( writeQueueSend != NULL) {
    while (writeQueueSend->pk_next !=NULL) {
    while (writeQueueSend->pk_next !=NULL) {
      tmp_pkt = writeQueueSend;
      tmp_pkt = writeQueueSend;
      writeQueueSend = tmp_pkt->pk_next;
      writeQueueSend = tmp_pkt->pk_next;
      DevSW_FreePacket(tmp_pkt);
      DevSW_FreePacket(tmp_pkt);
    }
    }
  }
  }
  tmp_pkt = writeQueueRoot;
  tmp_pkt = writeQueueRoot;
  if ( writeQueueRoot == NULL)
  if ( writeQueueRoot == NULL)
    return;
    return;
 
 
  while (writeQueueRoot->pk_next !=NULL) {
  while (writeQueueRoot->pk_next !=NULL) {
    tmp_pkt = writeQueueRoot;
    tmp_pkt = writeQueueRoot;
    writeQueueRoot = tmp_pkt->pk_next;
    writeQueueRoot = tmp_pkt->pk_next;
    DevSW_FreePacket(tmp_pkt);
    DevSW_FreePacket(tmp_pkt);
  }
  }
  return;
  return;
}
}
 
 
/**********************************************************************/
/**********************************************************************/
 
 
/*
/*
 *  Function: DummyCallback
 *  Function: DummyCallback
 *   Purpose: Default callback routine to handle unexpected input
 *   Purpose: Default callback routine to handle unexpected input
 *              on a channel
 *              on a channel
 *
 *
 *    Params:
 *    Params:
 *       Input: packet  The received packet
 *       Input: packet  The received packet
 *
 *
 *              state   Contains nothing of significance
 *              state   Contains nothing of significance
 *
 *
 *   Returns: Nothing
 *   Returns: Nothing
 */
 */
static void DummyCallback(Packet *packet, void *state)
static void DummyCallback(Packet *packet, void *state)
{
{
    ChannelID chan;
    ChannelID chan;
    const char fmt[] = "Unexpected read on channel %u, length %d\n";
    const char fmt[] = "Unexpected read on channel %u, length %d\n";
    char fmtbuf[sizeof(fmt) + 24];
    char fmtbuf[sizeof(fmt) + 24];
 
 
    UNUSED(state);
    UNUSED(state);
 
 
    chan = *(packet->pk_buffer);
    chan = *(packet->pk_buffer);
    sprintf(fmtbuf, fmt, chan, packet->pk_length);
    sprintf(fmtbuf, fmt, chan, packet->pk_length);
    printf(fmtbuf);
    printf(fmtbuf);
 
 
    /*
    /*
     * junk this packet
     * junk this packet
     */
     */
    DevSW_FreePacket(packet);
    DevSW_FreePacket(packet);
}
}
 
 
/*
/*
 *  Function: BlockingCallback
 *  Function: BlockingCallback
 *   Purpose: Callback routine used to implement a blocking read call
 *   Purpose: Callback routine used to implement a blocking read call
 *
 *
 *    Params:
 *    Params:
 *       Input: packet  The received packet.
 *       Input: packet  The received packet.
 *
 *
 *      Output: state   Address of higher level's pointer to the received
 *      Output: state   Address of higher level's pointer to the received
 *                      packet.
 *                      packet.
 *
 *
 *   Returns: Nothing
 *   Returns: Nothing
 */
 */
static void BlockingCallback(Packet *packet, void *state)
static void BlockingCallback(Packet *packet, void *state)
{
{
    /*
    /*
     * Pass the packet back to the caller which requested a packet
     * Pass the packet back to the caller which requested a packet
     * from this channel.  This also flags the completion of the I/O
     * from this channel.  This also flags the completion of the I/O
     * request to the blocking read call.
     * request to the blocking read call.
     */
     */
    *((Packet **)state) = packet;
    *((Packet **)state) = packet;
}
}
 
 
/*
/*
 *  Function: FireCallback
 *  Function: FireCallback
 *   Purpose: Pass received packet along to the callback routine for
 *   Purpose: Pass received packet along to the callback routine for
 *              the appropriate channel
 *              the appropriate channel
 *
 *
 *    Params:
 *    Params:
 *       Input: packet  The received packet.
 *       Input: packet  The received packet.
 *
 *
 *   Returns: Nothing
 *   Returns: Nothing
 *
 *
 * Post-conditions: The Target-to-Host sequence number for the channel
 * Post-conditions: The Target-to-Host sequence number for the channel
 *                      will have been incremented.
 *                      will have been incremented.
 */
 */
static void FireCallback(Packet *packet)
static void FireCallback(Packet *packet)
{
{
    ChannelID chan;
    ChannelID chan;
    struct Channel *ch;
    struct Channel *ch;
 
 
    /*
    /*
     * is this a sensible channel number?
     * is this a sensible channel number?
     */
     */
    chan = *(packet->pk_buffer);
    chan = *(packet->pk_buffer);
    if (invalidChannelID(chan))
    if (invalidChannelID(chan))
    {
    {
        printf("ERROR: invalid ChannelID received from target\n");
        printf("ERROR: invalid ChannelID received from target\n");
 
 
        /*
        /*
         * free the packet's resources, 'cause no-one else will
         * free the packet's resources, 'cause no-one else will
         */
         */
        DevSW_FreePacket(packet);
        DevSW_FreePacket(packet);
        return;
        return;
    }
    }
 
 
    /*
    /*
     * looks OK - increment sequence number, and pass packet to callback
     * looks OK - increment sequence number, and pass packet to callback
     */
     */
    ch = channels + chan;
    ch = channels + chan;
    (ch->callback)(packet, ch->callback_state);
    (ch->callback)(packet, ch->callback_state);
}
}
 
 
/**********************************************************************/
/**********************************************************************/
 
 
/*
/*
 * These are the externally visible functions.  They are documented
 * These are the externally visible functions.  They are documented
 * in hostchan.h
 * in hostchan.h
 */
 */
void Adp_addToQueue(Packet **head, Packet *newpkt)
void Adp_addToQueue(Packet **head, Packet *newpkt)
{
{
    /*
    /*
     * this is a bit of a hack
     * this is a bit of a hack
     */
     */
    Packet *pk;
    Packet *pk;
 
 
    /*
    /*
     * make sure that the hack we are about to use will work as expected
     * make sure that the hack we are about to use will work as expected
     */
     */
    ASSERT(&(((Packet *)0)->pk_next) == 0, "bad struct Packet layout");
    ASSERT(&(((Packet *)0)->pk_next) == 0, "bad struct Packet layout");
 
 
#if defined(DEBUG) && 0
#if defined(DEBUG) && 0
    printf("Adp_addToQueue(%p, %p)\n", head, newpkt);
    printf("Adp_addToQueue(%p, %p)\n", head, newpkt);
#endif
#endif
 
 
    /*
    /*
     * here's the hack - it relies upon the next
     * here's the hack - it relies upon the next
     * pointer being at the start of Packet.
     * pointer being at the start of Packet.
     */
     */
    pk = (Packet *)(head);
    pk = (Packet *)(head);
 
 
    /*
    /*
     * skip to the end of the queue
     * skip to the end of the queue
     */
     */
    while (pk->pk_next != NULL)
    while (pk->pk_next != NULL)
        pk = pk->pk_next;
        pk = pk->pk_next;
 
 
    /*
    /*
     * now add the new element
     * now add the new element
     */
     */
    newpkt->pk_next = NULL;
    newpkt->pk_next = NULL;
    pk->pk_next = newpkt;
    pk->pk_next = newpkt;
}
}
 
 
Packet *Adp_removeFromQueue(Packet **head)
Packet *Adp_removeFromQueue(Packet **head)
{
{
    struct Packet *pk;
    struct Packet *pk;
 
 
    pk = *head;
    pk = *head;
 
 
    if (pk != NULL)
    if (pk != NULL)
        *head = pk->pk_next;
        *head = pk->pk_next;
 
 
    return pk;
    return pk;
}
}
 
 
void Adp_SetLogEnable(int logEnableFlag)
void Adp_SetLogEnable(int logEnableFlag)
{
{
  DevSW_SetLogEnable(logEnableFlag);
  DevSW_SetLogEnable(logEnableFlag);
}
}
 
 
void Adp_SetLogfile(const char *filename)
void Adp_SetLogfile(const char *filename)
{
{
  DevSW_SetLogfile(filename);
  DevSW_SetLogfile(filename);
}
}
 
 
AdpErrs Adp_OpenDevice(const char *name, const char *arg,
AdpErrs Adp_OpenDevice(const char *name, const char *arg,
                       unsigned int heartbeat_on)
                       unsigned int heartbeat_on)
{
{
    int i;
    int i;
    AdpErrs retc;
    AdpErrs retc;
    ChannelID chan;
    ChannelID chan;
 
 
#ifdef DEBUG
#ifdef DEBUG
    printf("Adp_OpenDevice(%s, %s)\n", name, arg ? arg : "<NULL>");
    printf("Adp_OpenDevice(%s, %s)\n", name, arg ? arg : "<NULL>");
#endif
#endif
 
 
    heartbeat_configured = heartbeat_on;
    heartbeat_configured = heartbeat_on;
    if (deviceToUse != NULL)
    if (deviceToUse != NULL)
        return adp_device_already_open;
        return adp_device_already_open;
 
 
    for (i = 0; (deviceToUse = devices[i]) != NULL; ++i)
    for (i = 0; (deviceToUse = devices[i]) != NULL; ++i)
        if (DevSW_Match(deviceToUse, name, arg) == adp_ok)
        if (DevSW_Match(deviceToUse, name, arg) == adp_ok)
            break;
            break;
 
 
    if (deviceToUse == NULL)
    if (deviceToUse == NULL)
        return adp_device_not_found;
        return adp_device_not_found;
 
 
    /*
    /*
     * we seem to have found a suitable device driver, so try to open it
     * we seem to have found a suitable device driver, so try to open it
     */
     */
    if ((retc = DevSW_Open(deviceToUse, name, arg, DC_DBUG)) != adp_ok)
    if ((retc = DevSW_Open(deviceToUse, name, arg, DC_DBUG)) != adp_ok)
    {
    {
        /* we don't have a device to use */
        /* we don't have a device to use */
        deviceToUse = NULL;
        deviceToUse = NULL;
        return retc;
        return retc;
    }
    }
 
 
    /*
    /*
     * there is no explicit open on channels any more, so
     * there is no explicit open on channels any more, so
     * initialise state for all channels.
     * initialise state for all channels.
     */
     */
    for (chan = 0; chan < CI_NUM_CHANNELS; ++chan)
    for (chan = 0; chan < CI_NUM_CHANNELS; ++chan)
    {
    {
        struct Channel *ch = channels + chan;
        struct Channel *ch = channels + chan;
 
 
        ch->callback = DummyCallback;
        ch->callback = DummyCallback;
        ch->callback_state = NULL;
        ch->callback_state = NULL;
        OppoSeq = 0;
        OppoSeq = 0;
        HomeSeq = 0;
        HomeSeq = 0;
    }
    }
 
 
    return adp_ok;
    return adp_ok;
}
}
 
 
AdpErrs Adp_CloseDevice(void)
AdpErrs Adp_CloseDevice(void)
{
{
    AdpErrs retc;
    AdpErrs retc;
 
 
#ifdef DEBUG
#ifdef DEBUG
    printf("Adp_CloseDevice\n");
    printf("Adp_CloseDevice\n");
#endif
#endif
 
 
    if (deviceToUse == NULL)
    if (deviceToUse == NULL)
        return adp_device_not_open;
        return adp_device_not_open;
 
 
    heartbeat_enabled = FALSE;
    heartbeat_enabled = FALSE;
 
 
    retc = DevSW_Close(deviceToUse, DC_DBUG);
    retc = DevSW_Close(deviceToUse, DC_DBUG);
 
 
    /*
    /*
     * we have to clear deviceToUse, even when the lower layers
     * we have to clear deviceToUse, even when the lower layers
     * faulted the close, otherwise the condition will never clear
     * faulted the close, otherwise the condition will never clear
     */
     */
    if (retc != adp_ok)
    if (retc != adp_ok)
        WARN("DevSW_Close faulted the call");
        WARN("DevSW_Close faulted the call");
 
 
    deviceToUse = NULL;
    deviceToUse = NULL;
    return retc;
    return retc;
}
}
 
 
AdpErrs Adp_Ioctl(int opcode, void *args)
AdpErrs Adp_Ioctl(int opcode, void *args)
{
{
#ifdef DEBUG
#ifdef DEBUG
    printf("Adp_Ioctl\n");
    printf("Adp_Ioctl\n");
#endif
#endif
 
 
    if (deviceToUse == NULL)
    if (deviceToUse == NULL)
        return adp_device_not_open;
        return adp_device_not_open;
 
 
    return DevSW_Ioctl(deviceToUse, opcode, args);
    return DevSW_Ioctl(deviceToUse, opcode, args);
}
}
 
 
AdpErrs Adp_ChannelRegisterRead(const ChannelID chan,
AdpErrs Adp_ChannelRegisterRead(const ChannelID chan,
                                const ChannelCallback cbfunc,
                                const ChannelCallback cbfunc,
                                void *cbstate)
                                void *cbstate)
{
{
#ifdef DEBUG
#ifdef DEBUG
    printf("Adp_ChannelRegisterRead(%d, %p, %x)\n", chan, cbfunc, cbstate);
    printf("Adp_ChannelRegisterRead(%d, %p, %x)\n", chan, cbfunc, cbstate);
#endif
#endif
 
 
    if (deviceToUse == NULL)
    if (deviceToUse == NULL)
        return adp_device_not_open;
        return adp_device_not_open;
 
 
    if (invalidChannelID(chan))
    if (invalidChannelID(chan))
        return adp_bad_channel_id;
        return adp_bad_channel_id;
 
 
    if (cbfunc == NULL)
    if (cbfunc == NULL)
    {
    {
        channels[chan].callback = DummyCallback;
        channels[chan].callback = DummyCallback;
        channels[chan].callback_state = NULL;
        channels[chan].callback_state = NULL;
    }
    }
    else
    else
    {
    {
        channels[chan].callback = cbfunc;
        channels[chan].callback = cbfunc;
        channels[chan].callback_state = cbstate;
        channels[chan].callback_state = cbstate;
    }
    }
 
 
    return adp_ok;
    return adp_ok;
}
}
 
 
AdpErrs Adp_ChannelRead(const ChannelID chan, Packet **packet)
AdpErrs Adp_ChannelRead(const ChannelID chan, Packet **packet)
{
{
    struct Channel *ch;
    struct Channel *ch;
 
 
#ifdef DEBUG
#ifdef DEBUG
    printf("Adp_ChannelRead(%d, %x)\n", chan, *packet);
    printf("Adp_ChannelRead(%d, %x)\n", chan, *packet);
#endif
#endif
 
 
    if (deviceToUse == NULL)
    if (deviceToUse == NULL)
        return adp_device_not_open;
        return adp_device_not_open;
 
 
    if (invalidChannelID(chan))
    if (invalidChannelID(chan))
        return adp_bad_channel_id;
        return adp_bad_channel_id;
 
 
    /*
    /*
     * if a callback has already been registered for this
     * if a callback has already been registered for this
     * channel, then we do not allow this blocking read.
     * channel, then we do not allow this blocking read.
     */
     */
    ch = channels + chan;
    ch = channels + chan;
    if (ch->callback != DummyCallback)
    if (ch->callback != DummyCallback)
        return adp_callback_already_registered;
        return adp_callback_already_registered;
 
 
    /*
    /*
     * OK, use our own callback to wait for a packet to arrive
     * OK, use our own callback to wait for a packet to arrive
     * on this channel
     * on this channel
     */
     */
    ch->callback = BlockingCallback;
    ch->callback = BlockingCallback;
    ch->callback_state = packet;
    ch->callback_state = packet;
    *packet = NULL;
    *packet = NULL;
 
 
    /*
    /*
     * keep polling until a packet appears for this channel
     * keep polling until a packet appears for this channel
     */
     */
    while (((volatile Packet *)(*packet)) == NULL)
    while (((volatile Packet *)(*packet)) == NULL)
        /*
        /*
         * this call will block until a packet is read on any channel
         * this call will block until a packet is read on any channel
         */
         */
        Adp_AsynchronousProcessing(async_block_on_read);
        Adp_AsynchronousProcessing(async_block_on_read);
 
 
    /*
    /*
     * OK, the packet has arrived: clear the callback
     * OK, the packet has arrived: clear the callback
     */
     */
    ch->callback = DummyCallback;
    ch->callback = DummyCallback;
    ch->callback_state = NULL;
    ch->callback_state = NULL;
 
 
    return adp_ok;
    return adp_ok;
}
}
 
 
static AdpErrs ChannelWrite(
static AdpErrs ChannelWrite(
    const ChannelID chan, Packet *packet, AsyncMode mode)
    const ChannelID chan, Packet *packet, AsyncMode mode)
{
{
    struct Channel *ch;
    struct Channel *ch;
    unsigned char *cptr;
    unsigned char *cptr;
 
 
#ifdef DEBUG
#ifdef DEBUG
    printf( "Adp_ChannelWrite(%d, %x)\n", chan, packet );
    printf( "Adp_ChannelWrite(%d, %x)\n", chan, packet );
#endif
#endif
 
 
    if (deviceToUse == NULL)
    if (deviceToUse == NULL)
        return adp_device_not_open;
        return adp_device_not_open;
 
 
    if (invalidChannelID(chan))
    if (invalidChannelID(chan))
        return adp_bad_channel_id;
        return adp_bad_channel_id;
 
 
    /*
    /*
     * fill in the channels header at the start of this buffer
     * fill in the channels header at the start of this buffer
     */
     */
    ch = channels + chan;
    ch = channels + chan;
    cptr = packet->pk_buffer;
    cptr = packet->pk_buffer;
    *cptr++ = chan;
    *cptr++ = chan;
    *cptr = 0;
    *cptr = 0;
    packet->pk_length += CHAN_HEADER_SIZE;
    packet->pk_length += CHAN_HEADER_SIZE;
 
 
    /*
    /*
     * OK, add this packet to the write queue, and try to flush it out
     * OK, add this packet to the write queue, and try to flush it out
     */
     */
 
 
    Adp_addToQueue(&writeQueueSend, packet);
    Adp_addToQueue(&writeQueueSend, packet);
    Adp_AsynchronousProcessing(mode);
    Adp_AsynchronousProcessing(mode);
 
 
    return adp_ok;
    return adp_ok;
}
}
 
 
AdpErrs Adp_ChannelWrite(const ChannelID chan, Packet *packet) {
AdpErrs Adp_ChannelWrite(const ChannelID chan, Packet *packet) {
  return ChannelWrite(chan, packet, async_block_on_write);
  return ChannelWrite(chan, packet, async_block_on_write);
}
}
 
 
AdpErrs Adp_ChannelWriteAsync(const ChannelID chan, Packet *packet) {
AdpErrs Adp_ChannelWriteAsync(const ChannelID chan, Packet *packet) {
  return ChannelWrite(chan, packet, async_block_on_nothing);
  return ChannelWrite(chan, packet, async_block_on_nothing);
}
}
 
 
static AdpErrs send_resend_msg(DeviceID devid) {
static AdpErrs send_resend_msg(DeviceID devid) {
 
 
  /*
  /*
   * Send a resend message, usually in response to a bad packet or
   * Send a resend message, usually in response to a bad packet or
   * a resend request */
   * a resend request */
  Packet * packet;
  Packet * packet;
  packet = DevSW_AllocatePacket(CF_DATA_BYTE_POS);
  packet = DevSW_AllocatePacket(CF_DATA_BYTE_POS);
  packet->pk_buffer[CF_CHANNEL_BYTE_POS] = CI_PRIVATE;
  packet->pk_buffer[CF_CHANNEL_BYTE_POS] = CI_PRIVATE;
  packet->pk_buffer[CF_HOME_SEQ_BYTE_POS] = HomeSeq;
  packet->pk_buffer[CF_HOME_SEQ_BYTE_POS] = HomeSeq;
  packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS] = OppoSeq;
  packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS] = OppoSeq;
  packet->pk_buffer[CF_FLAGS_BYTE_POS] = CF_RELIABLE | CF_RESEND;
  packet->pk_buffer[CF_FLAGS_BYTE_POS] = CF_RELIABLE | CF_RESEND;
  packet->pk_length = CF_DATA_BYTE_POS;
  packet->pk_length = CF_DATA_BYTE_POS;
  return DevSW_Write(deviceToUse, packet, devid);
  return DevSW_Write(deviceToUse, packet, devid);
}
}
 
 
static AdpErrs check_seq(unsigned char msg_home, unsigned char msg_oppo) {
static AdpErrs check_seq(unsigned char msg_home, unsigned char msg_oppo) {
  Packet *tmp_pkt;
  Packet *tmp_pkt;
 
 
  UNUSED(msg_oppo);
  UNUSED(msg_oppo);
  /*
  /*
   * check if we have got an ack for anything and if so remove it from the
   * check if we have got an ack for anything and if so remove it from the
   * queue
   * queue
   */
   */
  if (msg_home == (unsigned char)(OppoSeq+1)) {
  if (msg_home == (unsigned char)(OppoSeq+1)) {
    /*
    /*
     * arrived in sequence can increment our opposing seq number and remove
     * arrived in sequence can increment our opposing seq number and remove
     * the relevant packet from our queue
     * the relevant packet from our queue
     * check that the packet we're going to remove really is the right one
     * check that the packet we're going to remove really is the right one
     */
     */
    tmp_pkt = writeQueueRoot;
    tmp_pkt = writeQueueRoot;
    while ((tmp_pkt->pk_next != NULL) &&
    while ((tmp_pkt->pk_next != NULL) &&
           (tmp_pkt->pk_next->pk_buffer[CF_HOME_SEQ_BYTE_POS]
           (tmp_pkt->pk_next->pk_buffer[CF_HOME_SEQ_BYTE_POS]
            != OppoSeq)){
            != OppoSeq)){
      tmp_pkt = tmp_pkt->pk_next;
      tmp_pkt = tmp_pkt->pk_next;
    }
    }
    OppoSeq++;
    OppoSeq++;
    if (tmp_pkt->pk_next == NULL) {
    if (tmp_pkt->pk_next == NULL) {
#ifdef DEBUG
#ifdef DEBUG
      printf("trying to remove a non existant packet\n");
      printf("trying to remove a non existant packet\n");
#endif
#endif
      return adp_bad_packet;
      return adp_bad_packet;
    }
    }
    else {
    else {
      Packet *tmp = tmp_pkt->pk_next;
      Packet *tmp = tmp_pkt->pk_next;
#ifdef RET_DEBUG
#ifdef RET_DEBUG
      printf("removing a packet from the root queue\n");
      printf("removing a packet from the root queue\n");
#endif
#endif
      tmp_pkt->pk_next = tmp_pkt->pk_next->pk_next;
      tmp_pkt->pk_next = tmp_pkt->pk_next->pk_next;
      /* remove the appropriate packet */
      /* remove the appropriate packet */
      DevSW_FreePacket(tmp);
      DevSW_FreePacket(tmp);
    return adp_ok;
    return adp_ok;
    }
    }
  }
  }
  else if (msg_home < (unsigned char) (OppoSeq+1)){
  else if (msg_home < (unsigned char) (OppoSeq+1)){
    /* already received this message */
    /* already received this message */
#ifdef RET_DEBUG
#ifdef RET_DEBUG
    printf("sequence numbers low\n");
    printf("sequence numbers low\n");
#endif   
#endif   
    return adp_seq_low;
    return adp_seq_low;
  }
  }
  else {  /* we've missed something */
  else {  /* we've missed something */
#ifdef RET_DEBUG
#ifdef RET_DEBUG
    printf("sequence numbers high\n");
    printf("sequence numbers high\n");
#endif   
#endif   
    return adp_seq_high;
    return adp_seq_high;
  }
  }
}
}
 
 
static unsigned long tv_diff(const struct timeval *time_now,
static unsigned long tv_diff(const struct timeval *time_now,
                             const struct timeval *time_was)
                             const struct timeval *time_was)
{
{
    return (  ((time_now->tv_sec * 1000000) + time_now->tv_usec)
    return (  ((time_now->tv_sec * 1000000) + time_now->tv_usec)
            - ((time_was->tv_sec * 1000000) + time_was->tv_usec) );
            - ((time_was->tv_sec * 1000000) + time_was->tv_usec) );
}
}
 
 
#if !defined(__unix) && !defined(__CYGWIN32__)
#if !defined(__unix) && !defined(__CYGWIN32__)
static void gettimeofday( struct timeval *time_now, void *dummy )
static void gettimeofday( struct timeval *time_now, void *dummy )
{
{
    time_t t = clock();
    time_t t = clock();
    UNUSED(dummy);
    UNUSED(dummy);
    time_now->tv_sec = t/CLOCKS_PER_SEC;
    time_now->tv_sec = t/CLOCKS_PER_SEC;
    time_now->tv_usec = (t%CLOCKS_PER_SEC)*(1000000/CLOCKS_PER_SEC);
    time_now->tv_usec = (t%CLOCKS_PER_SEC)*(1000000/CLOCKS_PER_SEC);
}
}
#endif
#endif
 
 
static AdpErrs pacemaker(void)
static AdpErrs pacemaker(void)
{
{
  Packet *packet;
  Packet *packet;
 
 
  packet = DevSW_AllocatePacket(CF_DATA_BYTE_POS);
  packet = DevSW_AllocatePacket(CF_DATA_BYTE_POS);
  if (packet == NULL) {
  if (packet == NULL) {
    printf("ERROR: could not allocate a packet in pacemaker()\n");
    printf("ERROR: could not allocate a packet in pacemaker()\n");
    return adp_malloc_failure;
    return adp_malloc_failure;
  }
  }
  packet->pk_buffer[CF_CHANNEL_BYTE_POS] = CI_PRIVATE;
  packet->pk_buffer[CF_CHANNEL_BYTE_POS] = CI_PRIVATE;
  packet->pk_buffer[CF_HOME_SEQ_BYTE_POS] = HomeSeq;
  packet->pk_buffer[CF_HOME_SEQ_BYTE_POS] = HomeSeq;
  packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS] = OppoSeq;
  packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS] = OppoSeq;
  packet->pk_buffer[CF_FLAGS_BYTE_POS] = CF_RELIABLE | CF_HEARTBEAT;
  packet->pk_buffer[CF_FLAGS_BYTE_POS] = CF_RELIABLE | CF_HEARTBEAT;
  packet->pk_length = CF_DATA_BYTE_POS;
  packet->pk_length = CF_DATA_BYTE_POS;
  return DevSW_Write(deviceToUse, packet, DC_DBUG);
  return DevSW_Write(deviceToUse, packet, DC_DBUG);
}
}
 
 
#ifdef FAKE_BAD_LINE_RX
#ifdef FAKE_BAD_LINE_RX
static AdpErrs fake_bad_line_rx( const Packet *const packet, AdpErrs adp_err )
static AdpErrs fake_bad_line_rx( const Packet *const packet, AdpErrs adp_err )
{
{
    static unsigned int bl_num = 0;
    static unsigned int bl_num = 0;
 
 
    if (     (packet != NULL)
    if (     (packet != NULL)
          && (bl_num++ >= 20 )
          && (bl_num++ >= 20 )
          && ((bl_num % FAKE_BAD_LINE_RX) == 0))
          && ((bl_num % FAKE_BAD_LINE_RX) == 0))
    {
    {
        printf("DEBUG: faking a bad packet\n");
        printf("DEBUG: faking a bad packet\n");
        return adp_bad_packet;
        return adp_bad_packet;
    }
    }
    return adp_err;
    return adp_err;
}
}
#endif /* def FAKE_BAD_LINE_RX */
#endif /* def FAKE_BAD_LINE_RX */
 
 
#ifdef FAKE_BAD_LINE_TX
#ifdef FAKE_BAD_LINE_TX
static unsigned char tmp_ch;
static unsigned char tmp_ch;
 
 
static void fake_bad_line_tx( void )
static void fake_bad_line_tx( void )
{
{
    static unsigned int bl_num = 0;
    static unsigned int bl_num = 0;
 
 
    /* give the thing a chance to boot then try corrupting stuff */
    /* give the thing a chance to boot then try corrupting stuff */
    if ( (bl_num++ >= 20) && ((bl_num % FAKE_BAD_LINE_TX) == 0))
    if ( (bl_num++ >= 20) && ((bl_num % FAKE_BAD_LINE_TX) == 0))
    {
    {
        printf("DEBUG: faking a bad packet for tx\n");
        printf("DEBUG: faking a bad packet for tx\n");
        tmp_ch = writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS];
        tmp_ch = writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS];
        writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS] = 77;
        writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS] = 77;
    }
    }
}
}
 
 
static void unfake_bad_line_tx( void )
static void unfake_bad_line_tx( void )
{
{
    static unsigned int bl_num = 0;
    static unsigned int bl_num = 0;
 
 
    /*
    /*
     * must reset the packet so that its not corrupted when we
     * must reset the packet so that its not corrupted when we
     *  resend it
     *  resend it
     */
     */
    if ( (bl_num >= 20) && ((bl_num % FAKE_BAD_LINE_TX) != 0))
    if ( (bl_num >= 20) && ((bl_num % FAKE_BAD_LINE_TX) != 0))
    {
    {
        writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS] = tmp_ch;
        writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS] = tmp_ch;
    }
    }
}
}
#endif /* def FAKE_BAD_LINE_TX */
#endif /* def FAKE_BAD_LINE_TX */
 
 
/*
/*
 * NOTE: we are assuming that a resolution of microseconds will
 * NOTE: we are assuming that a resolution of microseconds will
 * be good enough for the purporses of the heartbeat.  If this proves
 * be good enough for the purporses of the heartbeat.  If this proves
 * not to be the case then we may need a rethink, possibly using
 * not to be the case then we may need a rethink, possibly using
 * [get,set]itimer
 * [get,set]itimer
 */
 */
static struct timeval time_now;
static struct timeval time_now;
static struct timeval time_lastalive;
static struct timeval time_lastalive;
 
 
static void async_process_dbug_read( const AsyncMode mode,
static void async_process_dbug_read( const AsyncMode mode,
                                     bool *const finished  )
                                     bool *const finished  )
{
{
    Packet *packet;
    Packet *packet;
    unsigned int msg_home, msg_oppo;
    unsigned int msg_home, msg_oppo;
    AdpErrs adp_err;
    AdpErrs adp_err;
 
 
    adp_err = DevSW_Read(deviceToUse, DC_DBUG, &packet,
    adp_err = DevSW_Read(deviceToUse, DC_DBUG, &packet,
                         mode == async_block_on_read    );
                         mode == async_block_on_read    );
 
 
#ifdef FAKE_BAD_LINE_RX
#ifdef FAKE_BAD_LINE_RX
    adp_err = fake_bad_line_rx( packet, adp_err );
    adp_err = fake_bad_line_rx( packet, adp_err );
#endif
#endif
 
 
    if (adp_err == adp_bad_packet) {
    if (adp_err == adp_bad_packet) {
        /* We got a bad packet, ask for a resend, send a resend message */
        /* We got a bad packet, ask for a resend, send a resend message */
#ifdef DEBUG
#ifdef DEBUG
        printf("received a bad packet\n");
        printf("received a bad packet\n");
#endif
#endif
        send_resend_msg(DC_DBUG);
        send_resend_msg(DC_DBUG);
    }
    }
    else if (packet != NULL)
    else if (packet != NULL)
    {
    {
        /* update the heartbeat clock */
        /* update the heartbeat clock */
        gettimeofday(&time_lastalive, NULL);
        gettimeofday(&time_lastalive, NULL);
 
 
            /*
            /*
             * we got a live one here - were we waiting for it?
             * we got a live one here - were we waiting for it?
             */
             */
        if (mode == async_block_on_read)
        if (mode == async_block_on_read)
           /* not any more */
           /* not any more */
           *finished = TRUE;
           *finished = TRUE;
#ifdef RETRANS
#ifdef RETRANS
 
 
        if (packet->pk_length < CF_DATA_BYTE_POS) {
        if (packet->pk_length < CF_DATA_BYTE_POS) {
            /* we've got a packet with no header information! */
            /* we've got a packet with no header information! */
            printf("ERROR: packet with no transport header\n");
            printf("ERROR: packet with no transport header\n");
            send_resend_msg(DC_DBUG);
            send_resend_msg(DC_DBUG);
        }
        }
        else {
        else {
#ifdef RET_DEBUG
#ifdef RET_DEBUG
            unsigned int c;
            unsigned int c;
#endif
#endif
            /*
            /*
             * TODO: Check to see if its acknowledgeing anything, remove
             * TODO: Check to see if its acknowledgeing anything, remove
             * those packets it is from the queue.  If its a retrans add the
             * those packets it is from the queue.  If its a retrans add the
             * packets to the queue
             * packets to the queue
             */
             */
            msg_home = packet->pk_buffer[CF_HOME_SEQ_BYTE_POS];
            msg_home = packet->pk_buffer[CF_HOME_SEQ_BYTE_POS];
            msg_oppo = packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS];
            msg_oppo = packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS];
#ifdef RET_DEBUG
#ifdef RET_DEBUG
            printf("msg seq numbers are hseq 0x%x oseq 0x%x\n",
            printf("msg seq numbers are hseq 0x%x oseq 0x%x\n",
                   msg_home, msg_oppo);
                   msg_home, msg_oppo);
            for (c=0;c<packet->pk_length;c++)
            for (c=0;c<packet->pk_length;c++)
               printf("%02.2x", packet->pk_buffer[c]);
               printf("%02.2x", packet->pk_buffer[c]);
            printf("\n");
            printf("\n");
#endif
#endif
            /* now was it a resend request? */
            /* now was it a resend request? */
            if ((packet->pk_buffer[CF_FLAGS_BYTE_POS])
            if ((packet->pk_buffer[CF_FLAGS_BYTE_POS])
                & CF_RESEND) {
                & CF_RESEND) {
                /* we've been asked for a resend so we had better resend */
                /* we've been asked for a resend so we had better resend */
                /*
                /*
                 * I don't think we can use a resend as acknowledgement for
                 * I don't think we can use a resend as acknowledgement for
                 * anything so lets not do this for the moment
                 * anything so lets not do this for the moment
                 * check_seq(msg_home, msg_oppo);
                 * check_seq(msg_home, msg_oppo);
                 */
                 */
#ifdef RET_DEBUG
#ifdef RET_DEBUG
                printf("received a resend request\n");
                printf("received a resend request\n");
#endif
#endif
                if (HomeSeq != msg_oppo) {
                if (HomeSeq != msg_oppo) {
                    int found = FALSE;
                    int found = FALSE;
                    /* need to resend from msg_oppo +1 upwards */
                    /* need to resend from msg_oppo +1 upwards */
                    DevSW_FreePacket(packet);
                    DevSW_FreePacket(packet);
                    resending = TRUE;
                    resending = TRUE;
                    /* find the correct packet to resend from */
                    /* find the correct packet to resend from */
                    packet = writeQueueRoot;
                    packet = writeQueueRoot;
                    while (((packet->pk_next) != NULL) && !found) {
                    while (((packet->pk_next) != NULL) && !found) {
                        if ((packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS])
                        if ((packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS])
                            != msg_oppo+1) {
                            != msg_oppo+1) {
                            resend_pkt = packet;
                            resend_pkt = packet;
                            found = TRUE;
                            found = TRUE;
                        }
                        }
                        packet = packet->pk_next;
                        packet = packet->pk_next;
                    }
                    }
                    if (!found) {
                    if (!found) {
                        panic("trying to resend non-existent packets\n");
                        panic("trying to resend non-existent packets\n");
                    }
                    }
                }
                }
                else if (OppoSeq != msg_home) {
                else if (OppoSeq != msg_home) {
                    /*
                    /*
                     * send a resend request telling the target where we think
                     * send a resend request telling the target where we think
                     * the world is at
                     * the world is at
                     */
                     */
                    DevSW_FreePacket(packet);
                    DevSW_FreePacket(packet);
                    send_resend_msg(DC_DBUG);
                    send_resend_msg(DC_DBUG);
                }
                }
            }
            }
            else {
            else {
                /* not a resend request, lets check the sequence numbers */
                /* not a resend request, lets check the sequence numbers */
 
 
                if ((packet->pk_buffer[CF_CHANNEL_BYTE_POS] != CI_HBOOT) &&
                if ((packet->pk_buffer[CF_CHANNEL_BYTE_POS] != CI_HBOOT) &&
                    (packet->pk_buffer[CF_CHANNEL_BYTE_POS] != CI_TBOOT)) {
                    (packet->pk_buffer[CF_CHANNEL_BYTE_POS] != CI_TBOOT)) {
                    adp_err = check_seq(msg_home, msg_oppo);
                    adp_err = check_seq(msg_home, msg_oppo);
                    if (adp_err == adp_seq_low) {
                    if (adp_err == adp_seq_low) {
                        /* we have already received this packet so discard */
                        /* we have already received this packet so discard */
                        DevSW_FreePacket(packet);
                        DevSW_FreePacket(packet);
                    }
                    }
                    else if (adp_err == adp_seq_high) {
                    else if (adp_err == adp_seq_high) {
                        /*
                        /*
                         * we must have missed a packet somewhere, discard this
                         * we must have missed a packet somewhere, discard this
                         * packet and tell the target where we are
                         * packet and tell the target where we are
                         */
                         */
                        DevSW_FreePacket(packet);
                        DevSW_FreePacket(packet);
                        send_resend_msg(DC_DBUG);
                        send_resend_msg(DC_DBUG);
                    }
                    }
                    else
                    else
                       /*
                       /*
                        * now pass the packet to whoever is waiting for it
                        * now pass the packet to whoever is waiting for it
                        */
                        */
                       FireCallback(packet);
                       FireCallback(packet);
                }
                }
                else
                else
                   FireCallback(packet);
                   FireCallback(packet);
            }
            }
        }
        }
#else
#else
        /*
        /*
             * now pass the packet to whoever is waiting for it
             * now pass the packet to whoever is waiting for it
             */
             */
        FireCallback(packet);
        FireCallback(packet);
#endif
#endif
    }
    }
}
}
 
 
static void async_process_appl_read(void)
static void async_process_appl_read(void)
{
{
    Packet *packet;
    Packet *packet;
    AdpErrs adp_err;
    AdpErrs adp_err;
 
 
    /* see if there is anything for the DC_APPL channel */
    /* see if there is anything for the DC_APPL channel */
    adp_err = DevSW_Read(deviceToUse, DC_APPL, &packet, FALSE);
    adp_err = DevSW_Read(deviceToUse, DC_APPL, &packet, FALSE);
 
 
    if (adp_err == adp_ok && packet != NULL)
    if (adp_err == adp_ok && packet != NULL)
    {
    {
        /* got an application packet on a shared device */
        /* got an application packet on a shared device */
 
 
#ifdef DEBUG
#ifdef DEBUG
        printf("GOT DC_APPL PACKET: len %d\nData: ", packet->pk_length);
        printf("GOT DC_APPL PACKET: len %d\nData: ", packet->pk_length);
        {
        {
            unsigned int c;
            unsigned int c;
            for ( c = 0; c < packet->pk_length; ++c )
            for ( c = 0; c < packet->pk_length; ++c )
               printf( "%02X ", packet->pk_buffer[c] );
               printf( "%02X ", packet->pk_buffer[c] );
        }
        }
        printf("\n");
        printf("\n");
#endif
#endif
 
 
        if (dc_appl_handler != NULL)
        if (dc_appl_handler != NULL)
        {
        {
            dc_appl_handler( deviceToUse, packet );
            dc_appl_handler( deviceToUse, packet );
        }
        }
        else
        else
        {
        {
            /* for now, just free it!! */
            /* for now, just free it!! */
#ifdef DEBUG
#ifdef DEBUG
            printf("no handler - dropping DC_APPL packet\n");
            printf("no handler - dropping DC_APPL packet\n");
#endif
#endif
            DevSW_FreePacket( packet );
            DevSW_FreePacket( packet );
        }
        }
    }
    }
}
}
 
 
static void async_process_write( const AsyncMode mode,
static void async_process_write( const AsyncMode mode,
                                 bool *const finished  )
                                 bool *const finished  )
{
{
    Packet *packet;
    Packet *packet;
 
 
#ifdef DEBUG
#ifdef DEBUG
    static unsigned int num_written = 0;
    static unsigned int num_written = 0;
#endif
#endif
 
 
    /*
    /*
     * NOTE: here we rely in the fact that any packet in the writeQueueSend
     * NOTE: here we rely in the fact that any packet in the writeQueueSend
     * section of the queue will need its sequence number setting up while
     * section of the queue will need its sequence number setting up while
     * and packet in the writeQueueRoot section will have its sequence
     * and packet in the writeQueueRoot section will have its sequence
     * numbers set up from when it was first sent so we can easily look
     * numbers set up from when it was first sent so we can easily look
     * up the packet numbers when(if) we want to resend the packet.
     * up the packet numbers when(if) we want to resend the packet.
     */
     */
 
 
#ifdef DEBUG
#ifdef DEBUG
    if (writeQueueSend!=NULL)
    if (writeQueueSend!=NULL)
       printf("written 0x%x\n",num_written += writeQueueSend->pk_length);
       printf("written 0x%x\n",num_written += writeQueueSend->pk_length);
#endif
#endif
    /*
    /*
     * give the switcher a chance to complete any partial writes
     * give the switcher a chance to complete any partial writes
     */
     */
    if (DevSW_FlushPendingWrite(deviceToUse) == adp_write_busy)
    if (DevSW_FlushPendingWrite(deviceToUse) == adp_write_busy)
    {
    {
        /* no point trying a new write */
        /* no point trying a new write */
        return;
        return;
    }
    }
 
 
    /*
    /*
     * now see whether there is anything to write
     * now see whether there is anything to write
     */
     */
    packet = NULL;
    packet = NULL;
    if (resending) {
    if (resending) {
        packet = resend_pkt;
        packet = resend_pkt;
#ifdef RET_DEBUG
#ifdef RET_DEBUG
        printf("resending hseq 0x%x oseq 0x%x\n",
        printf("resending hseq 0x%x oseq 0x%x\n",
               packet->pk_buffer[CF_HOME_SEQ_BYTE_POS],
               packet->pk_buffer[CF_HOME_SEQ_BYTE_POS],
               packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS]);
               packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS]);
#endif
#endif
    }
    }
    else if (writeQueueSend != NULL) {
    else if (writeQueueSend != NULL) {
#ifdef RETRANS
#ifdef RETRANS
        /* set up the sequence number on the packet */
        /* set up the sequence number on the packet */
        packet = writeQueueSend;
        packet = writeQueueSend;
        HomeSeq++;
        HomeSeq++;
        (writeQueueSend->pk_buffer[CF_OPPO_SEQ_BYTE_POS])
        (writeQueueSend->pk_buffer[CF_OPPO_SEQ_BYTE_POS])
            = OppoSeq;
            = OppoSeq;
        (writeQueueSend->pk_buffer[CF_HOME_SEQ_BYTE_POS])
        (writeQueueSend->pk_buffer[CF_HOME_SEQ_BYTE_POS])
            = HomeSeq;
            = HomeSeq;
        (writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS])
        (writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS])
            = CF_RELIABLE;
            = CF_RELIABLE;
# ifdef RET_DEBUG
# ifdef RET_DEBUG
        printf("sending packet with hseq 0x%x oseq 0x%x\n",
        printf("sending packet with hseq 0x%x oseq 0x%x\n",
               writeQueueSend->pk_buffer[CF_HOME_SEQ_BYTE_POS],
               writeQueueSend->pk_buffer[CF_HOME_SEQ_BYTE_POS],
               writeQueueSend->pk_buffer[CF_OPPO_SEQ_BYTE_POS]);
               writeQueueSend->pk_buffer[CF_OPPO_SEQ_BYTE_POS]);
# endif
# endif
#endif /* RETRANS */
#endif /* RETRANS */
    }
    }
 
 
    if (packet != NULL) {
    if (packet != NULL) {
        AdpErrs dev_err;
        AdpErrs dev_err;
 
 
#ifdef FAKE_BAD_LINE_TX
#ifdef FAKE_BAD_LINE_TX
        fake_bad_line_tx();
        fake_bad_line_tx();
#endif
#endif
 
 
        dev_err = DevSW_Write(deviceToUse, packet, DC_DBUG);
        dev_err = DevSW_Write(deviceToUse, packet, DC_DBUG);
        if (dev_err == adp_ok) {
        if (dev_err == adp_ok) {
#ifdef RETRANS
#ifdef RETRANS
            if (resending) {
            if (resending) {
                /* check to see if we've recovered yet */
                /* check to see if we've recovered yet */
                if ((packet->pk_next) == NULL){
                if ((packet->pk_next) == NULL){
# ifdef RET_DEBUG
# ifdef RET_DEBUG
                    printf("we have recovered\n");
                    printf("we have recovered\n");
# endif
# endif
                    resending = FALSE;
                    resending = FALSE;
                }
                }
                else {
                else {
                    resend_pkt = resend_pkt->pk_next;
                    resend_pkt = resend_pkt->pk_next;
                }
                }
            }
            }
            else {
            else {
                /*
                /*
                 * move the packet we just sent from the send queue to the root
                 * move the packet we just sent from the send queue to the root
                 */
                 */
                Packet *tmp_pkt, *tmp;
                Packet *tmp_pkt, *tmp;
 
 
# ifdef FAKE_BAD_LINE_TX
# ifdef FAKE_BAD_LINE_TX
                unfake_bad_line_tx();
                unfake_bad_line_tx();
# endif
# endif
 
 
                tmp_pkt = writeQueueSend;
                tmp_pkt = writeQueueSend;
                writeQueueSend = writeQueueSend->pk_next;
                writeQueueSend = writeQueueSend->pk_next;
                tmp_pkt->pk_next = NULL;
                tmp_pkt->pk_next = NULL;
                if (writeQueueRoot == NULL)
                if (writeQueueRoot == NULL)
                   writeQueueRoot = tmp_pkt;
                   writeQueueRoot = tmp_pkt;
                else {
                else {
                    tmp = writeQueueRoot;
                    tmp = writeQueueRoot;
                    while (tmp->pk_next != NULL) {
                    while (tmp->pk_next != NULL) {
                        tmp = tmp->pk_next;
                        tmp = tmp->pk_next;
                    }
                    }
                    tmp->pk_next = tmp_pkt;
                    tmp->pk_next = tmp_pkt;
                }
                }
            }
            }
#else  /* not RETRANS */
#else  /* not RETRANS */
            /*
            /*
             * switcher has taken the write, so remove it from the
             * switcher has taken the write, so remove it from the
             * queue, and free its resources
             * queue, and free its resources
             */
             */
            DevSW_FreePacket(Adp_removeFromQueue(&writeQueueSend));
            DevSW_FreePacket(Adp_removeFromQueue(&writeQueueSend));
#endif /* if RETRANS ... else ... */
#endif /* if RETRANS ... else ... */
 
 
            if (mode == async_block_on_write)
            if (mode == async_block_on_write)
               *finished = DevSW_WriteFinished(deviceToUse);
               *finished = DevSW_WriteFinished(deviceToUse);
 
 
        } /* endif write ok */
        } /* endif write ok */
    }
    }
    else /* packet == NULL */
    else /* packet == NULL */
    {
    {
        if (mode == async_block_on_write)
        if (mode == async_block_on_write)
           *finished = DevSW_WriteFinished(deviceToUse);
           *finished = DevSW_WriteFinished(deviceToUse);
    }
    }
}
}
 
 
static void async_process_heartbeat( void )
static void async_process_heartbeat( void )
{
{
    /* check to see whether we need to send a heartbeat */
    /* check to see whether we need to send a heartbeat */
    gettimeofday(&time_now, NULL);
    gettimeofday(&time_now, NULL);
 
 
    if (tv_diff(&time_now, &time_lastalive) >= HEARTRATE)
    if (tv_diff(&time_now, &time_lastalive) >= HEARTRATE)
    {
    {
        /*
        /*
         * if we've not booted then don't do send a heartrate the link
         * if we've not booted then don't do send a heartrate the link
         * must be reliable enough for us to boot without any clever stuff,
         * must be reliable enough for us to boot without any clever stuff,
         * if we can't do this then theres little chance of the link staying
         * if we can't do this then theres little chance of the link staying
         * together even with the resends etc
         * together even with the resends etc
         */
         */
        if (heartbeat_enabled) {
        if (heartbeat_enabled) {
            gettimeofday(&time_lastalive, NULL);
            gettimeofday(&time_lastalive, NULL);
            pacemaker();
            pacemaker();
        }
        }
    }
    }
}
}
 
 
static void async_process_callbacks( void )
static void async_process_callbacks( void )
{
{
    /* call any registered asynchronous callbacks */
    /* call any registered asynchronous callbacks */
    unsigned int i;
    unsigned int i;
    for ( i = 0; i < num_async_callbacks; ++i )
    for ( i = 0; i < num_async_callbacks; ++i )
       async_callbacks[i]( deviceToUse, &time_now );
       async_callbacks[i]( deviceToUse, &time_now );
}
}
 
 
void Adp_AsynchronousProcessing(const AsyncMode mode)
void Adp_AsynchronousProcessing(const AsyncMode mode)
{
{
    bool finished = FALSE;
    bool finished = FALSE;
#ifdef DEBUG
#ifdef DEBUG
    unsigned int wc = 0, dc = 0, ac = 0, hc = 0;
    unsigned int wc = 0, dc = 0, ac = 0, hc = 0;
# define INC_COUNT(x) ((x)++)
# define INC_COUNT(x) ((x)++)
#else
#else
# define INC_COUNT(x)
# define INC_COUNT(x)
#endif
#endif
 
 
    if ((time_lastalive.tv_sec == 0) && (time_lastalive.tv_usec == 0)) {
    if ((time_lastalive.tv_sec == 0) && (time_lastalive.tv_usec == 0)) {
      /* first time through, needs initing */
      /* first time through, needs initing */
      gettimeofday(&time_lastalive, NULL);
      gettimeofday(&time_lastalive, NULL);
    }
    }
 
 
    /* main loop */
    /* main loop */
    do
    do
    {
    {
        async_process_write( mode, &finished );
        async_process_write( mode, &finished );
        INC_COUNT(wc);
        INC_COUNT(wc);
 
 
        if ( ! finished && mode != async_block_on_write )
        if ( ! finished && mode != async_block_on_write )
        {
        {
            async_process_dbug_read( mode, &finished );
            async_process_dbug_read( mode, &finished );
            INC_COUNT(dc);
            INC_COUNT(dc);
        }
        }
 
 
        if ( ! finished && mode != async_block_on_write )
        if ( ! finished && mode != async_block_on_write )
        {
        {
           async_process_appl_read();
           async_process_appl_read();
           INC_COUNT(ac);
           INC_COUNT(ac);
        }
        }
 
 
        if ( ! finished )
        if ( ! finished )
        {
        {
          if (heartbeat_configured)
          if (heartbeat_configured)
            async_process_heartbeat();
            async_process_heartbeat();
          async_process_callbacks();
          async_process_callbacks();
          INC_COUNT(hc);
          INC_COUNT(hc);
        }
        }
 
 
    } while (!finished && mode != async_block_on_nothing);
    } while (!finished && mode != async_block_on_nothing);
 
 
#ifdef DEBUG
#ifdef DEBUG
    if ( mode != async_block_on_nothing )
    if ( mode != async_block_on_nothing )
       printf( "Async: %s - w %d, d %d, a %d, h %d\n",
       printf( "Async: %s - w %d, d %d, a %d, h %d\n",
               mode == async_block_on_write ? "blk_write" : "blk_read",
               mode == async_block_on_write ? "blk_write" : "blk_read",
               wc, dc, ac, hc );
               wc, dc, ac, hc );
#endif
#endif
}
}
 
 
/*
/*
 * install a handler for DC_APPL packets (can be NULL), returning old one.
 * install a handler for DC_APPL packets (can be NULL), returning old one.
 */
 */
DC_Appl_Handler Adp_Install_DC_Appl_Handler(const DC_Appl_Handler handler)
DC_Appl_Handler Adp_Install_DC_Appl_Handler(const DC_Appl_Handler handler)
{
{
    DC_Appl_Handler old_handler = dc_appl_handler;
    DC_Appl_Handler old_handler = dc_appl_handler;
 
 
#ifdef DEBUG
#ifdef DEBUG
    printf( "Installing DC_APPL handler %x (old %x)\n", handler, old_handler );
    printf( "Installing DC_APPL handler %x (old %x)\n", handler, old_handler );
#endif
#endif
 
 
    dc_appl_handler = handler;
    dc_appl_handler = handler;
    return old_handler;
    return old_handler;
}
}
 
 
 
 
/*
/*
 * add an asynchronous processing callback to the list
 * add an asynchronous processing callback to the list
 * TRUE == okay, FALSE == no more async processing slots
 * TRUE == okay, FALSE == no more async processing slots
 */
 */
bool Adp_Install_Async_Callback( const Adp_Async_Callback callback_proc )
bool Adp_Install_Async_Callback( const Adp_Async_Callback callback_proc )
{
{
    if ( num_async_callbacks < MAX_ASYNC_CALLBACKS && callback_proc != NULL )
    if ( num_async_callbacks < MAX_ASYNC_CALLBACKS && callback_proc != NULL )
    {
    {
        async_callbacks[num_async_callbacks] = callback_proc;
        async_callbacks[num_async_callbacks] = callback_proc;
        ++num_async_callbacks;
        ++num_async_callbacks;
        return TRUE;
        return TRUE;
    }
    }
    else
    else
       return FALSE;
       return FALSE;
}
}
 
 
 
 
/*
/*
 * delay for a given period (in microseconds)
 * delay for a given period (in microseconds)
 */
 */
void Adp_delay(unsigned int period)
void Adp_delay(unsigned int period)
{
{
    struct timeval tv;
    struct timeval tv;
 
 
#ifdef DEBUG
#ifdef DEBUG
    printf("delaying for %d microseconds\n", period);
    printf("delaying for %d microseconds\n", period);
#endif
#endif
    tv.tv_sec = (period / 1000000);
    tv.tv_sec = (period / 1000000);
    tv.tv_usec = (period % 1000000);
    tv.tv_usec = (period % 1000000);
 
 
    (void)select(0, NULL, NULL, NULL, &tv);
    (void)select(0, NULL, NULL, NULL, &tv);
}
}
 
 
/* EOF hostchan.c */
/* EOF hostchan.c */
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.