- refactored network

git-svn-id: http://moon:8086/svn/mips@204 a8ebac50-d88d-4704-bea3-6648445a41b3
This commit is contained in:
2021-11-23 19:29:51 +00:00
parent 2b04dc86da
commit 794bd38593
20 changed files with 1 additions and 1 deletions
+70
View File
@@ -0,0 +1,70 @@
// -------------------------------------------------------------------------
// ethernet.c
//
// 21.12.2003, J. Ahrensfeld
//
// -------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include "libsys.h"
#include "ethernet.h"
#include "arp.h"
#define ARP_DGRAM_SIZE 46
// -------------------------------------------------------------------------
void ArpRequest(packet_t *pPacket, uint8_t *eth_addr_src, uint8_t *inet_addr_src, uint8_t *eth_addr_dst, uint8_t *inet_addr_dst)
{
ARP *pARP;
pARP = (ARP*)Eth_pkt_buffer_get(pPacket);
memset(pARP, 0, sizeof(ARP));
// Make ARP request
memcpy(pARP->inet_addr_src, inet_addr_src, 4);
memcpy(pARP->inet_addr_dst, inet_addr_dst, 4);
memcpy(pARP->eth_addr_src, eth_addr_src, 6);
memcpy(pARP->eth_addr_dst, eth_addr_dst, 6);
pARP->hw_type = TYPE_HW_ETH10;
pARP->proto_type = TYPE_PROTO_IP;
pARP->opcode = ARP_REQUEST;
pARP->hw_size = 6;
pARP->proto_size = 4;
// Send it
Eth_pkt_append(pPacket, sizeof(ARP));
}
void ArpReply(packet_t *pPacket, uint8_t *eth_addr_src, uint8_t *inet_addr_src, uint8_t *eth_addr_dst, uint8_t *inet_addr_dst)
{
ARP *pARP;
pARP = (ARP*)Eth_pkt_buffer_get(pPacket);
memset(pARP, 0, sizeof(ARP));
// Make ARP reply
memcpy(pARP->inet_addr_src, inet_addr_src, 4);
memcpy(pARP->inet_addr_dst, inet_addr_dst, 4);
memcpy(pARP->eth_addr_src, eth_addr_src, 6);
memcpy(pARP->eth_addr_dst, eth_addr_dst, 6);
pARP->hw_type = TYPE_HW_ETH10;
pARP->proto_type = TYPE_PROTO_IP;
pARP->opcode = ARP_REPLY;
pARP->hw_size = 6;
pARP->proto_size = 4;
// Send it
Eth_pkt_append(pPacket, sizeof(ARP));
}
+34
View File
@@ -0,0 +1,34 @@
// -------------------------------------------------------------------------
// arp.h
//
// 21.12.2003, J. Ahrensfeld
//
// -------------------------------------------------------------------------
#ifndef ARP_H
#define ARP_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
// -------------------------------------------------------------------------
typedef struct _sARP
{
uint16_t hw_type, proto_type;
uint8_t hw_size, proto_size;
uint16_t opcode;
uint8_t eth_addr_src[6], inet_addr_src[4];
uint8_t eth_addr_dst[6], inet_addr_dst[4];
uint8_t padding[18];
} __attribute__ ((__packed__)) ARP;
// -------------------------------------------------------------------------
void ArpRequest(packet_t *pPacket, uint8_t *eth_addr_src, uint8_t *inet_addr_src, uint8_t *eth_addr_dst, uint8_t *inet_addr_dst);
void ArpReply(packet_t *pPacket, uint8_t *eth_addr_src, uint8_t *inet_addr_src, uint8_t *eth_addr_dst, uint8_t *inet_addr_dst);
// -------------------------------------------------------------------------
#endif // ARP_H
+155
View File
@@ -0,0 +1,155 @@
// -------------------------------------------------------------------------
// ethernet.c
//
// 21.12.2003, J. Ahrensfeld
//
// -------------------------------------------------------------------------
#include "libsys.h"
#include "ethernet.h"
#include "ipv4.h"
#include "udp.h"
#include "dhcp.h"
#include "string.h"
const char hostname[] = "ML-402";
// -------------------------------------------------------------------------
// Testing
void DHCP_request_send(packet_t *pPacket, uint32_t dhcp_msg_type, uint8_t *mac_addr_src, uint8_t *inet_addr_src, uint8_t *inet_addr_dst, DHCP *pLast)
{
uint16_t sum;
DHCP *pDHCP;
uint8_t *pData;
dhcp_opt_hdr_t *pOpt_hdr;
uint32_t size, pos, magic = 0x63825363;
pDHCP = (DHCP*)UDP_create(pPacket, inet_addr_src, 68, inet_addr_dst, 67, NULL, sizeof(DHCP));
memset(pDHCP, 0, sizeof(DHCP));
pDHCP->op = DHCP_BOOTREQUEST;
pDHCP->htype = TYPE_HW_ETH10;
pDHCP->hlen = 6;
pDHCP->hops = 0;
pDHCP->secs = 0;
pDHCP->flags = 0;
memcpy(pDHCP->chaddr, mac_addr_src, pDHCP->hlen);
switch(dhcp_msg_type)
{
case DHCP_MSG_DHCPDISCOVER:
pDHCP->xid = (uint32_t)rand();
// Options
pos = 0;
size = sizeof(magic);
memcpy(&pDHCP->options[pos], &magic, size);
pos += size;
// Set msg type
size = sizeof(dhcp_opt_hdr_t);
pOpt_hdr = (dhcp_opt_hdr_t*)&pDHCP->options[pos];
pOpt_hdr->code = DHCP_OPT_MSGTYPE;
pOpt_hdr->len = 1;
pos += size;
size = pOpt_hdr->len;
pDHCP->options[pos] = dhcp_msg_type;
pos += size;
// Set client ID
size = sizeof(dhcp_opt_hdr_t);
pOpt_hdr = (dhcp_opt_hdr_t*)&pDHCP->options[pos];
pOpt_hdr->code = DHCP_OPT_CLIENTID;
pOpt_hdr->len = 6;
pos += size;
size = pOpt_hdr->len;
memcpy(&pDHCP->options[pos], mac_addr_src, size);
pos += size;
// Set client name
size = sizeof(dhcp_opt_hdr_t);
pOpt_hdr = (dhcp_opt_hdr_t*)&pDHCP->options[pos];
pOpt_hdr->code = DHCP_OPT_HOSTNAME;
pOpt_hdr->len = strlen(hostname);
pos += size;
size = pOpt_hdr->len;
memcpy(&pDHCP->options[pos], hostname, size);
pos += size;
pDHCP->options[pos] = DHCP_OPT_END;
break;
case DHCP_MSG_DHCPREQUEST:
pDHCP->xid = pLast->xid;
// Options
pos = 0;
size = sizeof(magic);
memcpy(&pDHCP->options[pos], &magic, size);
pos += size;
// Set msg type
size = sizeof(dhcp_opt_hdr_t);
pOpt_hdr = (dhcp_opt_hdr_t*)&pDHCP->options[pos];
pOpt_hdr->code = DHCP_OPT_MSGTYPE;
pOpt_hdr->len = 1;
pos += size;
size = pOpt_hdr->len;
pDHCP->options[pos] = dhcp_msg_type;
pos += size;
// Set client ID
size = sizeof(dhcp_opt_hdr_t);
pOpt_hdr = (dhcp_opt_hdr_t*)&pDHCP->options[pos];
pOpt_hdr->code = DHCP_OPT_CLIENTID;
pOpt_hdr->len = 6;
pos += size;
size = pOpt_hdr->len;
memcpy(&pDHCP->options[pos], mac_addr_src, size);
pos += size;
// Set client name
size = sizeof(dhcp_opt_hdr_t);
pOpt_hdr = (dhcp_opt_hdr_t*)&pDHCP->options[pos];
pOpt_hdr->code = DHCP_OPT_HOSTNAME;
pOpt_hdr->len = strlen(hostname);
pos += size;
size = pOpt_hdr->len;
memcpy(&pDHCP->options[pos], hostname, size);
pos += size;
// Set requested IP address
size = sizeof(dhcp_opt_hdr_t);
pOpt_hdr = (dhcp_opt_hdr_t*)&pDHCP->options[pos];
pOpt_hdr->code = DHCP_OPT_REQIP;
pOpt_hdr->len = 4;
pos += size;
size = pOpt_hdr->len;
memcpy(&pDHCP->options[pos], pLast->yiaddr, size);
pos += size;
pDHCP->options[pos] = DHCP_OPT_END;
break;
default:
break;
}
pData = (uint8_t*)Eth_pkt_append(pPacket, sizeof(DHCP));
}
+59
View File
@@ -0,0 +1,59 @@
// -------------------------------------------------------------------------
// ipv4.h
//
// 21.12.2003, J. Ahrensfeld
//
// -------------------------------------------------------------------------
#ifndef DHCP_H
#define DHCP_H
#include "libsys.h"
#include "ethernet.h"
// -------------------------------------------------------------------------
typedef struct _sDHCP
{
uint8_t op, htype, hlen, hops;
uint32_t xid;
uint16_t secs, flags;
uint8_t ciaddr[4];
uint8_t yiaddr[4];
uint8_t siaddr[4];
uint8_t giaddr[4];
uint8_t chaddr[16];
uint8_t sname[64];
uint8_t file[128];
uint8_t options[312];
} __attribute__ ((__packed__)) DHCP;
#define DHCP_BOOTREQUEST 1 // request.
#define DHCP_BOOTREPLY 2 // reply.
typedef struct _sdhcp_opt_hdr_t
{
uint8_t code, len;
} __attribute__ ((__packed__)) dhcp_opt_hdr_t;
#define DHCP_OPT_HOSTNAME 12
#define DHCP_OPT_REQIP 50
#define DHCP_OPT_MSGTYPE 53
#define DHCP_OPT_SERVERID 54
#define DHCP_OPT_CLIENTID 61
#define DHCP_OPT_END 255
#define DHCP_MSG_DHCPDISCOVER 1
#define DHCP_MSG_DHCPOFFER 2
#define DHCP_MSG_DHCPREQUEST 3
#define DHCP_MSG_DHCPDECLINE 4
#define DHCP_MSG_DHCPACK 5
#define DHCP_MSG_DHCPNAK 6
#define DHCP_MSG_DHCPRELEASE 7
// -------------------------------------------------------------------------
void DHCP_request_send(packet_t *pPacket, uint32_t dhcp_msg_type, uint8_t *mac_addr_src, uint8_t *inet_addr_src, uint8_t *inet_addr_dst, DHCP *pLast);
// -------------------------------------------------------------------------
#endif // DHCP_H
+131
View File
@@ -0,0 +1,131 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <libsys/libsys.h>
void EMAC_TX_commit(void)
{
volatile uint32_t *pEmac_ctrl = (uint32_t*)SYS_EMAC_TX_CTRL;
volatile uint32_t *pEmac_size = (uint32_t*)SYS_EMAC_TX_SIZE;
*pEmac_ctrl |= EMAC_TX_CTRL_PKT_COMMIT;
}
void EMAC_TX_alloc(uint32_t size)
{
volatile uint32_t *pEmac_ctrl = (uint32_t*)SYS_EMAC_TX_CTRL;
volatile uint32_t *pEmac_size = (uint32_t*)SYS_EMAC_TX_SIZE;
while(*pEmac_ctrl & EMAC_TX_STAT_PKT_ALLOC_BSY);
*pEmac_size = size;
*pEmac_ctrl |= EMAC_TX_CTRL_PKT_ALLOC;
while(*pEmac_ctrl & EMAC_TX_STAT_PKT_ALLOC_BSY);
}
uint32_t EMAC_TX_is_avail(void)
{
volatile uint32_t *pEmac_ctrl = (uint32_t*)SYS_EMAC_TX_CTRL;
volatile uint32_t *pEmac_size = (uint32_t*)SYS_EMAC_TX_SIZE;
while(*pEmac_ctrl & EMAC_TX_STAT_PKT_ALLOC_BSY);
return (*pEmac_ctrl & EMAC_TX_STAT_PKT_ARMED) == EMAC_TX_STAT_PKT_ARMED;
}
uint32_t EMAC_TX_is_idle(void)
{
volatile uint32_t *pEmac_ctrl = (uint32_t*)SYS_EMAC_TX_CTRL;
volatile uint32_t *pEmac_size = (uint32_t*)SYS_EMAC_TX_SIZE;
return (*pEmac_ctrl & EMAC_TX_STAT_PKT_DONE) == EMAC_TX_STAT_PKT_DONE;
}
void EMAC_TX_reset(void)
{
volatile uint32_t *pEmac_ctrl = (uint32_t*)SYS_EMAC_TX_CTRL;
volatile uint32_t *pEmac_size = (uint32_t*)SYS_EMAC_TX_SIZE;
*pEmac_ctrl = EMAC_TX_CTRL_RESET | EMAC_TX_CTRL_FCS_APPEND;
while(*pEmac_ctrl & EMAC_TX_CTRL_RESET);
}
uint32_t EMAC_RX_is_avail(void)
{
volatile uint32_t *pEmac_ctrl = (uint32_t*)SYS_EMAC_RX_CTRL;
volatile uint32_t *pEmac_size = (uint32_t*)SYS_EMAC_RX_SIZE;
return (*pEmac_ctrl & EMAC_RX_STAT_PKT_AVAIL) == EMAC_RX_STAT_PKT_AVAIL;
}
void EMAC_RX_request(void)
{
volatile uint32_t *pEmac_ctrl = (uint32_t*)SYS_EMAC_RX_CTRL;
volatile uint32_t *pEmac_size = (uint32_t*)SYS_EMAC_RX_SIZE;
*pEmac_ctrl = (*pEmac_ctrl & ~EMAC_RX_CTRL_PKT_FREE) | EMAC_RX_CTRL_PKT_REQ;
}
uint32_t EMAC_RX_is_valid(void)
{
volatile uint32_t *pEmac_ctrl = (uint32_t*)SYS_EMAC_RX_CTRL;
volatile uint32_t *pEmac_size = (uint32_t*)SYS_EMAC_RX_SIZE;
return (*pEmac_ctrl & EMAC_RX_STAT_PKT_VALID) == EMAC_RX_STAT_PKT_VALID;
}
void EMAC_RX_free(void)
{
volatile uint32_t *pEmac_ctrl = (uint32_t*)SYS_EMAC_RX_CTRL;
volatile uint32_t *pEmac_size = (uint32_t*)SYS_EMAC_RX_SIZE;
*pEmac_ctrl = (*pEmac_ctrl & ~EMAC_RX_CTRL_PKT_REQ) | EMAC_RX_CTRL_PKT_FREE;
}
void EMAC_RX_reset(void)
{
volatile uint32_t *pEmac_ctrl = (uint32_t*)SYS_EMAC_RX_CTRL;
volatile uint32_t *pEmac_size = (uint32_t*)SYS_EMAC_RX_SIZE;
*pEmac_ctrl = EMAC_RX_CTRL_RESET | EMAC_RX_CTRL_FCS_CHECK;
while(*pEmac_ctrl & EMAC_RX_CTRL_RESET);
}
uint32_t EMAC_RX_get_size(void)
{
volatile uint32_t *pEmac_ctrl = (uint32_t*)SYS_EMAC_RX_CTRL;
volatile uint32_t *pEmac_size = (uint32_t*)SYS_EMAC_RX_SIZE;
return *pEmac_size;
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef EMAC_H
#define EMAC_H
#include <sys/types.h>
#include <libsys/libsys.h>
void EMAC_TX_commit(void);
void EMAC_TX_alloc(uint32_t size);
uint32_t EMAC_TX_is_avail(void);
uint32_t EMAC_TX_is_idle(void);
void EMAC_TX_reset(void);
uint32_t EMAC_RX_is_avail(void);
void EMAC_RX_request(void);
uint32_t EMAC_RX_is_valid(void);
void EMAC_RX_free(void);
void EMAC_RX_reset(void);
uint32_t EMAC_RX_get_size(void);
#endif // EMAC_H
+154
View File
@@ -0,0 +1,154 @@
// -------------------------------------------------------------------------
// ethernet.c
//
// 21.12.2003, J. Ahrensfeld
//
// -------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include "libsys.h"
#include "ethernet.h"
// -------------------------------------------------------------------------
uint32_t eth_crc32(uint32_t crc, uint8_t *pData, uint32_t len)
{
uint32_t n;
uint32_t crc_table[] =
{
0x4DBDF21C, 0x500AE278, 0x76D3D2D4, 0x6B64C2B0,
0x3B61B38C, 0x26D6A3E8, 0x000F9344, 0x1DB88320,
0xA005713C, 0xBDB26158, 0x9B6B51F4, 0x86DC4190,
0xD6D930AC, 0xCB6E20C8, 0xEDB71064, 0xF0000000
};
for (n=0; n < len; n++)
{
crc = (crc >> 4) ^ crc_table[(crc ^ (pData[n] >> 0)) & 0x0F]; /* lower nibble */
crc = (crc >> 4) ^ crc_table[(crc ^ (pData[n] >> 4)) & 0x0F]; /* upper nibble */
}
return crc;
}
// -------------------------------------------------------------------------
void EthInit(void)
{
}
uint8_t *Eth_pkt_create(packet_t *pPacket, uint16_t proto, uint8_t *pHwAddr_src, uint8_t *pHwAddr_dst)
{
eth_hdr_t *pEth_hdr;
pPacket->pData = pPacket->pkt_buf;
pEth_hdr = (eth_hdr_t*)pPacket->pData;
memcpy(pEth_hdr->eth_addr_src, pHwAddr_src, 6);
memcpy(pEth_hdr->eth_addr_dst, pHwAddr_dst, 6);
pEth_hdr->proto = proto;
pPacket->size = sizeof(eth_hdr_t);
pPacket->pData += pPacket->size;
return pPacket->pData;
}
uint8_t *Eth_pkt_append(packet_t *pPacket, uint32_t size)
{
pPacket->size += size;
pPacket->pData += size;
return pPacket->pData;
}
uint8_t *Eth_pkt_buffer_get(packet_t *pPacket)
{
return pPacket->pData;
}
uint32_t Eth_pkt_send(packet_t *pPacket)
{
volatile uint32_t *pEmac_ctrl = (uint32_t*)SYS_EMAC_TX_CTRL;
volatile uint32_t *pEmac_size = (uint32_t*)SYS_EMAC_TX_SIZE;
volatile uint32_t *pEmac_data = (uint32_t*)SYS_EMAC_DATA;
uint32_t *pData = (uint32_t*)pPacket->pkt_buf;
uint32_t i, num_words, num_bytes;
num_bytes = pPacket->size;
do
{
EMAC_TX_alloc(num_bytes);
} while(!EMAC_TX_is_avail());
num_words = num_bytes >> 2;
if (num_bytes & 3)
num_words++;
while(num_words >= 8)
{
*pEmac_data = pData[i+0];
*pEmac_data = pData[i+1];
*pEmac_data = pData[i+2];
*pEmac_data = pData[i+3];
*pEmac_data = pData[i+4];
*pEmac_data = pData[i+5];
*pEmac_data = pData[i+6];
*pEmac_data = pData[i+7];
i += 8;
num_words -= 8;
}
for (i=0; i < num_words; i++)
{
*pEmac_data = pData[i];
}
EMAC_TX_commit();
return num_bytes;
}
uint32_t Eth_pkt_recv(uint8_t *pData)
{
volatile uint32_t *pEmac_ctrl = (uint32_t*)SYS_EMAC_RX_CTRL;
volatile uint32_t *pEmac_size = (uint32_t*)SYS_EMAC_RX_SIZE;
volatile uint32_t *pEmac_data = (uint32_t*)SYS_EMAC_DATA;
uint32_t crc32, i, num_words, num_bytes, pkt_size;
if(EMAC_RX_is_avail())
{
if (EMAC_RX_is_valid())
{
// if ((*pEmac_ctrl & EMAC_RX_STAT_PKT_BCAST))
// {
// printf("Packet broad cast!\n");
// }
num_bytes = EMAC_RX_get_size();
num_words = num_bytes >> 2;
if (num_bytes & 3)
num_words++;
EMAC_RX_request();
for (i=0; i < num_words; i++)
((uint32_t*)pData)[i] = *pEmac_data;
EMAC_RX_free();
}
}
}
uint16_t htons(uint16_t a)
{
return HTONS(a);
}
+74
View File
@@ -0,0 +1,74 @@
// -------------------------------------------------------------------------
// ethernet.h
//
// 21.12.2003, J. Ahrensfeld
//
// -------------------------------------------------------------------------
#ifndef ETHERNET_H
#define ETHERNET_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include "libsys.h"
#define ETH_PACKET_MIN_SIZE 64
#define ETH_PACKET_MAX_SIZE 1500
// -------------------------------------------------------------------------
#define ARP_REQUEST 0x0001
#define ARP_REPLY 0x0002
#define TYPE_HW_ETH10 0x0001
#define TYPE_HW_ETH3 0x0002
#define TYPE_HW_AX25 0x0003
#define TYPE_HW_TKRNG 0x0004
#define TYPE_HW_CHAOS 0x0005
#define TYPE_HW_IEEE 0x0006
#define TYPE_HW_ARCNET 0x0007
#define TYPE_PROTO_IP 0x0800
#define TYPE_PROTO_X75 0x0801
#define TYPE_PROTO_NBS 0x0802
#define TYPE_PROTO_ECMA 0x0803
#define TYPE_PROTO_CHAOS 0x0804
#define TYPE_PROTO_X25 0x0805
#define TYPE_PROTO_ARP 0x0806
#define TYPE_PROTO_XNS 0x0807
#define TYPE_PROTO_LOOP 0x9000
#define HTONS(n) ((((uint16_t)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8))
// -------------------------------------------------------------------------
typedef struct _seth_hdr_t
{
uint8_t eth_addr_dst[6], eth_addr_src[6];
uint16_t proto;
} __attribute__ ((__packed__)) eth_hdr_t;
typedef struct _spacket_t
{
uint8_t pkt_buf[1516];
uint16_t size;
uint8_t *pData;
} packet_t;
// -------------------------------------------------------------------------
void EthInit(void);
uint8_t *Eth_pkt_create(packet_t *pPacket, uint16_t proto, uint8_t *pHwAddr_src, uint8_t *pHwAddr_dst);
uint8_t *Eth_pkt_append(packet_t *pPacket, uint32_t size);
uint8_t *Eth_pkt_buffer_get(packet_t *pPacket);
uint32_t Eth_pkt_send(packet_t *pPacket);
uint32_t Eth_pkt_recv(uint8_t *pData);
uint16_t htons(uint16_t a);
// -------------------------------------------------------------------------
#endif // ETHERNET_H
+67
View File
@@ -0,0 +1,67 @@
// -------------------------------------------------------------------------
// ethernet.c
//
// 21.12.2003, J. Ahrensfeld
//
// -------------------------------------------------------------------------
#include "libsys.h"
#include "ethernet.h"
#include "ipv4.h"
#include "icmp.h"
#include "string.h"
// -------------------------------------------------------------------------
// Testing
void ICMPSendRequest(packet_t *pPacket, uint8_t *inet_addr_src, uint8_t *inet_addr_dst, uint8_t *icmp_payload, uint16_t len)
{
uint16_t sum;
ICMP *pICMP;
uint8_t *pData;
pICMP = (ICMP*)IPV4_create(pPacket, IP_TYPE_ICMP, sizeof(ICMP)+len, inet_addr_src, inet_addr_dst);
memset(pICMP, 0, sizeof(ICMP));
pICMP->type = ICMP_ECHO_REQUEST;
pICMP->icmp_code = 0x00;
pICMP->hdr_chksum = 0x0000;
pICMP->data_hdr[0]= 0x00; // Identifier
pICMP->data_hdr[1]= 0x00; // Sequence number
sum = IPv4ChkSum((uint16_t*)pICMP, 0, sizeof(ICMP));
sum = IPv4ChkSum((uint16_t*)icmp_payload, sum, len);
pICMP->hdr_chksum = ~sum;
pData = (uint8_t*)Eth_pkt_append(pPacket, sizeof(ICMP));
memcpy(pData, icmp_payload, len);
Eth_pkt_append(pPacket, len);
}
void ICMPSendReply(packet_t *pPacket, uint8_t *inet_addr_src, uint8_t *inet_addr_dst, ICMP *pHdr, uint8_t *icmp_payload, uint16_t len)
{
uint16_t sum;
ICMP *pICMP;
uint8_t *pData;
pICMP = (ICMP*)IPV4_create(pPacket, ICMP_ECHO_REPLY, sizeof(ICMP) + len, inet_addr_src, inet_addr_dst);
memcpy(pICMP, pHdr, sizeof(ICMP));
pICMP->type = ICMP_ECHO_REPLY;
pICMP->hdr_chksum = 0x0000;
sum = IPv4ChkSum((uint16_t*)pICMP, 0, sizeof(ICMP));
sum = IPv4ChkSum((uint16_t*)icmp_payload, sum, len);
pICMP->hdr_chksum = ~sum;
pData = (uint8_t*)Eth_pkt_append(pPacket, sizeof(ICMP));
memcpy(pData, icmp_payload, len);
Eth_pkt_append(pPacket, len);
}
+57
View File
@@ -0,0 +1,57 @@
// -------------------------------------------------------------------------
// ipv4.h
//
// 21.12.2003, J. Ahrensfeld
//
// -------------------------------------------------------------------------
#ifndef ICMP_H
#define ICMP_H
#include "libsys.h"
#include "ethernet.h"
// -------------------------------------------------------------------------
typedef struct _sICMP
{
uint8_t type;
uint8_t icmp_code;
uint16_t hdr_chksum;
uint16_t data_hdr[2];
} __attribute__ ((__packed__)) ICMP;
#define ICMP_ECHO_REPLY 0 // Echo reply.
#define ICMP_DST_UNREACH 3 // Destination unreachable.
#define ICMP_SRC_QUENCH 4 // Source quench.
#define ICMP_REDIRECT 5 // Redirect.
#define ICMP_ALT_HOST_ADDR 6 // Alternate Host Address.
#define ICMP_ECHO_REQUEST 8 // Echo request.
#define ICMP_ROUTER_ADVERTISE 9 // Router advertisement.
#define ICMP_ROUTER_SOLIC 10 // Router solicitation.
#define ICMP_TIME_EXCEEDED 11 // Time exceeded.
#define ICMP_PARAM_PROBLEM 12 // Parameter problem.
#define ICMP_TIMESTAMP_REQUEST 13 // Timestamp request.
#define ICMP_TIMESTAMP_REPLY 14 // Timestamp reply.
#define ICMP_INFO_REQUEST 15 // Information request.
#define ICMP_INFO_RPLY 16 // Information reply.
#define ICMP_ADDR_MASK_REQUEST 17 // Address mask request.
#define ICMP_ADDR_MASK_REPLY 18 // Address mask reply.
#define ICMP_TRACEROUTE 30 // Traceroute.
#define ICMP_CONV_ERROR 31 // Conversion error.
#define ICMP_MOB_HOST_REDIRECT 32 // Mobile Host Redirect.
#define ICMP_IPV6_WAY 33 // IPv6 Where-Are-You.
#define ICMP_IPV6_IAH 34 // IPv6 I-Am-Here.
#define ICMP_MOB_REG_REQUEST 35 // Mobile Registration Request.
#define ICMP_MOB_REG_REPLY 36 // Mobile Registration Reply.
#define ICMP_DOM_NAME_REQUEST 37 // Domain Name request.
#define ICMP_DOM_NAME_REPLY 38 // Domain Name reply.
#define ICMP_SKIP_ADP 39 // SKIP Algorithm Discovery Protocol.
#define ICMP_PHOTURIS 40 // Photuris, Security failures.
// -------------------------------------------------------------------------
void ICMPSendRequest(packet_t *pPacket, uint8_t *inet_addr_src, uint8_t *inet_addr_dst, uint8_t *icmp_payload, uint16_t len);
void ICMPSendReply(packet_t *pPacket, uint8_t *inet_addr_src, uint8_t *inet_addr_dst, ICMP *pICMP, uint8_t *icmp_payload, uint16_t len);
// -------------------------------------------------------------------------
#endif // ICMP_H
+65
View File
@@ -0,0 +1,65 @@
// -------------------------------------------------------------------------
// ethernet.c
//
// 21.12.2003, J. Ahrensfeld
//
// -------------------------------------------------------------------------
#include "libsys.h"
#include "ethernet.h"
#include "ipv4.h"
#include "string.h"
#define IPV4_HEADER_SIZE 20
// -------------------------------------------------------------------------
// Testing - not the final API
uint8_t *IPV4_create(packet_t *pPacket, uint16_t proto, uint16_t len, uint8_t *inet_addr_src, uint8_t *inet_addr_dst)
{
IPV4 *pIPv4_hdr;
pIPv4_hdr = (IPV4*)Eth_pkt_buffer_get(pPacket);
memset(pIPv4_hdr, 0, sizeof(IPV4));
memcpy(pIPv4_hdr->inet_addr_src, inet_addr_src, 4);
memcpy(pIPv4_hdr->inet_addr_dst, inet_addr_dst, 4);
pIPv4_hdr->ver_ihl = 0x45;
pIPv4_hdr->tos = 0x00;
pIPv4_hdr->len = sizeof(IPV4) + len;
pIPv4_hdr->id = 0x1234;
pIPv4_hdr->flag_foff = 0; //IPV4_FLAG_DF;
pIPv4_hdr->ttl = 0x10;
pIPv4_hdr->proto = proto;
pIPv4_hdr->hdr_chksum = 0x0000;
pIPv4_hdr->hdr_chksum = ~IPv4ChkSum((uint16_t*)pIPv4_hdr, 0, sizeof(IPV4));
// Send it
return Eth_pkt_append(pPacket, sizeof(IPV4));
}
// -------------------------------------------------------------------------
uint16_t IPv4ChkSum(uint16_t *pBuf, uint16_t acc, uint16_t len)
{
while(len > 1)
{
acc += *pBuf;
if(acc < *pBuf)
acc++;
++pBuf;
len -= 2;
}
/* add up any odd byte */
if(len == 1)
{
acc += htons(((uint16_t)(*(uint8_t *)pBuf)) << 8);
if(acc < htons(((uint16_t)(*(uint8_t *)pBuf)) << 8))
acc++;
}
return acc;
}
+58
View File
@@ -0,0 +1,58 @@
// -------------------------------------------------------------------------
// ipv4.h
//
// 21.12.2003, J. Ahrensfeld
//
// -------------------------------------------------------------------------
#ifndef IPV4_H
#define IPV4_H
#include "libsys.h"
#include "ethernet.h"
// -------------------------------------------------------------------------
typedef struct _sIPV4
{
uint8_t ver_ihl;
uint8_t tos;
uint16_t len;
uint16_t id;
uint16_t flag_foff;
uint8_t ttl;
uint8_t proto;
uint16_t hdr_chksum;
uint8_t inet_addr_src[4];
uint8_t inet_addr_dst[4];
} __attribute__ ((__packed__)) IPV4;
#define IP_TYPE_ICMP 0x01
#define IP_TYPE_TCP 0x06
#define IP_TYPE_UDP 0x11
#define IPV4_AMSK_PRECEDENCE 0x07
#define IPV4_TOS_LOW_DELAY 0x08
#define IPV4_TOS_HIGH_THRUPUT 0x10
#define IPV4_TOS_HIGH_REL 0x20
#define IPV4_AMSK_FLAG 0xE000
#define IPV4_AMSK_FOFF 0x1FFF
#define IPV4_FLAG_RES 0x8000
#define IPV4_FLAG_DF 0x4000
#define IPV4_FLAG_MF 0x2000
#define IPV4_PRECENCE_NETWORK_CTRL 0x07 // 111 - Network Control
#define IPV4_PRECENCE_INTERNET_CTRL 0x06 // 110 - Internetwork Control
#define IPV4_PRECENCE_CRITIC_ECP 0x05 // 101 - CRITIC/ECP
#define IPV4_PRECENCE_FLASH_OVERRIDE 0x04 // 100 - Flash Override
#define IPV4_PRECENCE_FLASH 0x03 // 011 - Flash
#define IPV4_PRECENCE_IMMEDIATE 0x02 // 010 - Immediate
#define IPV4_PRECENCE_PRIORITY 0x01 // 001 - Priority
#define IPV4_PRECENCE_ROUTINE 0x00 // 000 - Routine
// -------------------------------------------------------------------------
uint16_t IPv4ChkSum(uint16_t *pBuf, uint16_t acc, uint16_t len);
uint8_t *IPV4_create(packet_t *pPacket, uint16_t proto, uint16_t len, uint8_t *inet_addr_src, uint8_t *inet_addr_dst);
// -------------------------------------------------------------------------
#endif // IPV4_H
+194
View File
@@ -0,0 +1,194 @@
/** *******************************************************************************
*
* Project: Robotics library for the Autonomous Robotics Development Platform
* Port by: Jorge Sánchez de Nova jssdn (mail)_(at) kth.se
*
* NOTE: This code is based on the Xilinx XAPP1042.
*
* Description:
* Routines to control and display the status of a Marvell 88E1111 Ethernet PHY.
*
* Xilinx disclaimer below apply.
*
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
* SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR
* XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION
* AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION
* OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS
* IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* (c) Copyright 2008 Xilinx, Inc.
* All rights reserved.
*
******************************************************************************* **/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include "libsys.h"
//#include "errno.h"
#include "marvell_88e1111.h"
/*
* Pointers to functions which will read/write the PHY registers.
* These must be set with marvell_phy_setvectors() before any other functions
* in this file are called.
*/
static PhyWrite_t *PhyWrite_fp;
static PhyRead_t *PhyRead_fp;
/*
* marvell_phy_setvectors:
* initialize read/write vectors to the driver which will provide access
* to the PHY registers.
*/
void marvell_phy_setvectors (PhyRead_t *read_fp, PhyWrite_t *write_fp)
{
PhyWrite_fp = write_fp;
PhyRead_fp = read_fp;
}
/*
* marvell_phy_detected:
* Returns 0 if Marvell PHY detected at PhyAddress, otherwise returns
* -1.
*/
int marvell_phy_detected (void *phy_inst, uint32_t PhyAddress)
{
uint16_t val;
if (PhyRead_fp == NULL) {
printf("ERROR: PHY accessor vectors not set.\n");
return -1;
}
(*PhyRead_fp)(phy_inst, PhyAddress, MPHY_ID0_REG, &val);
if (val == MPHY_ID0_MARVELL_OUI) {
return 0;
}
return -1;
}
/*
* marvell_phy_set_1000mb_autoneg:
* Enable or disable the autonegotiation of 1000MB
*/
void marvell_phy_set_1000mb_autoneg (void *phy_inst, uint32_t PhyAddress, int Enable)
{
uint16_t val;
if ((PhyRead_fp == NULL) || (PhyWrite_fp == NULL)) {
printf("ERROR: PHY accessor vectors not set.\n\r");
return;
}
/*
* Change advertised capabilities
*/
(*PhyRead_fp)(phy_inst, PhyAddress, MPHY_1000BT_CONTROL_REG, &val);
if (Enable) {
val |= (MPHY_1000BT_CONTROL_ADV_1000BT_FD |
MPHY_1000BT_CONTROL_ADV_1000BT_HD);
} else {
val &= ~(MPHY_1000BT_CONTROL_ADV_1000BT_FD |
MPHY_1000BT_CONTROL_ADV_1000BT_HD);
}
(*PhyWrite_fp)(phy_inst, PhyAddress, MPHY_1000BT_CONTROL_REG, val);
/*
* Re-negotiate
*/
(*PhyRead_fp)(phy_inst, PhyAddress, MPHY_CONTROL_REG, &val);
val |= MPHY_CONTROL_RSTRT_AUTONEG;
(*PhyWrite_fp)(phy_inst, PhyAddress, MPHY_CONTROL_REG, val);
}
/*
* marvell_phy_link_status:
* Returns 0 if LINK is UP
* Returns -1 if LINK is DOWN
*/
int marvell_phy_link_status (void *phy_inst, uint32_t PhyAddress)
{
uint16_t val;
if (PhyRead_fp == NULL) {
printf("ERROR: PHY accessor vectors not set.\n\r");
return -1;
}
(*PhyRead_fp)(phy_inst, PhyAddress, MPHY_SPCFC_STATUS_REG, &val);
// printf("MPHY_SPCFC_STATUS_REG = %08X\n", val);
if (val & MPHY_SPCFC_STAT_LINK_RT) {
return 0;
}
return -1;
}
/*
* marvell_phy_display_status:
*/
void marvell_phy_display_status (void *phy_inst, uint32_t PhyAddress)
{
uint16_t val, speed_status;
if (PhyRead_fp == NULL) {
printf("ERROR: PHY accessor vectors not set.\n\r");
return;
}
(*PhyRead_fp)(phy_inst, PhyAddress, MPHY_SPCFC_STATUS_REG, &val);
if (val & MPHY_SPCFC_STAT_LINK_RT) {
printf("PHY Status: LINK_OK ");
} else {
printf("PHY Status: LINK_DOWN\n\r");
return;
}
speed_status = val >> MPHY_SPCFC_STAT_SPD_SHIFT;
switch (speed_status) {
case MPHY_SPCFC_STAT_SPD_RESVD:
printf("SPEED-RESERVED ");
break;
case MPHY_SPCFC_STAT_SPD_1000:
printf("SPEED-1000MB ");
break;
case MPHY_SPCFC_STAT_SPD_100:
printf("SPEED-100MB ");
break;
case MPHY_SPCFC_STAT_SPD_10:
printf("SPEED-10MB ");
break;
}
if (val & MPHY_SPCFC_STAT_DUPLEX) {
printf("FULL-DUPLEX ");
} else {
printf("HALF-DUPLEX ");
}
if (val & MPHY_SPCFC_STAT_SPD_DUP_RSLVD) {
printf("SPD_DPLX_RSLVD ");
} else {
printf("SPD_DPLX_NOT_RSLVD ");
}
if (val & MPHY_SPCFC_STAT_MDIX) {
printf("MDIX ");
} else {
printf("MDI ");
}
printf("\n");
}
+99
View File
@@ -0,0 +1,99 @@
#ifndef __MARVELL_88E1111_H__
#define __MARVELL_88E1111_H__
/** *******************************************************************************
*
* Project: Robotics library for the Autonomous Robotics Development Platform
* Port by: Jorge Sánchez de Nova jssdn (mail)_(at) kth.se
*
* NOTE: This code is based on the Xilinx XAPP1042.
*
* Description:
* Software to access PHY registers in a system where the serial control bus
* signals (MDC, MDIO) are connected to GPIO.
*
* Xilinx disclaimer below apply.
*
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
* SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR
* XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION
* AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION
* OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS
* IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* (c) Copyright 2008 Xilinx, Inc.
* All rights reserved.
*
******************************************************************************* **/
#define MPHY_CONTROL_REG 0
#define MPHY_CONTROL_LOOPBACK (1 << 14)
#define MPHY_CONTROL_AUTONEG (1 << 12)
#define MPHY_CONTROL_SPD_SEL_LSB (1 << 13)
#define MPHY_CONTROL_SPD_SEL_MSB (1 << 6)
#define MPHY_CONTROL_SPD_SEL_RSVD 3
#define MPHY_CONTROL_SPD_SEL_1000 2
#define MPHY_CONTROL_SPD_SEL_100 1
#define MPHY_CONTROL_SPD_SEL_10 0
#define MPHY_CONTROL_RSTRT_AUTONEG (1 << 9)
#define MPHY_CONTROL_DUPLEX (1 << 8)
#define MPHY_CONTROL_RESET (1 << 15)
#define MPHY_STATUS_REG 1
#define MPHY_STATUS_LINK (1 << 2)
#define MPHY_ID0_REG 2
#define MPHY_ID0_MARVELL_OUI 0x0141
#define MPHY_ID1_REG 3
#define MPHY_AUTONEG_ADV_REG 4
#define MPHY_AUTONEG_ADV_100TX_FD (1 << 8)
#define MPHY_AUTONEG_ADV_100TX_HD (1 << 7)
#define MPHY_AUTONEG_ADV_10TX_FD (1 << 6)
#define MPHY_AUTONEG_ADV_10TX_HD (1 << 5)
#define MPHY_1000BT_CONTROL_REG 9
#define MPHY_1000BT_CONTROL_ADV_1000BT_FD (1 << 9)
#define MPHY_1000BT_CONTROL_ADV_1000BT_HD (1 << 8)
#define MPHY_SPCFC_STATUS_REG 17
#define MPHY_SPCFC_STAT_SPD_SHIFT 14
#define MPHY_SPCFC_STAT_SPD_RESVD 3
#define MPHY_SPCFC_STAT_SPD_1000 2
#define MPHY_SPCFC_STAT_SPD_100 1
#define MPHY_SPCFC_STAT_SPD_10 0
#define MPHY_SPCFC_STAT_DUPLEX (1 << 13)
#define MPHY_SPCFC_STAT_SPD_DUP_RSLVD (1 << 11)
#define MPHY_SPCFC_STAT_LINK_RT (1 << 10)
#define MPHY_SPCFC_STAT_MDIX (1 << 6)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
/**************************** Type Definitions *******************************/
typedef void PhyWrite_t (void *phy_inst,
uint32_t PhyAddress,
uint32_t RegisterNum,
uint16_t PhyData);
typedef void PhyRead_t (void *phy_inst,
uint32_t PhyAddress,
uint32_t RegisterNum,
uint16_t *PhyDataPtr);
/************************** Function Prototypes ******************************/
void marvell_phy_setvectors(PhyRead_t *read_fp, PhyWrite_t *write_fp);
int marvell_phy_link_status(void *phy_inst, uint32_t PhyAddress);
void marvell_phy_display_status(void *phy_inst, uint32_t PhyAddress);
void marvell_phy_set_1000mb_autoneg(void *phy_inst, uint32_t PhyAddress, int Enable);
int marvell_phy_detected(void *phy_inst, uint32_t PhyAddress);
#endif
+313
View File
@@ -0,0 +1,313 @@
/** *******************************************************************************
*
* Project: Robotics library for the Autonomous Robotics Development Platform
* Port by: Jorge Sánchez de Nova jssdn (mail)_(at) kth.se
*
* NOTE: This code is based on the Xilinx XAPP1042 which, as noted by Xilinx, is based in Linux Kernel's
* drivers/net/fs_enet by Vitaly Bordug <vbordug@ru.mvista.com> and Pantelis Antoniou <panto@intracom.gr>
*
* Description:
* Software to access PHY registers in a system where the serial control bus
* signals (MDC, MDIO) are connected to GPIO.
*
* Xilinx disclaimer below apply.
*
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
* SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR
* XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION
* AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION
* OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS
* IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* (c) Copyright 2008 Xilinx, Inc.
* All rights reserved.
*
******************************************************************************* **/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#include "libsys.h"
#include "gpio.h"
#include "mii-bitbang.h"
/*
* mii_delay:
* Pause a bit.
*/
static void mii_delay (void)
{
/*
* Target MDC Frequency of 1/(2*1us) -- 500KHz
*/
usleep(1);
}
/*
* mdio_mode_output:
* set GPIO to OUTPUT
*/
static void mdio_mode_output(gpio_if_t *mii_gpio)
{
uint32_t dir;
gpio_get_dir(mii_gpio, GPIO_0_MASK_MDIO, GPIO_0_ALIGN_MDIO, &dir);
dir |= GPIO_0_MDIO_MDIO;
/* Set the direction for the MDIO signal to be output */
gpio_set_dir(mii_gpio, GPIO_0_MASK_MDIO, GPIO_0_ALIGN_MDIO, dir);
}
/*
* mdio_mode_input:
* set GPIO to INPUT
*/
static void mdio_mode_input(gpio_if_t *mii_gpio)
{
uint32_t dir;
gpio_get_dir(mii_gpio, GPIO_0_MASK_MDIO, GPIO_0_ALIGN_MDIO, &dir);
dir &= ~GPIO_0_MDIO_MDIO;
// printf("MDIO dir: 0x%x\n", dir);
/* Set the direction for the MDIO signal to be input */
gpio_set_dir(mii_gpio, GPIO_0_MASK_MDIO, GPIO_0_ALIGN_MDIO, dir);
}
/*
* mdio_read:
* Read the value presently driven by the PHY on the MDIO GPIO
*/
static int mdio_read(gpio_if_t *mii_gpio)
{
uint32_t data;
gpio_read_data(mii_gpio, GPIO_0_MASK_MDIO, GPIO_0_ALIGN_MDIO, &data);
// printf("MDIO read: 0x%x\n", data);
return (data & GPIO_0_MDIO_MDIO) != 0;
}
/*
* mdio_drive_bit:
* set the GPIO to drive the appropriate bit value on the MDIO pin
*/
static void mdio_drive_bit(gpio_if_t *mii_gpio, uint32_t value)
{
if (value)
gpio_write(mii_gpio, GPIO_0_MDIO_MDIO, GPIO_0_ALIGN_MDIO, GPIO_DATA_OFFSET, ~0);
else
gpio_write(mii_gpio, GPIO_0_MDIO_MDIO, GPIO_0_ALIGN_MDIO, GPIO_DATA_OFFSET, 0);
}
/*
* mdc_drive_bit:
* Toggle the MDC GPIO to the appropriate bit.
*/
static void mdc_drive_bit(gpio_if_t *mii_gpio, uint32_t value)
{
if (value)
gpio_write(mii_gpio, GPIO_0_MDIO_MDC, GPIO_0_ALIGN_MDIO, GPIO_DATA_OFFSET, ~0);
else
gpio_write(mii_gpio, GPIO_0_MDIO_MDC, GPIO_0_ALIGN_MDIO, GPIO_DATA_OFFSET, 0);
}
/*
* mdc_clk_1_0:
* Drive the MII Data Clock 1->0
*/
static void mdc_clk_1_0 (gpio_if_t *mii_gpio)
{
mii_delay();
mdc_drive_bit(mii_gpio, 1);
mii_delay();
mdc_drive_bit(mii_gpio, 0);
}
/*
* mii_send_address:
* Transmit the preamble, phy address, and phy register number on the bus.
*/
static void mii_send_address (gpio_if_t *mii_gpio, int read, uint8_t addr, uint8_t reg)
{
int i;
/*
* Send a 32 bit preamble of 1's
*/
mdio_mode_output(mii_gpio);
mdio_drive_bit(mii_gpio, 1); /* <<<<< */
for (i = 0; i < MII_PREABLE_BITS; i++) {
mdc_clk_1_0(mii_gpio);
}
/*
* send the start bit (01)
*/
mdio_drive_bit(mii_gpio, 0); /* <<<<< */
mdc_clk_1_0(mii_gpio);
mdio_drive_bit(mii_gpio, 1); /* <<<<< */
mdc_clk_1_0(mii_gpio);
/*
* send the opcode: read (10) write (10)
*/
mdio_drive_bit(mii_gpio, read); /* <<<<< */
mdc_clk_1_0(mii_gpio);
mdio_drive_bit(mii_gpio, !read); /* <<<<< */
mdc_clk_1_0(mii_gpio);
/*
* send the PHY address
*/
for (i = 0; i < MII_5ADDRESS_BITS; i++) {
if (addr & FIFTH_BIT_0x10) {
mdio_drive_bit(mii_gpio, 1); /* <<<<< */
} else {
mdio_drive_bit(mii_gpio, 0); /* <<<<< */
}
mdc_clk_1_0(mii_gpio);
addr <<= 1;
}
/*
* send the register address
*/
for (i = 0; i < MII_5ADDRESS_BITS; i++) {
if (reg & FIFTH_BIT_0x10) {
mdio_drive_bit(mii_gpio, 1); /* <<<<< */
} else {
mdio_drive_bit(mii_gpio, 0); /* <<<<< */
}
mdc_clk_1_0(mii_gpio);
reg <<= 1;
}
}
/*
* MiiGpio_PhyRead:
* Read from an MII PHY register
*/
uint32_t MiiGpio_PhyRead (gpio_if_t *mii_gpio, uint32_t PhyAddress, uint32_t RegisterNum)
{
uint16_t regval;
uint16_t i;
/*
* Bang the PHY address and PHY register on the bus.
*/
mii_send_address(mii_gpio, MII_READ, PhyAddress, RegisterNum);
/*
* Set GPIO mode to read
*/
mdio_mode_input(mii_gpio);
mdc_clk_1_0(mii_gpio);
/*
* check the turnaround bit
*/
if (mdio_read(mii_gpio) != 0)
{
printf("ERROR: PHY not driving turnaround bit low.\n\r");
return -1;
}
/*
* read 16 bits of register data, MSB first
*/
regval = 0;
for (i = 0; i < MII_16REGISTER_BITS; i++)
{
mdc_clk_1_0(mii_gpio);
regval <<= 1;
regval |= mdio_read(mii_gpio);
}
mdc_clk_1_0(mii_gpio);
return regval;
}
/*
* MiiGpio_PhyWrite:
* Write to an MII PHY register
*/
void MiiGpio_PhyWrite (gpio_if_t *mii_gpio, uint32_t PhyAddress, uint32_t RegisterNum, uint16_t PhyData)
{
int i;
/*
* Bang the PHY address and PHY register on the bus.
*/
mii_send_address(mii_gpio, MII_WRITE, PhyAddress, RegisterNum);
/* send the turnaround (10) */
mdio_drive_bit(mii_gpio, 1); /* <<<<< */
mdc_clk_1_0(mii_gpio);
mdio_drive_bit(mii_gpio, 0); /* <<<<< */
mdc_clk_1_0(mii_gpio);
/*
* write 16 bits of register data, MSB first
*/
for (i = 0; i < MII_16REGISTER_BITS; i++)
{
if (PhyData & MSB_16BITS_0x8000)
{
mdio_drive_bit(mii_gpio, 1); /* <<<<< */
}
else
{
mdio_drive_bit(mii_gpio, 0); /* <<<<< */
}
mdc_clk_1_0(mii_gpio);
PhyData <<= 1;
}
mdio_mode_input(mii_gpio);
mdc_clk_1_0(mii_gpio);
}
// TODO!
/*
* MiiGpio_Init:
* Initialize GPIOs connected to PHY MDC and MDIO pins
*/
int MiiGpio_Init(gpio_if_t *mii_gpio)
{
uint32_t Data;
int err;
if (mii_gpio == NULL) {
return -ENODEV;
}
/*
* Initialize the GPIO component
*/
//TODO: CHANGE!
err = gpio_init(mii_gpio, SYS_GPIO_0_BASE);
if( err < 0 )
return err;
/*
* Set the direction for MDC signals to be output
*/
// GPIO_SetDataDirection(mii_gpio, MDC_MDIO_GPIO_CHANNEL, MDC_MDIO_MDIO_BIT);
gpio_write(mii_gpio, GPIO_0_MASK_MDIO, GPIO_0_ALIGN_MDIO, GPIO_DIR_OFFSET, GPIO_0_MDIO_RST | GPIO_0_MDIO_MDC);
return 0;
}
+81
View File
@@ -0,0 +1,81 @@
#ifndef __MII_BITBANG_H__
#define __MII_BITBANG_H__
/** *******************************************************************************
*
* Project: Robotics library for the Autonomous Robotics Development Platform
* Port by: Jorge Sánchez de Nova jssdn (mail)_(at) kth.se
*
* NOTE: This code is based on the Xilinx XAPP1042 which, as noted by Xilinx, is based in Linux Kernel's
* drivers/net/fs_enet by Vitaly Bordug <vbordug@ru.mvista.com> and Pantelis Antoniou <panto@intracom.gr>
*
* Description:
* Software to access PHY registers in a system where the serial control bus
* signals (MDC, MDIO) are connected to GPIO.
*
* Xilinx disclaimer below apply.
*
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
* SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR
* XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION
* AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION
* OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS
* IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* (c) Copyright 2008 Xilinx, Inc.
* All rights reserved.
*
******************************************************************************* **/
#define GPIO_MDCMDIO_BASE 0x81000000
#define GPIO_MDCMDIO_END 0x8100FFFF
/*
* Which GPIO bit is MDC and which is MDIO are determined by:
*
* From system.mhs:
* PORT fpga_0_MII_MDC_MDIO_GPIO_IO_pin = fpga_0_MII_MDC_MDIO_GPIO_IO,
* DIR = IO, VEC = [1:0]
*
* From ML403 data/system.ucf:
* # MDIO
* Net fpga_0_MII_MDC_MDIO_GPIO_IO_pin<1> LOC = G4;
* # MDC
* Net fpga_0_MII_MDC_MDIO_GPIO_IO_pin<0> LOC = D1;
*/
#define MDC_MDIO_DEVICE_ID XPAR_MII_MDC_MDIO_DEVICE_ID
#define MDC_MDIO_GPIO_CHANNEL 1
#define MDC_MDIO_MDIO_BIT 2
#define MDC_MDIO_MDIO_BIT_SHIFT 1
#define MDC_MDIO_MDC_BIT 1
#define MDC_MDIO_MDC_BIT_SHIFT 0
#define MII_READ 1
#define MII_WRITE 0
#define MII_PREABLE_BITS 32
#define MII_5ADDRESS_BITS 5
#define MII_16REGISTER_BITS 16
#define MII_DATA_INVALID 0xFFFF
#define FIFTH_BIT_0x10 0x10
#define MSB_16BITS_0x8000 0x8000
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include "gpio.h"
uint32_t MiiGpio_PhyRead(gpio_if_t *mii_gpio, uint32_t PhyAddress, uint32_t RegisterNum);
void MiiGpio_PhyWrite(gpio_if_t *mii_gpio, uint32_t PhyAddress, uint32_t RegisterNum, uint16_t PhyData);
int MiiGpio_Init(gpio_if_t *mii_gpio);
#endif
+50
View File
@@ -0,0 +1,50 @@
// -------------------------------------------------------------------------
// udp.c
//
// 29.12.2003, J. Ahrensfeld
//
// -------------------------------------------------------------------------
#include "ethernet.h"
#include "ipv4.h"
#include "udp.h"
#include "string.h"
// -------------------------------------------------------------------------
// Testing
uint8_t *UDP_create(packet_t *pPacket, uint8_t *inet_addr_src, uint16_t port_src, uint8_t *inet_addr_dst, uint16_t port_dst, uint8_t *pUDP_payload, uint16_t len)
{
uint16_t sum;
UDP *pUDP;
UDPPP pseudo_hdr;
uint8_t *pData;
pUDP = (UDP*)IPV4_create(pPacket, IP_TYPE_UDP, sizeof(UDP)+len, inet_addr_src, inet_addr_dst);
// Fill UDP header
pUDP->src_port = port_src;
pUDP->dst_port = port_dst;
pUDP->len = len + sizeof(UDP);
pUDP->chksum = 0x0000;
// Fill pseudo header
memcpy(&pseudo_hdr.inet_addr_src, inet_addr_src, 4);
memcpy(&pseudo_hdr.inet_addr_dst, inet_addr_dst, 4);
pseudo_hdr.proto = IP_TYPE_UDP;
pseudo_hdr.len = len + sizeof(UDP);
// Calculate checksums
pUDP->chksum = ~IPv4ChkSum((uint16_t*)&pseudo_hdr, pUDP->chksum, sizeof(UDPPP));
// Commit header
pData = (uint8_t*)Eth_pkt_append(pPacket, sizeof(UDP));
// Commit data
if (pUDP_payload)
{
memcpy(pData, pUDP_payload, len);
return Eth_pkt_append(pPacket, len);
}
return pData;
}
+36
View File
@@ -0,0 +1,36 @@
// -------------------------------------------------------------------------
// udp.h
//
// 29.12.2003, J. Ahrensfeld
//
// -------------------------------------------------------------------------
#ifndef UDP_H
#define UDP_H
#include "libsys.h"
#include "ethernet.h"
// -------------------------------------------------------------------------
typedef struct _sUDP
{
uint16_t src_port;
uint16_t dst_port;
uint16_t len;
uint16_t chksum;
} __attribute__ ((__packed__)) UDP;
typedef struct _sUDPPP
{
uint8_t inet_addr_src[4];
uint8_t inet_addr_dst[4];
uint8_t zero;
uint8_t proto;
uint16_t len;
} __attribute__ ((__packed__)) UDPPP;
// -------------------------------------------------------------------------
uint8_t *UDP_create(packet_t *pPacket, uint8_t *inet_addr_src, uint16_t port_src, uint8_t *inet_addr_dst, uint16_t port_dst, uint8_t *pUDP_payload, uint16_t len);
// -------------------------------------------------------------------------
#endif // UDP_H