- refactored network
git-svn-id: http://moon:8086/svn/mips@204 a8ebac50-d88d-4704-bea3-6648445a41b3
This commit is contained in:
@@ -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));
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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));
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user