📄 socket.c
字号:
// Read IP address of the peer
addr[0] = UDPHeader.u.header.addr[0];
addr[1] = UDPHeader.u.header.addr[1];
addr[2] = UDPHeader.u.header.addr[2];
addr[3] = UDPHeader.u.header.addr[3];
// Read Port number of the peer
*port = UDPHeader.u.stream[6];
*port = (*port << 8) + UDPHeader.u.stream[7];
// Increase read pointer by 8, because already read as UDP header size
rd_ptr.lVal += 8;
// Calculate UDP data copy pointer
offset = ((UINT)(rd_ptr.lVal & RMASK[s]));
// Calculate data size of current UDP Packet from UDP header
size = size - 8;
// Copy one UDP data packet to user-specific buffer
ret = read_data(s, offset, buf, (u_int)size);
// Increase read pointer by UDP packet data size
rd_ptr.lVal += ret;
}
else if ((READ_VALUE(OPT_PROTOCOL(s)) & 0x07) == SOCK_IPL_RAW) // When IP layer RAW mode data
{
// Copy W3100A IP Raw header
read_data(s, offset, UDPHeader.u.stream, 6);
// Read IP layer RAW Packet size
size = UDPHeader.u.stream[0];
size = (size << 8) + UDPHeader.u.stream[1];
// Read IP address of the peer
addr[0] = UDPHeader.u.header.addr[0];
addr[1] = UDPHeader.u.header.addr[1];
addr[2] = UDPHeader.u.header.addr[2];
addr[3] = UDPHeader.u.header.addr[3];
// Increase read pointer by 6, because already read as IP RAW header size
rd_ptr.lVal += 6;
// Calculate IP layer raw mode data pointer
offset = ((UINT)(rd_ptr.lVal & RMASK[s]));
// Copy one IP Raw data packet to user-specific buffer
ret = read_data(s, offset, buf, (u_int)size);
rd_ptr.lVal = rd_ptr.lVal + (ret - 4);
}
// Update rx_rd_ptr
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);
// Real received size return
return(ret);
}
/*
****************************************************************************************************
* Channel closing function.
*
* Description : Function for closing the connection of the designated channel.
* Arguments : s - channel number
* Returns : None
* Note : API Function
****************************************************************************************************
*/
void close(SOCKET s)
{
u_int len;
short sAttempts = 0;
I_STATUS[s] = 0;
if (select(s, SEL_CONTROL) == SOCK_CLOSED)
return; // Already closed
// When closing, if there's data which have not processed, Insert some source codes to handle this
// Or before application call close(), handle those data first and call close() later.
len = select(s, SEL_SEND);
if (len == SSIZE[s])
{
// CLOSE
WRITE_VALUE(COMMAND(s), CCLOSE);
// TODO: The 'SCLOSED' status value is only set briefly as part of the close,
// and will otherwise quickly return to normal. That means your code might
// become 'stuck' at this point even if the packet has closed normally.
// Rather than a while() call, it might be preferred to time out on this
// close check and return to the application after some time.
while(!(I_STATUS[s] & SCLOSED))
{
sAttempts++;
if( sAttempts > 10 )
{
break;
}
I2CHIP_POLL_ISR(in4_isr_i2chip);
}
}
}
u_char tx_empty(SOCKET s)
{
return (select(s, SEL_SEND) == SSIZE[s]);
}
/*
****************************************************************************************************
* Channel closing function.
*
* Description : Function for closing the connection of the designated channel.
* Arguments : s - channel number
* Returns : None
* Note : API Function
****************************************************************************************************
*/
char reset_sock(SOCKET s)
{
u_char c;
c = 1 << s;
// RESET
WRITE_VALUE(RESETSOCK, c);
return (1);
}
/*
****************************************************************************************************
* Function handling the channel socket information.
*
* Description : Return socket information of designated channel
* Arguments : s - channel number
* func - SEL_CONTROL(0x00) -> return socket status
* SEL_SEND(0x01) -> return free transmit buffer size
* SEL_RECV(0x02) -> return received data size
* Returns : socket status or free transmit buffer size or received data size
* Note : API Function
****************************************************************************************************
*/
u_int select(SOCKET s, u_char func)
{
u_int val;
union un_l2cval rd_ptr, wr_ptr, ack_ptr;
u_char k;
switch (func)
{
// socket status information
case SEL_CONTROL :
val = READ_VALUE(SOCK_STATUS(s));
break;
// Calculate send free buffer size
case SEL_SEND :
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));
if (( READ_VALUE(OPT_PROTOCOL(s)) & 0x07) == SOCK_STREAM) // TCP
{
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();
if (wr_ptr.lVal >= ack_ptr.lVal)
val = (u_int)(SSIZE[s] - (wr_ptr.lVal - ack_ptr.lVal));
else
val = (u_int)(SSIZE[s] - (0 - ack_ptr.lVal + wr_ptr.lVal));
}
else // UDP, IP RAW ... (except TCP)
{
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();
if (wr_ptr.lVal >= rd_ptr.lVal)
val = (u_int)(SSIZE[s] - (wr_ptr.lVal - rd_ptr.lVal));
else
val = (u_int)(SSIZE[s] - (0 - rd_ptr.lVal + wr_ptr.lVal));
}
break;
// Calculate received data size
case SEL_RECV :
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();
if (wr_ptr.lVal == rd_ptr.lVal)
val = 0;
else if (wr_ptr.lVal > rd_ptr.lVal)
val = (u_int)(wr_ptr.lVal - rd_ptr.lVal);
else
val = (u_int)(0 - rd_ptr.lVal + wr_ptr.lVal);
break;
default :
val = -1;
break;
}
// Suppress compiler errors that k is not used
k = k;
return(val);
}
//
// unsigned char dma_read_i2chip (unsigned int i2_segm, unsigned int i2_offs,
// unsigned int cnt, unsigned int des_segm, unsigned int des_offs);
// Using DMA0 to read data from i2chip buffer into destination SRAM.
// where:
// unsigned int cnt = number of sectors, 512-byte per sector
// unsigned int des_segm = segment of destination SRAM data memory
// unsigned int des_offs = offset of destination SRAM data memory
// unsigned int i2_segm = segment of i2chip buffer mapped in memory
// unsigned int i2_offs = offset of i2chip buffer mapped in memory
// return DMA counter value
//
unsigned int dma_read_i2chip(u_char far* i2_src, u_char far* des, u_int cnt)
{
u_int des_segm, des_offs;
u_int i2_segm, i2_offs;
u_long temp;
temp = ((long)FP_SEG(des) << 4) + ((long)FP_OFF(des));
des_segm = (u_int)(temp >> 16);
des_offs = (u_int)(temp & 0xffff);
temp = ((long)FP_SEG(i2_src) << 4) + ((long)FP_OFF(i2_src));
i2_segm = (u_int)(temp >> 16);
i2_offs = (u_int)(temp & 0xffff);
outport(0xffc6, des_segm); /* D0DSTH destination SRAM segment */
outport(0xffc4, des_offs); /* D0DSTL destination SRAM offset */
outport(0xffc2, i2_segm); /* D0SRCH=SP0RD */
outport(0xffc0, i2_offs); /* D0SRCL=SP0RD */
outport(0xffc8, cnt); // D0TC counter
outport(0xfff8,0x0504); // PLLCON, 0203=10M,050f=40M, 051f=80MHz
// DMA0 mem-mem, 16-bit, unsync, Start moving data line below
outport(0xffca, 0xb60e); /* D0CON 1011 0110 0000 1111 */
// outport(0xffca, 0xb42e); // 1011 0100 0010 1110
while( inport(0xffc8) ); /* D0TC counter=0, DMA complete */
outport(0xfff8,0x051f); // PLLCON, 0203=10M,050f=40M, 051f=80MHz
return( inport(0xffc8) ); // counter
}
//
// unsigned int dma_write_i2chip (unsigned int src_segm, unsigned int src_offs,
// unsigned int cnt, unsigned int i2_segm, unsigned int i2_offs);
// Using DMA0 to write data from memory into i2chip.
// where:
// unsigned int cnt = number of 16-bit DMA transfers
// unsigned int src_segm = segment of the source SRAM data memory
// unsigned int src_offs = offset of the source SRAM data memory
// unsigned int i2_segm = segment of i2chip buffer mapped in memory
// unsigned int i2_offs = offset of i2chip buffer mapped in memory
// return DMA counter value
//
unsigned int dma_write_i2chip(u_char far* src, u_char far* i2_dest, u_int cnt)
{
u_int src_segm, src_offs;
u_int i2_segm, i2_offs;
u_long temp;
temp = (FP_SEG(src) << 4) + (FP_OFF(src));
src_segm = (u_int)(temp >> 4);
src_offs = (u_int)(temp & 0xffff);
temp = (FP_SEG(i2_dest) << 4) + (FP_OFF(i2_dest));
i2_segm = (u_int)(temp >> 4);
i2_offs = (u_int)(temp & 0xffff);
outport(0xffc8, cnt); // D0TC counter
outport(0xffc6, i2_segm); // D0DSTH=i2chip buffer segment
outport(0xffc4, i2_offs); // D0DSTL=i2chip buffer offset
outport(0xffc2, src_segm); /* D0SRCH=SP0RD */
outport(0xffc0, src_offs); /* D0SRCL=SP0RD */
// outport(0xfff8,0x050f); // PLLCON, 0203=10M,050f=40M, 051f=80MHz
// DMA0 mem-mem, 16-bit, unsync, Start moving data line below
outport(0xffca, 0xb60f); /* D0CON 1011 0110 0000 1111 */
while( inport(0xffc8) ); /* D0TC counter=0, DMA complete */
// outport(0xfff8,0x051f); // PLLCON, 0203=10M,050f=40M, 051f=80MHz
return( inport(0xffc8) ); // counter
}
/*
****************************************************************************************************
* Copies the receive buffer data of the W3100A to the system buffer.
*
* Description : Copies the receive buffer data of the W3100A to the system buffer.
* It is called from the recv()or recvfrom() function.
* Arguments : s - channel number
* src - receive buffer pointer of W3100A
* dst - system buffer pointer
* len - data size to copy
* Returns : copied data size
* Note : Internal Function
****************************************************************************************************
*/
u_int read_data(SOCKET s, u_int offset, u_char far * dst, u_int len)
{
u_int i, size, size1;
u_char far* src = (u_char far*)(MK_FP_WINDOW(RECV_DATA_BUF,
RBUFBASEADDRESS[s] + offset));
// src = (u_char far*)(MK_FP_WINDOW(RECV_DATA_BUF,
// 0));
if (len == 0)
{
WINDOW_RESTORE_BASE; // Needed whenever we do a call to MK_FP_WINDOW.
return 0;
}
if ((offset + len) > RSIZE[s])
{
size = (u_int)(RSIZE[s] - offset);
if (size > TERN_RDMA_THRES)
{
dma_read_i2chip(src, dst, size);
}
else
{
for (i = 0; i < size; i++)
{
*dst++ = READ_VALUE(src);
WINDOW_PTR_INC(src);
}
}
size1 = len - size;
src = (u_char far *)(MK_FP_WINDOW(RECV_DATA_BUF, (RBUFBASEADDRESS[s])));
if (size1 > TERN_RDMA_THRES)
{
dma_read_i2chip(src, dst, size);
}
else
{
for (i = 0; i < size1; i++)
{
*dst++ = READ_VALUE(src);
WINDOW_PTR_INC(src);
}
}
}
else
{
if (len > TERN_RDMA_THRES)
{
dma_read_i2chip(src, dst, size);
}
else
{
for (i = 0; i < len; i++)
{
*dst++ = READ_VALUE(src);
WINDOW_PTR_INC(src);
}
}
}
WINDOW_RESTORE_BASE; // Needed whenever we do a call to MK_FP_WINDOW.
return len;
}
/*
****************************************************************************************************
* Copies the system buffer data to the transmit buffer of the W3100A.
*
* Description : Copies the system buffer data to the transmit buffer of the W3100A.
* It is called from the send_in()or sendto_in() function.
* Arguments : s - channel number
* src - system buffer pointer
* dst - send buffer pointer of W3100A
* len - data size to copy
* Returns : copied data size
* Note : Internal Function
****************************************************************************************************
*/
u_int write_data(SOCKET s, u_char far * src, u_int offset, u_int len)
{
u_int i, size, size1;
u_char far* dst = (u_char far*)MK_FP_WINDOW(SEND_DATA_BUF,
SBUFBASEADDRESS[s] + offset);
if (len == 0)
{
WINDOW_RESTORE_BASE; // Needed whenever we do a call to MK_FP_WINDOW.
return 0;
}
if ((offset + len) > SSIZE[s])
{
size = (u_int)(SSIZE[s] - offset);
for (i = 0; i < size; i++)
{
WRITE_VALUE(dst, *src++);
WINDOW_PTR_INC(dst);
}
size1 = len - size;
dst = (u_char far *)(MK_FP_WINDOW(SEND_DATA_BUF, (SBUFBASEADDRESS[s])));
for (i = 0; i < size1; i++)
{
WRITE_VALUE(dst, *src++);
WINDOW_PTR_INC(dst);
}
}
else
{
for (i = 0; i < len; i++)
{
WRITE_VALUE(dst, *src++);
WINDOW_PTR_INC(dst);
}
}
WINDOW_RESTORE_BASE; // Needed whenever we do a call to MK_FP_WINDOW.
return len;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -