📄 channels.c
字号:
dev->lastUsed = b; Angel_LeaveCriticalSection(); LogInfo(LOG_CHANNEL, ("adp_add_pkt: Dev: %d stored packet %d, buffer 0x%x\n", devid, pkt_no, buffer)); Angel_show_unacked_list(devid); return adp_ok; } Angel_LeaveCriticalSection(); LogWarning(LOG_CHANNEL, ("adp_add_pkt: Dev %d: No free buffers to add" " packet %d to resend list\n", devid, pkt_no)); Angel_show_unacked_list(devid); return adp_ok;}/* * Function: adp_free_pkt * Purpose: To remove the packet with a given buffer ref from the resend list. * * Pre-Conditions: 'cur' must point to a buffer in the used list. * * Params: * Input: devid - the device ID of the driver * cur - the buffer ref of the buffer to delete * last - the buffer ref of the previous buffer, or LISTEND if cur is * first buffer * * Returns: adp_ok */static void adp_free_pkt(register struct DevState *dev, int cur, int last){ /* free up the actual buffer */ if (dev->unackedBufs[cur].buf) Angel_BufferRelease(dev->unackedBufs[cur].buf); else LogWarning(LOG_CHANNEL, ("adp_free_pkt: buffer NULL at index %d\n", cur)); /* clear buffer contents for tidyness */ dev->unackedBufs[cur].len = 0; dev->unackedBufs[cur].packno = 0; dev->unackedBufs[cur].buf = NULL; /* remove buffer from used list */ if (cur == dev->firstUsed) { /* remove first, possibly only item */ dev->firstUsed = dev->unackedBufs[cur].next; if (dev->firstUsed == LISTEND) dev->lastUsed = LISTEND; } else if (cur == dev->lastUsed) { /* remove last item -- cannot be only one */ dev->lastUsed = last; dev->unackedBufs[last].next = LISTEND; } else { /* remove any other -- must be at least 3 to begin with. */ dev->unackedBufs[last].next = dev->unackedBufs[cur].next; } /* and add back to free list */ dev->unackedBufs[cur].next = dev->firstFree; dev->firstFree = cur;}/* * Function: adp_remove_pkt * Purpose: To remove all packets which are acknowledged by * the given sequence number. Normally, this is just * the packet which has sequence number 'pkt_no', but * if two (or more) packets are sent out simultaneously, * then both will be ack'd by the next reply from the * host. Two or more packets can be sent without an * intervening reply if the packets are on different * channels. * * Params: * Input: devid - the device the packet is using * pkt_no - the packet sequence number * * Returns: adp_err - an adp error code equivalent to dev_err */static AdpErrs adp_remove_pkt(DeviceID devid, SequenceNR pkt_no){ struct DevState *dev = &dev_state[devid]; short i, j = LISTEND; LogInfo(LOG_CHANNEL, ("adp_remove_pkt: Dev: %d ack packet %d (ackExpected %d to max %d)\n", devid, pkt_no, dev->ackExpected, nextSEQ(dev->currentFrame))); Angel_EnterCriticalSection(); while (adp_between(dev->ackExpected, pkt_no, nextSEQ(dev->currentFrame))) { /* if we've got a buffered packet for this sequence number, * free it now. */ i = adp_get_unack_bufno(devid, dev->ackExpected, dev->firstUsed, &j); if (i != LISTEND) { adp_free_pkt(dev, i, j); } INC(dev->ackExpected); } Angel_LeaveCriticalSection(); Angel_show_unacked_list(devid); return adp_ok;}/* * Function: adp_translate_dev_error * Purpose: To translate an error code from the underlying device * system to the ADP error code set. * * Params: * Input: dev_err - a device error code (DE_xxx) * * Returns: adp_err - an adp error code equivalent to dev_err */AdpErrsadp_translate_dev_error(DevError dev_err){ switch (dev_err) { case DE_OKAY: return adp_ok; case DE_NO_DEV: case DE_BAD_DEV: return adp_device_not_found; case DE_BAD_CHAN: return adp_bad_channel_id; case DE_BUSY: return adp_write_busy; case DE_INVAL: return adp_bad_packet; default: return adp_failed; }}/* * Function: release_callback * Purpose: To release the buffer used by various send functions, if the * packet being sent is not on a reliable packet stream (i.e. there * will be no acknowledging packet). * * Params: * Input: v_chan_pkt -- pointer to packet's data * v_chan_len -- length of the packet. * v_status -- status * cb_data -- the device ID * * Returns: none */static void release_callback(void *v_chan_pkt, void *v_chan_len, void *v_status, void *cb_data){ DevStatus status = (DevStatus) (int)v_status; p_Buffer chan_pkt = (p_Buffer)v_chan_pkt; p_Buffer buffer = chan_pkt - CB_CHAN_DATA_BYTE_POS; IGNORE(cb_data); IGNORE(v_chan_len); if (status != DS_DONE) LogWarning(LOG_CHANNEL, ("release_callback: status not OK (%d)\n", status)); LogInfo(LOG_CHANNEL, ( "release callback: freeing packet\n")); Angel_BufferRelease( buffer );}/* * Function: send_resend_msg * Purpose: To format and send a resend message on device devid. * The packet sequence numbers are taken from the device * state, and the last good frame (i.e. one before the * packet being requested) is passed in. * * Params: * Input: devid - the device ID of the driver * lastGoodFrame - the sequence number of the last good * frame. The other side should send LGF+1. * * Returns: AdpErrs - adp_ok if ok * adp_failed if buffer not available * translation of device error (see adp_translate_dev_error()) * otherwise. */static AdpErrs send_resend_msg(DeviceID devid, SequenceNR lastGoodFrame){ DevError dev_err; p_Buffer packet; packet = angel_ChannelAllocBuffer(CF_DATA_BYTE_POS); if (packet == NULL) { LogError(LOG_CHANNEL, ("send_resend_msg: Could not allocate a buffer\n")); return adp_failed; } packet[CF_CHANNEL_BYTE_POS] = CI_PRIVATE; packet[CF_PACKET_SEQ_BYTE_POS] = dev_state[devid].currentFrame; packet[CF_ACK_SEQ_BYTE_POS] = lastGoodFrame; packet[CF_FLAGS_BYTE_POS] = CF_RESEND; LogWarning(LOG_CHANNEL, ( "send_resend_msg: resend for frame %d\n", lastGoodFrame)); do { dev_err = angel_DeviceWrite(devid, packet, CF_DATA_BYTE_POS, release_callback, (void *)CI_PRIVATE, DC_DBUG); if (dev_err == DE_BUSY); { Angel_Yield(); } } while (dev_err == DE_BUSY); if (dev_err == DE_OKAY) { LogInfo(LOG_CHANNEL, ( "sent resend msg... ok\n", dev_err)); } else { LogError(LOG_CHANNEL, ( "sent resend msg, FAILED ret code 0x%x\n", dev_err)); angel_ChannelReleaseBuffer(packet); } return adp_translate_dev_error(dev_err);}/* * Function: send_heartbeat_ack_msg * Purpose: Send the acknowledgement for a heartbeat msg * * Params: * Input: devid device ID of the driver * * Returns: AdpErrs - should be adp_ok */static AdpErrs send_heartbeat_ack_msg(DeviceID devid, int timestamp){ p_Buffer packet; DevError dev_err; /* * if not ack'ing then just return; we dont want to mess our * debugger up! */ if (!Angel_AckedHeartbeats) { LogInfo(LOG_CHANNEL, ( "not acking heartbeats.\n")); return adp_ok; } /* * Send a resend message, usually in response to a bad packet or * a resend request */ packet = angel_ChannelAllocBuffer(CF_DATA_BYTE_POS); if (packet == NULL) { return adp_failed; } packet[CF_CHANNEL_BYTE_POS] = CI_PRIVATE; packet[CF_PACKET_SEQ_BYTE_POS] = dev_state[devid].currentFrame; packet[CF_ACK_SEQ_BYTE_POS] = lastSEQ(dev_state[devid].frameExpected); packet[CF_FLAGS_BYTE_POS] = CF_HEARTBEAT; PUT32LE(packet + CF_DATA_BYTE_POS, timestamp); LogInfo(LOG_CHANNEL, ( "set up heartbeat packet, trying to write\n")); do { dev_err = angel_DeviceWrite(devid, packet, CF_DATA_BYTE_POS + 4, release_callback, (void *)CI_PRIVATE, DC_DBUG); if (dev_err == DE_BUSY); { Angel_Yield(); } } while (dev_err == DE_BUSY); if (dev_err == DE_OKAY) { LogInfo(LOG_CHANNEL, ( "sent heartbeat msg... ok\n", dev_err)); } else { LogError(LOG_CHANNEL, ( "sent heartbeat msg, FAILED ret code 0x%x\n", dev_err)); angel_ChannelReleaseBuffer(packet); } return adp_translate_dev_error(dev_err);}/* * Function: read_callback * Purpose: callback for packet rx on active device. * This code handles all packet input for the DC_DBUG * device channel, implementing it's own channel split * on top of this to implement the various debugging * channels. * * The code must perform most of the reliability functions * required by the debug channels, checking for lost or * out of sequence packets, requesting resends etc. This * version of the code is very different to that in previous * Angel systems, as it is here that many of the improvements * to Angel have been made for SDT 2.11a. * * For a description of the code, see inline comments, and * the forthcoming Guide "Angel SDT2.11a: An Introduction" * * Params: * Input: v_chan_pkt -- pointer to packet's data * v_chan_len -- length of packet * v_status -- status of packet -- good or bad data * cb_data -- the device ID * * Returns: Nothing. May call specific or general read callback, * or trigger a message to be sent in reply. *//* this macro is called when it is possible that a bad packet delivery * has been counted in the packet flow control; if this weren't done * the code would hang if waiting for the recovery packet when a bad * packet was delivered. */#define check_flow_control() if (booted_flow_controlled) \ angel_DeviceControl(devid, DC_RX_PACKET_FLOW, (void*)-1);static voidread_callback(void *v_chan_pkt, void *v_chan_len, void *v_status, void *cb_data){ p_Buffer chan_pkt = (p_Buffer) v_chan_pkt; unsigned chan_len = (unsigned)v_chan_len; DevStatus status = (DevStatus) (int)v_status; DeviceID devid = (DeviceID) cb_data; ChannelID chanid; SequenceNR rx_packetseq; SequenceNR rx_ackseq; unsigned char rx_flags; register struct DevState *dev = NULL; /* * clear buffers mode tells buffers.c to put 0xDEAD in * free buffers. check we haven't been handed one of these. */ if (*chan_pkt == 0xAD && *(chan_pkt+1) == 0xDE && *(chan_pkt+2) == 0xAD && *(chan_pkt+3) == 0xDE ) { LogError(LOG_CHANNEL, ("read callback: called with free buffer %x (status %d)\n", chan_pkt, status)); return; } dev = &dev_state[devid]; switch (status) { case DS_DONE: /* extract and check channel */ chanid = chan_pkt[CF_CHANNEL_BYTE_POS]; rx_packetseq = chan_pkt[CF_PACKET_SEQ_BYTE_POS]; rx_ackseq = chan_pkt[CF_ACK_SEQ_BYTE_POS];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -