📄 socket.c
字号:
/*
********************************************************************************
*
* Copyright 2002, Vineyard Technologies, Inc.
*
* Filename : socket.c
* Programmer : Steve KyeongHyeon Lee
* Created : 2003/02/17
* Modified :
*
* Description : Driver API program of W3100A (Little Endian)
********************************************************************************
*/
#include "types.h"
#ifdef LANIF
/*
###############################################################################
File Include Section
###############################################################################
*/
#include <stdio.h>
#include <absacc.h>
#include "gio.h"
#include "socket.h"
#define FIX_PTR_CHANGE 1
/*
###############################################################################
Externs
###############################################################################
*/
/*
###############################################################################
Define Part
###############################################################################
*/
// Indirect Access Mode Register
#define FREG_IDM_OR 0xC000
#define FREG_IDM_AR0 0xC001
#define FREG_IDM_AR1 0xC002
#define FREG_IDM_DR 0xC003
// IDM_OR bits
#define IND_EN 0x80 // (1)Enable indirect bus I/F
#define LB 0x02 // Little(1) or Big Endian (0)
#define AUTO_INC 0x01 // Address Auto Increment(1)
void read_4reg(u16 shadow, u8* val, u16 addr);
void write_4reg(u8* val, u16 addr);
/*
###############################################################################
Indirect Mode Access API
###############################################################################
*/
void idminit(void)
{
XBYTE[FREG_IDM_OR] = IND_EN | AUTO_INC;
}
/*
###############################################################################
Indirect Mode Access API
###############################################################################
*/
void idmw(u16 addr, u8 val)
{
//XBYTE[FREG_IDM_OR] = IND_EN;
XBYTE[FREG_IDM_AR0] = (u8)(addr>>8);
XBYTE[FREG_IDM_AR1] = (u8)addr;
XBYTE[FREG_IDM_DR] = val;
}
/*
###############################################################################
Indirect Mode Access API
###############################################################################
*/
u8 idmr(u16 addr)
{
idata u8 val;
// xdata u8 val;
//XBYTE[FREG_IDM_OR] = IND_EN;
XBYTE[FREG_IDM_AR0] = (u8)(addr>>8);
XBYTE[FREG_IDM_AR1] = (u8)addr;
val = XBYTE[FREG_IDM_DR];
return val;
}
/*
###############################################################################
Indirect Mode Access API
###############################################################################
*/
xdata u8 idm_addr0;
xdata u8 idm_addr1;
void idm_save(void)
{
idm_addr0 = XBYTE[FREG_IDM_AR0];
idm_addr1 = XBYTE[FREG_IDM_AR1];
}
/*
###############################################################################
Indirect Mode Access API
###############################################################################
*/
void idm_restore(void)
{
//XBYTE[FREG_IDM_OR] = IND_EN;
XBYTE[FREG_IDM_AR0] = idm_addr0;
XBYTE[FREG_IDM_AR1] = idm_addr1;
}
/*
###############################################################################
Indirect Mode Access API
###############################################################################
*/
#ifdef DEBUG_IDM_AUTO
void idm_auto_inc_test(void)
{
xdata u16 addr;
lan_enable();
// set memory as test mode.
XBYTE[FREG_IDM_OR] = IND_EN; // | AUTO_INC;
XBYTE[FREG_IDM_AR0] = 0x00;
XBYTE[FREG_IDM_AR1] = 0x01;
XBYTE[FREG_IDM_DR] = 0x80;
// clear area 0x4000 to 0x5000 (offset)
addr=0x4000;
XBYTE[FREG_IDM_OR] = IND_EN; // | AUTO_INC;
for(addr=0x4000;addr<0x5000;addr++)
{
XBYTE[FREG_IDM_AR0] = (u8)(addr>>8);
XBYTE[FREG_IDM_AR1] = (u8) addr;
XBYTE[FREG_IDM_DR] = 0x00;
}
// set auto increment mode
addr = 0x4000;
XBYTE[FREG_IDM_AR0] = (u8)(addr>>8);
XBYTE[FREG_IDM_AR1] = (u8) addr;
XBYTE[FREG_IDM_OR] = IND_EN | AUTO_INC;
// write 0xaa into 0x4000 -- 0x400f
for(;addr<0x4010;addr++)
{
XBYTE[FREG_IDM_DR] = 0xaa;
}
// skip writing 0x4010 -- 0x401f
addr = 0x4020;
XBYTE[FREG_IDM_AR0] = (u8)(addr>>8);
XBYTE[FREG_IDM_AR1] = (u8) addr;
// write 0xaa into 0x4020 -- 0x402f
for(;addr<0x4030;addr++)
{
XBYTE[FREG_IDM_DR] = 0xaa;
}
dv03_enable();
}
#endif
/*******************************************************************/
#define WAIT1US_40MHZ 10 // Wait loop factor value
#define WAIT1MS_40MHZ 10000 //100 //10000
#define MAX_SOCK_NUM 4 // Concurrent maxmium number of socket
#define I2CHIP_BASE 0x0000 //0x8000 // Address of W3100A
#define SEND_DATA_BUF 0x4000 //0xC000 // Internal Tx buffer address of W3100A
#define RECV_DATA_BUF 0x6000 //0xE000 // Internal Rx buffer address of W3100A
#define MAX_SEGMENT_SIZE 1460 // Maximum TCP transmission packet size
// Internal register set of W3100A
#define COMMAND(i) (I2CHIP_BASE + i)
#define INT_STATUS(i) (I2CHIP_BASE + 0x04 + i)
#define INT_REG (I2CHIP_BASE + 0x08)
#define INTMASK (I2CHIP_BASE + 0x09)
#define RESETSOCK (I2CHIP_BASE + 0x0A)
#define RX_PTR_BASE 0x10
#define RX_PTR_SIZE 0x0C
#define TX_PTR_BASE 0x40
#define TX_PTR_SIZE 0x0C
#define RX_WR_PTR(i,n) ((I2CHIP_BASE + RX_PTR_BASE + RX_PTR_SIZE * i)+n)
#define RX_RD_PTR(i,n) ((I2CHIP_BASE + RX_PTR_BASE + RX_PTR_SIZE * i + 0x04)+n)
#define RX_ACK_PTR(i,n) ((I2CHIP_BASE + TX_PTR_BASE + TX_PTR_SIZE * i + 0x08)+n)
#define TX_WR_PTR(i,n) ((I2CHIP_BASE + TX_PTR_BASE + TX_PTR_SIZE * i)+n)
#define TX_RD_PTR(i,n) ((I2CHIP_BASE + TX_PTR_BASE + TX_PTR_SIZE * i + 0x04)+n)
#define TX_ACK_PTR(i,n) ((I2CHIP_BASE + RX_PTR_BASE + RX_PTR_SIZE * i + 0x08)+n)
// Shadow Register Pointer Define
#define SHADOW_RXWR_PTR(i) (I2CHIP_BASE + 0x1E0 + 3 *i)
#define SHADOW_RXRD_PTR(i) (I2CHIP_BASE + 0x1E1 + 3 *i)
#define SHADOW_TXACK_PTR(i) (I2CHIP_BASE + 0x1E2 + 3 *i)
#define SHADOW_TXWR_PTR(i) (I2CHIP_BASE + 0x1F0 + 3 *i)
#define SHADOW_TXRD_PTR(i) (I2CHIP_BASE + 0x1F1 + 3 *i)
#define SOCK_BASE 0xA0
#define SOCK_SIZE 0x18
#define SOCK_STATUS(i) (I2CHIP_BASE + SOCK_BASE + SOCK_SIZE * i)
#define OPT_PROTOCOL(i) (I2CHIP_BASE + SOCK_BASE + SOCK_SIZE * i + 0x01)
#define DST_HA_PTR(i) (I2CHIP_BASE + SOCK_BASE + SOCK_SIZE * i + 0x02)
#define DST_IP_PTR(i,n) ((I2CHIP_BASE + SOCK_BASE + SOCK_SIZE * i + 0x08)+n)
#define DST_PORT_PTR(i,n) ((I2CHIP_BASE + SOCK_BASE + SOCK_SIZE * i + 0x0C)+n)
#define SRC_PORT_PTR(i,n) ((I2CHIP_BASE + SOCK_BASE + SOCK_SIZE * i + 0x0E)+n)
#define IP_PROTOCOL(i) (I2CHIP_BASE + SOCK_BASE + SOCK_SIZE * i + 0x10)
#define TOS(i) (I2CHIP_BASE + SOCK_BASE + SOCK_SIZE * i + 0x11) // Type of Service register
#define GATEWAY_PTR(n) (I2CHIP_BASE + 0x80 + n)
#define SUBNET_MASK_PTR(n) (I2CHIP_BASE + 0x84 + n)
#define SRC_HA_PTR(n) (I2CHIP_BASE + 0x88 + n)
#define SRC_IP_PTR(n) (I2CHIP_BASE + 0x8E + n)
#define TIMEOUT_PTR(n) (I2CHIP_BASE + 0x92 + n)
#define RETRYCNT_PTR (I2CHIP_BASE + 0x94)
#define RX_DMEM_SIZE (I2CHIP_BASE + 0x95)
#define TX_DMEM_SIZE (I2CHIP_BASE + 0x96)
/* SOCKET OPTION(Settting OPT_PROTOCOL REG.) */
#define SOCKOPT_BROADCAST 0x80 // Transmission, Reception of broadcasting data
#define SOCKOPT_NDTIMEOUT 0x40 // Setting timeout
#define SOCKOPT_NDACK 0x20 // Setting No Delayed Ack(TCP)
#define SOCKOPT_SWS 0x10 // Setting Silly Window Syndrome(TCP)
/* OPTION(Setting OPT_PROTOCOL REG.) for MAC LAYER RAW MODE */
#define MACLOPT_RXERR 0x80 // Setting reception of error packet
#define MACLOPT_BROADCAST 0x40 // Setting reception of broadcast packet
#define MACLOPT_PROMISC 0x20 // Setting reception of promiscuous packet
/* Command variables */
#define CSYS_INIT 0x01 // To set up network information(mac address, gateway address, subnet mask, source ip)
#define CSOCK_INIT 0x02 // To initialize socket
#define CCONNECT 0x04 // To establish connection as tcp client mode
#define CLISTEN 0x08 // To wait for connection request as tcp server mode
#define CCLOSE 0x10 // To terminate connection
#define CSEND 0x20 // To send data
#define CRECV 0x40 // To receive data
#define CSW_RESET 0x80 // To do software reset
/*
###############################################################################
Static function prototypes
###############################################################################
*/
void initseqnum(SOCKET s);
char listen(SOCKET s, u8 * addr, u16 * port);
u16 select(SOCKET s, u8 func);
char connect(SOCKET s, u8 * addr, u16 port);
u16 sendto_in(SOCKET , const u8 *, u16, u8 flag);
int send_in(SOCKET s, u8 * buf, u16 len, u8 flag, u8 isTcp);
u16 read_data(SOCKET s, u8 * src, u8 * dst, u16 len);
u16 write_data(SOCKET s, u8 * src, u8 * dst, u16 len);
char reset_sock(SOCKET s);
volatile void wait_1us(int i);
volatile void wait_1ms(int i);
void enable(void);
void disable(void);
/*
###############################################################################
Local Variable Declaration Section
###############################################################################
*/
u8 I_STATUS[4]={0,0,0,0}; // Store Interrupt Status according to channels
u16 Local_Port; // Source port number if a specific source port is not decided
union un_l2cval SEQ_NUM; // Set initial sequence number
u32 SMASK[MAX_SOCK_NUM]; // Variable to store MASK of Tx in each channel, on setting dynamic memory size.
u32 RMASK[MAX_SOCK_NUM]; // Variable to store MASK of Rx in each channel, on setting dynamic memory size.
int SSIZE[MAX_SOCK_NUM]; // Maximun Tx memory size by each channel
int RSIZE[MAX_SOCK_NUM]; // Maximun Rx memory size by each channel
u16 SBUFBASEADDRESS[MAX_SOCK_NUM]; // Maximun Tx memory base address by each channel
u16 RBUFBASEADDRESS[MAX_SOCK_NUM]; // Maximun Rx memory base address by each channel
u8 w3100a_intrrupt_mask = 0;
u8 bufaddr_h = 0x00;
u8 bufaddr_l = 0x00;
union un_l2cval tx_wr_ptr_save;
u8 in_w3100a_intr = 0;
/*
###############################################################################
Function Implementation Section
###############################################################################
*/
void SOCK_access_mode(void)
{
lan_enable();
idminit();
dv03_enable();
}
/*
********************************************************************************
* Interrupt handling function of the W3100A
*
* Description :
* Stores the status information that each function waits for in the global
* variable I_STATUS for transfer.
* I_STATUS stores the interrupt status value for each channel.
* Arguments : None
* Returns : interrupt status register value
* Note : Internal Function
********************************************************************************
*/
#ifdef DEBUG_CTRL_RX_CNT
xdata u16 gv_socket_ctrl_rx_cnt = 0;
#endif
void SOCK_ISR_W3100A(u8* status)// using 3
{
u8 Tstatus;
lan_enable(); // To access W3100A
*status = Tstatus = idmr(INT_REG);
// Control Channel Status Change
if (Tstatus & 0x01) { // channel 0 interrupt(sysinit, sockinit, established, closed, timeout, send_ok, recv_ok)
I_STATUS[0] = idmr(INT_STATUS(0)); // & ~(SSEND_OK|SRECV_OK); // No checking tx rx ok interrupt
//if(I_STATUS[0]==0x00) // if tx or rx interrupt
// *status &= 0xFE; // clear channel 0 interrupt status bits
idmw(INT_REG, 0x01); // clear interrupt status
}
// Video Channel Status Change
if (Tstatus & 0x02) { // channel 1 interrupt(sysinit, sockinit, established, closed, timeout, send_ok, recv_ok)
I_STATUS[1] = idmr(INT_STATUS(1)) & ~(SSEND_OK|SRECV_OK); // No checking tx rx ok interrupt
if(I_STATUS[1]==0x00) // if tx or rx interrupt
*status &= 0xFD; // clear channel 1 interrupt status bits
idmw(INT_REG, 0x02); // clear interrupt status
}
// Control Channel Rx packets
if (Tstatus & 0x10) { // channel 0 receive interrupt
#ifdef DEBUG_CTRL_RX_CNT
gv_socket_ctrl_rx_cnt++;
#endif
idmw(INT_REG, 0x10);
}
// Video Channel Rx packets -- never happen
if (Tstatus & 0x20) { // channel 1 receive interrupt
idmw(INT_REG, 0x20);
}
}
/*
*********************************************************************************************************
* W3100A Initialization Function
*
* Description: Reset of W3100A S/W and Registeration of i386 interrupt
* Arguments : None.
* Returns : None.
* Note :
*********************************************************************************************************
*/
void SOCK_softreset_W3100A(u32 seqnum)
{
/*
xdata u16 addr;
xdata u16 size;
*/
lan_enable();
Local_Port = 1000; // This default value will be set if you didn't designate it when you create
// a socket. If you don't designate port number and create a socket continuously,
// the port number will be assigned with incremented by one to Local_Port
SEQ_NUM.lVal = seqnum; //4294967293;// Sets the initial SEQ# to be used for TCP communication. (It should be ramdom
// value)
idmw(COMMAND(0), CSW_RESET); // Software RESET
dv03_enable();
}
/*
********************************************************************************
* W3100A initialization function
*
* Description :
* Sets the Tx, Rx memory size by each channel, source MAC, source IP, gateway, and subnet mask
* to be used by the W3100A to the designated values.
* May be called when reflecting modified network information or Tx, Rx memory size on the W3100A
* Include Ping Request for ARP update (In case that a device embedding W3100A is directly connected to Router)
* Arguments : sbufsize - Tx memory size (00 - 1KByte, 01- 2KBtye, 10 - 4KByte, 11 - 8KByte)
* bit 1-0 : Tx memory size of channel #0
* bit 3-2 : Tx memory size of channel #1
* bit 5-4 : Tx memory size of channel #2
* bit 7-6 : Tx memory size of channel #3
* rbufsize - Rx memory size (00 - 1KByte, 01- 2KBtye, 10 - 4KByte, 11 - 8KByte)
* bit 1-0 : Rx memory size of channel #0
* bit 3-2 : Rx memory size of channel #1
* bit 5-4 : Rx memory size of channel #2
* bit 7-6 : Rx memory size of channel #3
* Returns : None
* Note : API Function
* Maximum memory size for Tx, Rx in W3100A is 8KBytes,
* In the range of 8KBytes, the memory size could be allocated dynamically by each channel
* Be attentive to sum of memory size shouldn't exceed 8Kbytes
* and to data transmission and receiption from non-allocated channel may cause some problems.
* If 8KBytes memory already is assigned to centain channel, other 3 channels couldn't be used, for there's no available memory.
* If two 4KBytes memory are assigned to two each channels, other 2 channels couldn't be used, for there's no available memory.
* [Example of memory assignment]
* sbufsize => 00000011, rbufsize => 00000011 : Assign 8KBytes for Tx and Rx to channel #0, Cannot use channel #1,#2,#3
* sbufsize => 00001010, rbufsize => 00001010 : Assign 4KBytes for Tx and Rx to each channel #0,#1 respectively. Cannot use channel #2,#3
* sbufsize => 01010101, rbufsize => 01010101 : Assign 2KBytes for Tx and Rx to each all channels respectively.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -