📄 hdlc.c
字号:
/* Store the total size, removing the two bytes of the FCS. */
bytes_left = (_ppp_rx_queue[_ppp_rx_queue_read]->size - PPP_FCS_SIZE_BYTE2);
/* Determine offset if Address & Control compression is used. */
if (buffer[0] == 0xff)
acclen += PPP_MAX_ADDR_CONTROL_SIZE;
/* Determine offset if Protocol Field compression is used. */
if (buffer[acclen] == 0x21)
pfclen += PPP_COMPRESS_HEADER;
else
pfclen += PPP_MAX_PROTOCOL_SIZE;
hdrlen = sizeof(DLAYER) - (acclen + pfclen);
paylen = NET_PARENT_BUFFER_SIZE - hdrlen;
/* Allocate a buffer chain to copy this packet into. */
buf_ptr = MEM_Buffer_Chain_Dequeue (&MEM_Buffer_Freelist,
((INT32)(bytes_left + hdrlen)));
/* Make sure we got some buffers. */
if (buf_ptr)
{
/* Set the total length in the parent buffer. */
buf_ptr->mem_total_data_len = bytes_left;
/* Set the data pointer. */
buf_ptr->data_ptr = (buf_ptr->mem_parent_packet + hdrlen);
/* Now break this packet into a buffer chain. */
/* Will it all fit into one buffer? */
if (bytes_left <= paylen)
{
/* Store the number of bytes held by this buffer, this includes the
protocol headers. */
buf_ptr->data_len = buf_ptr->mem_total_data_len;
/* Copy the data. */
memcpy (buf_ptr->data_ptr, buffer, (unsigned int)bytes_left);
}
else
{
/* Fill the parent buffer in the chain. This one is slightly smaller than
the rest in the chain. */
memcpy (buf_ptr->data_ptr, buffer, (unsigned int)paylen);
/* Take off the bytes just copied from the total bytes left. */
bytes_left -= paylen;
/* Store the number of bytes in this buffer. */
buf_ptr->data_len = paylen;
/* Bump it the number of bytes just copied. */
buffer += paylen;
/* Get a work buffer pointer to the buffer chain */
work_buf = buf_ptr;
/* Break the rest up into the multiple buffers in the chain. */
do
{
/* Move to the next buffer in the chain */
work_buf = work_buf->next_buffer;
/* If the bytes left will fit into one buffer then copy them over */
if (bytes_left <= NET_MAX_BUFFER_SIZE)
{
/* Copy the rest of the data. */
memcpy (work_buf->mem_packet, buffer, (unsigned int)bytes_left);
/* Set the data ptr */
work_buf->data_ptr = work_buf->mem_packet;
/* Store the number of bytes in this buffer. */
work_buf->data_len = bytes_left;
/* Update the data bytes left to copy. */
bytes_left = 0;
}
else
{
/* Copy all that will fit into a single buffer */
memcpy (work_buf->mem_packet, buffer, NET_MAX_BUFFER_SIZE);
/* Update the buffer pointer */
buffer += NET_MAX_BUFFER_SIZE;
/* Set the data ptr */
work_buf->data_ptr = work_buf->mem_packet;
/* Store the number of bytes in this buffer. */
work_buf->data_len = NET_MAX_BUFFER_SIZE;
/* Update the data bytes left to copy. */
bytes_left -= NET_MAX_BUFFER_SIZE;
}
} while ( (bytes_left > 0) &&
(bytes_left <=
(_ppp_rx_queue[_ppp_rx_queue_read]->size - PPP_FCS_SIZE_BYTE2)) );
} /* end if it will fit into one buffer */
/* Remove Address and Control header if it exists. */
if (acclen)
{
buf_ptr->data_ptr += acclen;
buf_ptr->data_len -= acclen;
buf_ptr->mem_total_data_len -= acclen;
}
/* Set the device that this packet was RX on. */
buf_ptr->mem_buf_device = _ppp_rx_queue[_ppp_rx_queue_read]->device;
/* Remove the temp buffer entry. */
_ppp_rx_queue[_ppp_rx_queue_read] = NU_NULL;
/* Move the packet onto the buffer list, where the upper
layer protocols can find it. */
MEM_Buffer_Enqueue (&MEM_Buffer_List, buf_ptr);
/* Let the upper layer know a good packet is here. */
NU_Set_Events(&Buffers_Available, (UNSIGNED)2, NU_OR);
}
else
{
NERRS_Log_Error (TCP_SEVERE, __FILE__, __LINE__);
/* Bump the number of packets discarded. */
((LINK_LAYER *)_ppp_rx_queue[_ppp_rx_queue_read]->device->
link_layer)->silent_discards++;
}
}
/* Bump the index and make sure the ring buffer loops. */
_ppp_rx_queue_read++;
_ppp_rx_queue_read %= (UINT8) HDLC_MAX_HOLDING_PACKETS_PTR;
} /* end PPP_RX_HISR routine */
#ifndef PPP_POLLED_TX
/************************************************************************
* FUNCTION
*
* PPP_TX_HISR_Entry
*
* DESCRIPTION
*
* Entry function for transmit HISR. This function is responsible for
* freeing the buffers used by the transmitted packet. It will also
* begin transmission of the next packet if there is one ready on the
* transmit queue.
*
* AUTHOR
*
* Uriah Pollock
*
* INPUTS
*
* none
*
* OUTPUTS
*
* none
*
************************************************************************/
VOID HDLC_TX_HISR_Entry (VOID)
{
DV_DEVICE_ENTRY *dev_ptr;
INT old_val;
/* Get a pointer to the device that activated this HISR. */
dev_ptr = _ppp_tx_dev_ptr_queue[_ppp_tx_dev_ptr_queue_read];
/* Make sure there was a device structure there. */
if (dev_ptr)
{
/* Disable interrupts. */
old_val = NU_Control_Interrupts (NU_DISABLE_INTERRUPTS);
/* Clear this entry. */
_ppp_tx_dev_ptr_queue[_ppp_tx_dev_ptr_queue_read] = NU_NULL;
/* If there is a buffer on the TX queue then remove it. It was just
transmitted. */
if (dev_ptr->dev_transq.head != NU_NULL)
{
/* Give the buffers held by this packet back to the stack. Note
that for PPP negotiation packets the deallocation list
(dlist) for the packet is NU_NULL. This means that the
packet will not be placed onto any list, which is the
desired affect since PPP frees these packets itself. */
if (dev_ptr->dev_transq.head->mem_dlist)
DEV_Recover_TX_Buffers (dev_ptr);
else
MEM_Buffer_Dequeue(&dev_ptr -> dev_transq);
/* Check to see if there is another packet that needs to be
sent. */
if (dev_ptr->dev_transq.head)
{
/* Restore the interrupts */
NU_Control_Interrupts (old_val);
/* Send the next packet in the tx queue. */
dev_ptr->dev_start (dev_ptr, dev_ptr->dev_transq.head);
}
}
/* Restore the interrupts */
NU_Control_Interrupts (old_val);
}
/* Bump the read index. */
_ppp_tx_dev_ptr_queue_read++;
/* Check for wrap of the ring buffer. */
_ppp_tx_dev_ptr_queue_read %= (UINT8) HDLC_MAX_TX_QUEUE_PTRS;
}
#endif
/************************************************************************
* FUNCTION
*
* PPP_Compute_TX_FCS
*
* DESCRIPTION
*
* This function will compute the frame check sequence for the frame
* contained at the address pointed to by frame_ptr. The computation of
* the FCS spans over multiple buffers in the chain containing the
* packet.
*
* AUTHOR
*
* Uriah Pollock
*
* INPUTS
*
* UINT16 fcs The initial FCS to start with
* NET_BUFFER *buf_ptr Pointer to the buffer that
* holds the packet to be sent.
*
* OUTPUTS
*
* UINT16 The computed FCS
*
************************************************************************/
UINT16 HDLC_Compute_TX_FCS (UINT16 fcs, NET_BUFFER *buf_ptr)
{
NET_BUFFER *tmp_buf_ptr = buf_ptr;
INT32 len, bytes_done;
UINT8 HUGE *frame_ptr;
bytes_done = 0;
/* Get the length of the buffer and a pointer to the data. */
len = tmp_buf_ptr->data_len;
frame_ptr = tmp_buf_ptr->data_ptr;
bytes_done += len;
while (tmp_buf_ptr)
{
/* Compute the FCS over the bytes in this buffer. */
while (len-- > 0)
fcs = (UINT16) ((fcs >> 8) ^ fcstab[(fcs ^ *frame_ptr++) & 0xff]);
tmp_buf_ptr = tmp_buf_ptr->next_buffer;
if (tmp_buf_ptr)
{
/* Get the length of the buffer and a pointer to the data. */
len = tmp_buf_ptr->data_len;
frame_ptr = tmp_buf_ptr->data_ptr;
bytes_done += len;
}
}
return (fcs);
}
/************************************************************************
* FUNCTION
*
* PPP_Compute_RX_FCS
*
* DESCRIPTION
*
* This function will compute the frame check sequence for the frame
* contained at the address pointed to by frame_ptr. The computaion
* does not span buffers. It is done over a contiguous area of memory
* only.
*
* AUTHOR
*
* Uriah Pollock
*
* INPUTS
*
* UINT16 fcs The initial FCS to start with
* PPP_TEMP_BUFFER *buf_ptr Pointer to the packet to
* compute the FCS over.
*
* OUTPUTS
*
* UINT16 The computed FCS
*
************************************************************************/
UINT16 HDLC_Compute_RX_FCS (UINT16 fcs, PPP_TEMP_BUFFER *buf_ptr)
{
UINT32 len;
UINT8 HUGE *frame_ptr;
/* Get the length of the buffer and a pointer to the data. */
len = buf_ptr->size;
frame_ptr = buf_ptr->buffer;
/* Compute the FCS. */
while (len--)
fcs = (UINT16) ((fcs >> 8) ^ fcstab[(fcs ^ *frame_ptr++) & 0xff]);
return (fcs);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -