forked from M-Labs/artiq
runtime: get IP and MAC from flash storage
This commit is contained in:
parent
56c85dd2cb
commit
d3753c9643
@ -1,6 +1,6 @@
|
||||
include $(MSCDIR)/software/common.mak
|
||||
|
||||
OBJECTS := isr.o flash_storage.o clock.o elf_loader.o services.o session.o log.o test_mode.o kloader.o mailbox.o ksupport_data.o main.o
|
||||
OBJECTS := isr.o flash_storage.o clock.o elf_loader.o services.o session.o log.o test_mode.o kloader.o mailbox.o ksupport_data.o kserver.o main.o
|
||||
OBJECTS_KSUPPORT := ksupport.o exception_jmp.o exceptions.o mailbox.o bridge.o rtio.o dds.o
|
||||
|
||||
CFLAGS += -Ilwip/src/include -Iliblwip
|
||||
|
215
soc/runtime/kserver.c
Normal file
215
soc/runtime/kserver.c
Normal file
@ -0,0 +1,215 @@
|
||||
#include <generated/csr.h>
|
||||
|
||||
#ifdef CSR_ETHMAC_BASE
|
||||
|
||||
#include <netif/etharp.h>
|
||||
#include <netif/liteethif.h>
|
||||
#include <lwip/init.h>
|
||||
#include <lwip/memp.h>
|
||||
#include <lwip/ip4_addr.h>
|
||||
#include <lwip/ip4.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <lwip/sys.h>
|
||||
#include <lwip/tcp.h>
|
||||
#include <lwip/timers.h>
|
||||
|
||||
#include "session.h"
|
||||
#include "kserver.h"
|
||||
|
||||
struct kserver_connstate {
|
||||
int magic_recognized;
|
||||
struct pbuf *rp;
|
||||
int rp_offset;
|
||||
};
|
||||
|
||||
static struct kserver_connstate *cs_new(void)
|
||||
{
|
||||
struct kserver_connstate *cs;
|
||||
|
||||
cs = (struct kserver_connstate *)mem_malloc(sizeof(struct kserver_connstate));
|
||||
if(!cs)
|
||||
return NULL;
|
||||
cs->magic_recognized = 0;
|
||||
cs->rp = NULL;
|
||||
cs->rp_offset = 0;
|
||||
return cs;
|
||||
}
|
||||
|
||||
static void cs_free(struct kserver_connstate *cs)
|
||||
{
|
||||
if(cs->rp)
|
||||
pbuf_free(cs->rp);
|
||||
mem_free(cs);
|
||||
}
|
||||
|
||||
static const char kserver_magic[] = "ARTIQ coredev\n";
|
||||
|
||||
static int magic_ok(struct kserver_connstate *cs)
|
||||
{
|
||||
return cs->magic_recognized >= 14;
|
||||
}
|
||||
|
||||
static struct kserver_connstate *active_cs;
|
||||
static struct tcp_pcb *active_pcb;
|
||||
|
||||
static void kserver_close(struct kserver_connstate *cs, struct tcp_pcb *pcb)
|
||||
{
|
||||
if(cs == active_cs) {
|
||||
session_end();
|
||||
active_cs = NULL;
|
||||
active_pcb = NULL;
|
||||
}
|
||||
|
||||
/* lwip loves to call back with broken pointers. Prevent that. */
|
||||
tcp_arg(pcb, NULL);
|
||||
tcp_recv(pcb, NULL);
|
||||
tcp_sent(pcb, NULL);
|
||||
tcp_err(pcb, NULL);
|
||||
|
||||
cs_free(cs);
|
||||
tcp_close(pcb);
|
||||
}
|
||||
|
||||
static err_t kserver_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
||||
{
|
||||
struct kserver_connstate *cs;
|
||||
|
||||
cs = (struct kserver_connstate *)arg;
|
||||
if(p) {
|
||||
if(cs->rp)
|
||||
pbuf_cat(cs->rp, p);
|
||||
else {
|
||||
cs->rp = p;
|
||||
cs->rp_offset = 0;
|
||||
}
|
||||
} else
|
||||
kserver_close(cs, pcb);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static err_t kserver_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
|
||||
{
|
||||
session_ack_mem(len);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void tcp_pcb_service(void *arg, struct tcp_pcb *pcb)
|
||||
{
|
||||
struct kserver_connstate *cs;
|
||||
int remaining_in_pbuf;
|
||||
char *rpp;
|
||||
struct pbuf *next;
|
||||
int r;
|
||||
|
||||
cs = (struct kserver_connstate *)arg;
|
||||
|
||||
while(cs->rp) {
|
||||
remaining_in_pbuf = cs->rp->len - cs->rp_offset;
|
||||
rpp = (char *)cs->rp->payload;
|
||||
while(remaining_in_pbuf > 0) {
|
||||
if(cs == active_cs) {
|
||||
r = session_input(&rpp[cs->rp_offset], remaining_in_pbuf);
|
||||
if(r > 0) {
|
||||
tcp_recved(pcb, r);
|
||||
cs->rp_offset += r;
|
||||
remaining_in_pbuf -= r;
|
||||
} else if(r == 0)
|
||||
return;
|
||||
else
|
||||
kserver_close(cs, pcb);
|
||||
} else {
|
||||
if(rpp[cs->rp_offset] == kserver_magic[cs->magic_recognized]) {
|
||||
cs->magic_recognized++;
|
||||
if(magic_ok(cs)) {
|
||||
if(active_cs)
|
||||
kserver_close(active_cs, active_pcb);
|
||||
session_start();
|
||||
active_cs = cs;
|
||||
active_pcb = pcb;
|
||||
tcp_sent(pcb, kserver_sent);
|
||||
}
|
||||
} else {
|
||||
kserver_close(cs, pcb);
|
||||
return;
|
||||
}
|
||||
remaining_in_pbuf--;
|
||||
cs->rp_offset++;
|
||||
tcp_recved(pcb, 1);
|
||||
}
|
||||
}
|
||||
next = cs->rp->next;
|
||||
if(cs->rp->tot_len != cs->rp->len) {
|
||||
pbuf_ref(next);
|
||||
pbuf_free(cs->rp);
|
||||
cs->rp = next;
|
||||
cs->rp_offset = 0;
|
||||
} else {
|
||||
pbuf_free(cs->rp);
|
||||
cs->rp = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void kserver_err(void *arg, err_t err)
|
||||
{
|
||||
struct kserver_connstate *cs;
|
||||
|
||||
cs = (struct kserver_connstate *)arg;
|
||||
cs_free(cs);
|
||||
}
|
||||
|
||||
static struct tcp_pcb *listen_pcb;
|
||||
|
||||
static err_t kserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
{
|
||||
struct kserver_connstate *cs;
|
||||
|
||||
cs = cs_new();
|
||||
if(!cs)
|
||||
return ERR_MEM;
|
||||
tcp_accepted(listen_pcb);
|
||||
tcp_arg(newpcb, cs);
|
||||
tcp_recv(newpcb, kserver_recv);
|
||||
tcp_err(newpcb, kserver_err);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void kserver_init(void)
|
||||
{
|
||||
listen_pcb = tcp_new();
|
||||
tcp_bind(listen_pcb, IP_ADDR_ANY, 1381);
|
||||
listen_pcb = tcp_listen(listen_pcb);
|
||||
tcp_accept(listen_pcb, kserver_accept);
|
||||
}
|
||||
|
||||
extern struct tcp_pcb *tcp_active_pcbs;
|
||||
|
||||
void kserver_service(void)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
void *data;
|
||||
int len, sndbuf;
|
||||
|
||||
/* Assume all active TCP PCBs with a non-NULL arg are our connections. */
|
||||
pcb = tcp_active_pcbs;
|
||||
while(pcb) {
|
||||
if(pcb->callback_arg)
|
||||
tcp_pcb_service(pcb->callback_arg, pcb);
|
||||
pcb = pcb->next;
|
||||
}
|
||||
|
||||
if(active_cs) {
|
||||
session_poll(&data, &len);
|
||||
if(len > 0) {
|
||||
sndbuf = tcp_sndbuf(active_pcb);
|
||||
if(len > sndbuf)
|
||||
len = sndbuf;
|
||||
tcp_write(active_pcb, data, len, 0);
|
||||
session_ack_data(len);
|
||||
}
|
||||
if(len < 0)
|
||||
kserver_close(active_cs, active_pcb);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CSR_ETHMAC_BASE */
|
7
soc/runtime/kserver.h
Normal file
7
soc/runtime/kserver.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef __KSERVER_H
|
||||
#define __KSERVER_H
|
||||
|
||||
void kserver_init(void);
|
||||
void kserver_service(void);
|
||||
|
||||
#endif /* __KSERVER_H */
|
@ -21,12 +21,13 @@
|
||||
#include <lwip/timers.h>
|
||||
#endif
|
||||
|
||||
#include "flash_storage.h"
|
||||
#include "clock.h"
|
||||
#include "test_mode.h"
|
||||
#include "kserver.h"
|
||||
#include "session.h"
|
||||
|
||||
#ifdef CSR_ETHMAC_BASE
|
||||
unsigned char macadr[6] = {0x10, 0xe2, 0xd5, 0x00, 0x00, 0x00};
|
||||
|
||||
u32_t sys_now(void)
|
||||
{
|
||||
@ -44,15 +45,69 @@ static void lwip_service(void)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char macadr[6];
|
||||
|
||||
static int hex2nib(int c)
|
||||
{
|
||||
if((c >= '0') && (c <= '9'))
|
||||
return c - '0';
|
||||
if((c >= 'a') && (c <= 'f'))
|
||||
return c - 'a' + 10;
|
||||
if((c >= 'A') && (c <= 'F'))
|
||||
return c - 'A' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void init_macadr(void)
|
||||
{
|
||||
static const unsigned char default_macadr[6] = {0x10, 0xe2, 0xd5, 0x32, 0x50, 0x00};
|
||||
char b[32];
|
||||
char fs_macadr[6];
|
||||
int i, r, s;
|
||||
|
||||
memcpy(macadr, default_macadr, 6);
|
||||
r = fs_read("mac", b, sizeof(b) - 1, NULL);
|
||||
if(r <= 0)
|
||||
return;
|
||||
b[r] = 0;
|
||||
for(i=0;i<6;i++) {
|
||||
r = hex2nib(b[3*i]);
|
||||
s = hex2nib(b[3*i + 1]);
|
||||
if((r < 0) || (s < 0))
|
||||
return;
|
||||
fs_macadr[i] = (r << 4) | s;
|
||||
}
|
||||
for(i=0;i<5;i++)
|
||||
if(b[3*i + 2] != ':')
|
||||
return;
|
||||
memcpy(macadr, fs_macadr, 6);
|
||||
}
|
||||
|
||||
static void fsip_or_default(struct ip4_addr *d, char *key, int i1, int i2, int i3, int i4)
|
||||
{
|
||||
int r;
|
||||
char cp[32];
|
||||
|
||||
IP4_ADDR(d, i1, i2, i3, i4);
|
||||
|
||||
r = fs_read(key, cp, sizeof(cp) - 1, NULL);
|
||||
if(r <= 0)
|
||||
return;
|
||||
cp[r] = 0;
|
||||
if(!ip4addr_aton(cp, d))
|
||||
return;
|
||||
}
|
||||
|
||||
static void network_init(void)
|
||||
{
|
||||
struct ip4_addr local_ip;
|
||||
struct ip4_addr netmask;
|
||||
struct ip4_addr gateway_ip;
|
||||
|
||||
IP4_ADDR(&local_ip, 192, 168, 0, 42);
|
||||
IP4_ADDR(&netmask, 255, 255, 255, 0);
|
||||
IP4_ADDR(&gateway_ip, 192, 168, 0, 1);
|
||||
init_macadr();
|
||||
fsip_or_default(&local_ip, "ip", 192, 168, 0, 42);
|
||||
fsip_or_default(&netmask, "netmask", 255, 255, 255, 0);
|
||||
fsip_or_default(&gateway_ip, "gateway", 192, 168, 0, 1);
|
||||
|
||||
lwip_init();
|
||||
|
||||
@ -62,204 +117,9 @@ static void network_init(void)
|
||||
netif_set_link_up(&netif);
|
||||
}
|
||||
|
||||
struct kserver_connstate {
|
||||
int magic_recognized;
|
||||
struct pbuf *rp;
|
||||
int rp_offset;
|
||||
};
|
||||
|
||||
static struct kserver_connstate *cs_new(void)
|
||||
{
|
||||
struct kserver_connstate *cs;
|
||||
|
||||
cs = (struct kserver_connstate *)mem_malloc(sizeof(struct kserver_connstate));
|
||||
if(!cs)
|
||||
return NULL;
|
||||
cs->magic_recognized = 0;
|
||||
cs->rp = NULL;
|
||||
cs->rp_offset = 0;
|
||||
return cs;
|
||||
}
|
||||
|
||||
static void cs_free(struct kserver_connstate *cs)
|
||||
{
|
||||
if(cs->rp)
|
||||
pbuf_free(cs->rp);
|
||||
mem_free(cs);
|
||||
}
|
||||
|
||||
static const char kserver_magic[] = "ARTIQ coredev\n";
|
||||
|
||||
static int magic_ok(struct kserver_connstate *cs)
|
||||
{
|
||||
return cs->magic_recognized >= 14;
|
||||
}
|
||||
|
||||
static struct kserver_connstate *active_cs;
|
||||
static struct tcp_pcb *active_pcb;
|
||||
|
||||
static void kserver_close(struct kserver_connstate *cs, struct tcp_pcb *pcb)
|
||||
{
|
||||
if(cs == active_cs) {
|
||||
session_end();
|
||||
active_cs = NULL;
|
||||
active_pcb = NULL;
|
||||
}
|
||||
|
||||
/* lwip loves to call back with broken pointers. Prevent that. */
|
||||
tcp_arg(pcb, NULL);
|
||||
tcp_recv(pcb, NULL);
|
||||
tcp_sent(pcb, NULL);
|
||||
tcp_err(pcb, NULL);
|
||||
|
||||
cs_free(cs);
|
||||
tcp_close(pcb);
|
||||
}
|
||||
|
||||
static err_t kserver_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
||||
{
|
||||
struct kserver_connstate *cs;
|
||||
|
||||
cs = (struct kserver_connstate *)arg;
|
||||
if(p) {
|
||||
if(cs->rp)
|
||||
pbuf_cat(cs->rp, p);
|
||||
else {
|
||||
cs->rp = p;
|
||||
cs->rp_offset = 0;
|
||||
}
|
||||
} else
|
||||
kserver_close(cs, pcb);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static err_t kserver_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
|
||||
{
|
||||
session_ack_mem(len);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void tcp_pcb_service(void *arg, struct tcp_pcb *pcb)
|
||||
{
|
||||
struct kserver_connstate *cs;
|
||||
int remaining_in_pbuf;
|
||||
char *rpp;
|
||||
struct pbuf *next;
|
||||
int r;
|
||||
|
||||
cs = (struct kserver_connstate *)arg;
|
||||
|
||||
while(cs->rp) {
|
||||
remaining_in_pbuf = cs->rp->len - cs->rp_offset;
|
||||
rpp = (char *)cs->rp->payload;
|
||||
while(remaining_in_pbuf > 0) {
|
||||
if(cs == active_cs) {
|
||||
r = session_input(&rpp[cs->rp_offset], remaining_in_pbuf);
|
||||
if(r > 0) {
|
||||
tcp_recved(pcb, r);
|
||||
cs->rp_offset += r;
|
||||
remaining_in_pbuf -= r;
|
||||
} else if(r == 0)
|
||||
return;
|
||||
else
|
||||
kserver_close(cs, pcb);
|
||||
} else {
|
||||
if(rpp[cs->rp_offset] == kserver_magic[cs->magic_recognized]) {
|
||||
cs->magic_recognized++;
|
||||
if(magic_ok(cs)) {
|
||||
if(active_cs)
|
||||
kserver_close(active_cs, active_pcb);
|
||||
session_start();
|
||||
active_cs = cs;
|
||||
active_pcb = pcb;
|
||||
tcp_sent(pcb, kserver_sent);
|
||||
}
|
||||
} else {
|
||||
kserver_close(cs, pcb);
|
||||
return;
|
||||
}
|
||||
remaining_in_pbuf--;
|
||||
cs->rp_offset++;
|
||||
tcp_recved(pcb, 1);
|
||||
}
|
||||
}
|
||||
next = cs->rp->next;
|
||||
if(cs->rp->tot_len != cs->rp->len) {
|
||||
pbuf_ref(next);
|
||||
pbuf_free(cs->rp);
|
||||
cs->rp = next;
|
||||
cs->rp_offset = 0;
|
||||
} else {
|
||||
pbuf_free(cs->rp);
|
||||
cs->rp = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void kserver_err(void *arg, err_t err)
|
||||
{
|
||||
struct kserver_connstate *cs;
|
||||
|
||||
cs = (struct kserver_connstate *)arg;
|
||||
cs_free(cs);
|
||||
}
|
||||
|
||||
static struct tcp_pcb *listen_pcb;
|
||||
|
||||
static err_t kserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
{
|
||||
struct kserver_connstate *cs;
|
||||
|
||||
cs = cs_new();
|
||||
if(!cs)
|
||||
return ERR_MEM;
|
||||
tcp_accepted(listen_pcb);
|
||||
tcp_arg(newpcb, cs);
|
||||
tcp_recv(newpcb, kserver_recv);
|
||||
tcp_err(newpcb, kserver_err);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void kserver_init(void)
|
||||
{
|
||||
listen_pcb = tcp_new();
|
||||
tcp_bind(listen_pcb, IP_ADDR_ANY, 1381);
|
||||
listen_pcb = tcp_listen(listen_pcb);
|
||||
tcp_accept(listen_pcb, kserver_accept);
|
||||
}
|
||||
|
||||
extern struct tcp_pcb *tcp_active_pcbs;
|
||||
|
||||
static void kserver_service(void)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
void *data;
|
||||
int len, sndbuf;
|
||||
|
||||
/* Assume all active TCP PCBs with a non-NULL arg are our connections. */
|
||||
pcb = tcp_active_pcbs;
|
||||
while(pcb) {
|
||||
if(pcb->callback_arg)
|
||||
tcp_pcb_service(pcb->callback_arg, pcb);
|
||||
pcb = pcb->next;
|
||||
}
|
||||
|
||||
if(active_cs) {
|
||||
session_poll(&data, &len);
|
||||
if(len > 0) {
|
||||
sndbuf = tcp_sndbuf(active_pcb);
|
||||
if(len > sndbuf)
|
||||
len = sndbuf;
|
||||
tcp_write(active_pcb, data, len, 0);
|
||||
session_ack_data(len);
|
||||
}
|
||||
if(len < 0)
|
||||
kserver_close(active_cs, active_pcb);
|
||||
}
|
||||
}
|
||||
|
||||
static void regular_main(void)
|
||||
{
|
||||
puts("Accepting sessions on Ethernet");
|
||||
clock_init();
|
||||
network_init();
|
||||
kserver_init();
|
||||
@ -317,6 +177,7 @@ static void serial_service(void)
|
||||
|
||||
static void regular_main(void)
|
||||
{
|
||||
puts("Accepting sessions on serial link");
|
||||
clock_init();
|
||||
|
||||
/* Open the session for the serial control. */
|
||||
@ -369,12 +230,6 @@ int main(void)
|
||||
|
||||
puts("ARTIQ runtime built "__DATE__" "__TIME__"\n");
|
||||
|
||||
#ifdef CSR_ETHMAC_BASE
|
||||
puts("Accepting sessions on Ethernet");
|
||||
#else
|
||||
puts("Accepting sessions on serial link");
|
||||
#endif
|
||||
|
||||
puts("Press 't' to enter test mode...");
|
||||
blink_led();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user