📄 socket.c
字号:
*
* Description : Called by the send() function for TCP transmission.
* It first calculates the free transmit buffer size
* and compares it with the size of the data to be transmitted to determine the transmission size.
* After calculating the data size, it copies data from TX_WR_PTR.
* It waits if there is a previous send command in process.
* When the send command is cleared, it updates the TX_WR_PTR up to the size to be transmitted
and performs the send command.
* Arguments : s - channel number
* buf - Pointer pointing data to send
* len - data size to send
* Returns : Succeeded: sent data size, Failed: -1
* Note : Internal Function
****************************************************************************************************
*/
int send_in(SOCKET s, u_char far * buf, u_int len)
{
u_char k;
u_int size;
union un_l2cval wr_ptr, ack_ptr;
unsigned int offset;
S_START:
disable(); // CT: Shadow register access should not conflict with ISR.
k = READ_VALUE(SHADOW_TXWR_PTR(s));
WINDOW_RESTORE_BASE; // Needed whenever we touch a shadow ptr; different window.
delay0(2);
wr_ptr.cVal[3] = READ_VALUE(TX_WR_PTR(s));
wr_ptr.cVal[2] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(1));
wr_ptr.cVal[1] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(2));
wr_ptr.cVal[0] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(3));
k = READ_VALUE(SHADOW_TXACK_PTR(s));
WINDOW_RESTORE_BASE; // Needed whenever we touch a shadow ptr; different window.
delay0(2);
ack_ptr.cVal[3] = READ_VALUE(TX_ACK_PTR(s));
ack_ptr.cVal[2] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(1));
ack_ptr.cVal[1] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(2));
ack_ptr.cVal[0] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(3));
enable();
// Suppress compiler errors that k is not used
k = k;
// Calculate send free buffer size
if (wr_ptr.lVal >= ack_ptr.lVal)
size = (u_int)(SSIZE[s] - (wr_ptr.lVal - ack_ptr.lVal));
else
size = (u_int)(SSIZE[s] - (0 - ack_ptr.lVal + wr_ptr.lVal));
// Recalulate after some delay because of error in pointer calculation
if (size > SSIZE[s])
{
if (select(s, SEL_CONTROL) != SOCK_ESTABLISHED)
return -1;
delay_ms(1);
goto S_START;
}
// Wait when previous sending has not finished yet and there's no free buffer
if (size == 0)
{
if (select(s, SEL_CONTROL) != SOCK_ESTABLISHED)
return -1;
delay_ms(1);
goto S_START;
}
else if (size < len)
{
len = size;
}
// Calculate pointer to data copy
offset = (UINT)(wr_ptr.lVal & SMASK[s]);
// copy data
write_data(s, buf, offset, len);
while (READ_VALUE(COMMAND(s)) & CSEND)
{
// Confirm previous send command
if (select(s, SEL_CONTROL) != SOCK_ESTABLISHED)
return -1;
}
// update tx_wr_ptr
wr_ptr.lVal = wr_ptr.lVal + len;
WRITE_VALUE(TX_WR_PTR(s), wr_ptr.cVal[3]);
WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(1), wr_ptr.cVal[2]);
WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(2), wr_ptr.cVal[1]);
WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(3), wr_ptr.cVal[0]);
delay0(1);
// SEND
WRITE_VALUE(COMMAND(s), CSEND);
return(len);
}
/*
****************************************************************************************************
* TCP data receiving function.
*
* Description : This function is to clear out any received TCP data.
* Arguments : s - channel number
* Returns : None
* Note : API Fcuntion
****************************************************************************************************
*/
void recv_clear(SOCKET s)
{
u_char k;
u_int size;
union un_l2cval wr_ptr, rd_ptr;
disable();
k = READ_VALUE(SHADOW_RXWR_PTR(s));
WINDOW_RESTORE_BASE; // Needed whenever we touch a shadow ptr; different window.
delay0(2);
wr_ptr.cVal[3] = READ_VALUE(RX_WR_PTR(s));
wr_ptr.cVal[2] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(1));
wr_ptr.cVal[1] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(2));
wr_ptr.cVal[0] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(3));
k = READ_VALUE(SHADOW_RXRD_PTR(s));
WINDOW_RESTORE_BASE; // Needed whenever we touch a shadow ptr; different window.
delay0(2);
rd_ptr.cVal[3] = READ_VALUE(RX_RD_PTR(s));
rd_ptr.cVal[2] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(1));
rd_ptr.cVal[1] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(2));
rd_ptr.cVal[0] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(3));
enable();
// Suppress compiler errors that k is not used
k = k;
// calculate received data size
if (wr_ptr.lVal >= rd_ptr.lVal)
size = (u_int)(wr_ptr.lVal - rd_ptr.lVal);
else
size = (u_int)(0 - rd_ptr.lVal + wr_ptr.lVal);
// Update rx_rd_ptr
rd_ptr.lVal += size;
WRITE_VALUE(RX_RD_PTR(s), rd_ptr.cVal[3]);
WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(1), rd_ptr.cVal[2]);
WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(2), rd_ptr.cVal[1]);
WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(3), rd_ptr.cVal[0]);
// RECV
WRITE_VALUE(COMMAND(s), CRECV);
}
/*
****************************************************************************************************
* TCP data receiving function.
*
* Description : This function is for receiving TCP data.
* The recv() function is an application I/F function. It will read up to len chars if there are
enough characters in the buffer, otherwise will onl read the number of characters availiable
* Arguments : s - channel number
* buf - Pointer where the data to be received is copied
* len - Size of the data to be received
* Returns : Succeeded: received data size, Failed: -1
* Note : API Fcuntion
****************************************************************************************************
*/
int recv(SOCKET s, u_char far * buf, u_int len)
{
u_char k;
u_int size;
union un_l2cval wr_ptr, rd_ptr;
unsigned int offset;
// If out length is 0, then we do not need to do anything
if (len <= 0)
return (0);
disable();
k = READ_VALUE(SHADOW_RXWR_PTR(s));
WINDOW_RESTORE_BASE; // Needed whenever we touch a shadow ptr; different window.
delay0(2);
wr_ptr.cVal[3] = READ_VALUE(RX_WR_PTR(s));
wr_ptr.cVal[2] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(1));
wr_ptr.cVal[1] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(2));
wr_ptr.cVal[0] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(3));
k = READ_VALUE(SHADOW_RXRD_PTR(s));
WINDOW_RESTORE_BASE; // Needed whenever we touch a shadow ptr; different window.
delay0(2);
rd_ptr.cVal[3] = READ_VALUE(RX_RD_PTR(s));
rd_ptr.cVal[2] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(1));
rd_ptr.cVal[1] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(2));
rd_ptr.cVal[0] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(3));
enable();
// Suppress compiler errors that k is not used
k = k;
// calculate IIM7010A received data size
if (wr_ptr.lVal == rd_ptr.lVal)
return(0);
else if (wr_ptr.lVal >= rd_ptr.lVal)
size = (u_int)(wr_ptr.lVal - rd_ptr.lVal);
else
size = (u_int)(0 - rd_ptr.lVal + wr_ptr.lVal);
// Make sure we do not try to read more characters than what is availiable in the IIM7010 buffer
if (size < len)
len = size;
// Calculate pointer to be copied received data
offset = ((UINT)(rd_ptr.lVal & RMASK[s]));
// Copy received data
size = read_data(s, offset, buf, len);
// Update rx_rd_ptr
rd_ptr.lVal += size;
WRITE_VALUE(RX_RD_PTR(s), rd_ptr.cVal[3]);
WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(1), rd_ptr.cVal[2]);
WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(2), rd_ptr.cVal[1]);
WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(3), rd_ptr.cVal[0]);
// RECV
WRITE_VALUE(COMMAND(s), CRECV);
return(size);
}
/*
****************************************************************************************************
* UDP data sending function.
*
* Description : Composed of the sendto()and sendto_in() functions.
* The send() function is an application I/F function.
* It continues to call the send_in() function to complete the sending of the data up to the
* size of the data to be sent
* when the application is called.Unlike TCP transmission, it designates the destination address
* and the port.
* Arguments : s - channel port
* buf - Pointer pointing data to send
* len - data size to send
* addr - destination IP address to send data
* port - destination port number to send data
* Returns : Sent data size
* Note : API Function
****************************************************************************************************
*/
u_int sendto(SOCKET s, u_char far * buf, u_int len, u_char * addr, u_int port)
{
//char val;
u_int ptr, size;
// Wait until previous send commnad has completed.
while(READ_VALUE(COMMAND(s)) & CSEND)
{
if(select(s, SEL_CONTROL) == SOCK_CLOSED)
return -1; // Error.
}
// Designate destination port number.
if (port != 0)
{
WRITE_VALUE(DST_PORT_PTR(s), (u_char)((port & 0xff00) >> 8));
WRITE_VALUE(DST_PORT_PTR(s) + SA_OFFSET(1), (u_char)(port & 0x00ff));
}
// Designate destination IP address
WRITE_VALUE(DST_IP_PTR(s), addr[0]);
WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(1), addr[1]);
WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(2), addr[2]);
WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(3), addr[3]);
if (len <= 0)
return (0);
else
{
ptr = 0;
do
{
size = sendto_in(s, buf + ptr, len);
len = len - size;
ptr += size;
} while ( len > 0);
}
return ptr;
}
/*
****************************************************************************************************
* UDP data sending function.
*
* Description : An internal function that is the same as the send_in() function of the TCP.
* Arguments : s - Channel number
* buf - Pointer indicating the data to send
* len - data size to send
* Returns : Sent data size
* Note : Internal Function
****************************************************************************************************
*/
u_int sendto_in(SOCKET s, u_char far * buf, u_int len)
{
u_char k;
u_int size;
union un_l2cval wr_ptr, rd_ptr;
unsigned int offset;
S2_START:
disable();
k = READ_VALUE(SHADOW_TXWR_PTR(s));
WINDOW_RESTORE_BASE; // Needed whenever we touch a shadow ptr; different window.
delay0(2);
wr_ptr.cVal[3] = READ_VALUE(TX_WR_PTR(s));
wr_ptr.cVal[2] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(1));
wr_ptr.cVal[1] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(2));
wr_ptr.cVal[0] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(3));
k = READ_VALUE(SHADOW_TXRD_PTR(s));
WINDOW_RESTORE_BASE; // Needed whenever we touch a shadow ptr; different window.
delay0(2);
rd_ptr.cVal[3] = READ_VALUE(TX_RD_PTR(s));
rd_ptr.cVal[2] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(1));
rd_ptr.cVal[1] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(2));
rd_ptr.cVal[0] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(3));
enable();
// Suppress compiler errors that k is not used
k = k;
// Calculate free buffer size to send
if (wr_ptr.lVal >= rd_ptr.lVal)
size = (u_int)(SSIZE[s] - (wr_ptr.lVal - rd_ptr.lVal));
else
size = (u_int)(SSIZE[s] - (0 - rd_ptr.lVal + wr_ptr.lVal));
// Recalulate after some delay because of error in pointer caluation
if (size > SSIZE[s])
{
delay_ms(1);
goto S2_START;
}
// Wait when previous sending has not finished yet and there's no free buffer
if (size == 0)
{
delay_ms(1);
goto S2_START;
}
else if (size < len)
{
len = size;
}
// Calculate pointer to copy data pointer
offset =(UINT)(wr_ptr.lVal & SMASK[s]);
// copy data
write_data(s, buf, offset, len);
// Confirm previous send command
while (READ_VALUE(COMMAND(s)) & CSEND)
{
if(select(s, SEL_CONTROL)==SOCK_CLOSED)
return -1; // Error
}
// update tx_wr_ptr
wr_ptr.lVal = wr_ptr.lVal + len;
WRITE_VALUE(TX_WR_PTR(s), wr_ptr.cVal[3]);
WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(1), wr_ptr.cVal[2]);
WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(2), wr_ptr.cVal[1]);
WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(3), wr_ptr.cVal[0]);
delay0(1);
// SEND
WRITE_VALUE(COMMAND(s), CSEND);
return(len);
}
/*
****************************************************************************************************
* UDP data receiving function.
*
* Description : Function for receiving UDP and IP layer RAW mode data, and handling the data header.
* Arguments : s - channel number
* buf - Pointer where the data to be received is copied
* len - Size of the data to be received
* addr - Peer IP address for receiving
* port - Peer port number for receiving
* Returns : Received data size
* Note : API Function
****************************************************************************************************
*/
u_int recvfrom(SOCKET s, u_char far *buf, u_int len, u_char *addr, u_int *port)
{
struct _UDPHeader // When receiving UDP data, header added by W3100A
{
union
{
struct
{
u_int size;
u_char addr[4];
u_int port;
} header;
u_char stream[8];
} u;
} UDPHeader;
u_int ret;
union un_l2cval wr_ptr, rd_ptr;
u_long size;
u_char k;
unsigned int offset;
if(select(s,SEL_CONTROL)==SOCK_CLOSED)
return -1;
disable();
k = READ_VALUE(SHADOW_RXWR_PTR(s));
WINDOW_RESTORE_BASE; // Needed whenever we touch a shadow ptr; different window.
delay0(2);
wr_ptr.cVal[3] = READ_VALUE(RX_WR_PTR(s));
wr_ptr.cVal[2] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(1));
wr_ptr.cVal[1] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(2));
wr_ptr.cVal[0] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(3));
k = READ_VALUE(SHADOW_RXRD_PTR(s));
WINDOW_RESTORE_BASE; // Needed whenever we touch a shadow ptr; different window.
delay0(2);
rd_ptr.cVal[3] = READ_VALUE(RX_RD_PTR(s));
rd_ptr.cVal[2] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(1));
rd_ptr.cVal[1] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(2));
rd_ptr.cVal[0] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(3));
enable();
// Suppress compiler errors that k is not used
k = k;
// Calculate received data size
if (len <= 0)
return (0);
else if (wr_ptr.lVal >= rd_ptr.lVal)
size = wr_ptr.lVal - rd_ptr.lVal;
else
size = 0 - rd_ptr.lVal + wr_ptr.lVal;
if (size == 0)
return 0;
// Calulate received data pointer
offset = ((UINT)(rd_ptr.lVal & RMASK[s]));
// When UDP data
if (( READ_VALUE(OPT_PROTOCOL(s)) & 0x07) == SOCK_DGRAM)
{
// Copy W3100A UDP header
read_data(s, offset, UDPHeader.u.stream, 8);
// Read UDP Packet size
size = UDPHeader.u.stream[0];
size = (size << 8) + UDPHeader.u.stream[1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -