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