diff options
Diffstat (limited to 'gdb/rdi-share/hostchan.c')
-rw-r--r-- | gdb/rdi-share/hostchan.c | 1057 |
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 */ |