📄 hostchan.c
字号:
} } 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(__CYGWIN__)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);}#endifstatic 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_RXstatic 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_TXstatic 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -