1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
// https://github.com/pulp-platform/riscv-dbg/blob/master/tb/remote_bitbang/remote_bitbang.c
// See LICENSE.Berkeley for license details.
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "remote_jtag.hpp"
remote_jtag::remote_jtag(uint16_t port)
{
this->socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd < 0) {
fprintf(stderr, "remote_bitbang failed to make socket: %m\n");
abort();
}
int reuseaddr = 1;
if (setsockopt(this->socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof reuseaddr) < 0) {
fprintf(stderr, "remote_bitbang failed setsockopt: %m\n");
abort();
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(0x7f000001);
addr.sin_port = htons(port);
if (bind(this->socket_fd, (struct sockaddr *)&addr, sizeof addr) < 0) {
fprintf(stderr, "remote_bitbang failed to bind socket: %m\n");
abort();
}
if (listen(this->socket_fd, 1) < -1) {
fprintf(stderr, "remote_bitbang failed to listen on socket: %m\n");
abort();
}
fprintf(stderr, "JTAG remote bitbang server is ready\n");
fprintf(stderr, "Listening on port %d\n", ntohs(addr.sin_port));
this->poll_thread = std::thread([this]() { this->poll_main(); });
}
remote_jtag::~remote_jtag()
{
if (this->poll_thread.joinable())
this->poll_thread.join();
if (this->socket_fd >= 0) {
close(this->socket_fd);
this->socket_fd = -1;
}
}
void remote_jtag::poll_main()
{
fprintf(stderr, "Attempting to accept client socket\n");
int client_fd = accept(this->socket_fd, NULL, NULL);
if (client_fd < 0) {
fprintf(stderr, "failed to accept on socket: %m\n");
this->dead.store(true, std::memory_order_relaxed);
return;
} else
fprintf(stderr, "Accepted successfully.\n");
std::unique_lock<std::mutex> lock(this->buffer_lock);
while (true) {
this->read_bytes = read(client_fd, this->in_buffer, sizeof this->in_buffer);
this->readable.store(true, std::memory_order_relaxed);
this->processed_cond.wait
(
lock, [&] { return !this->readable.load(std::memory_order_relaxed); }
);
if (this->read_bytes <= 0 || this->dead.load(std::memory_order_relaxed))
break;
unsigned write_size = this->write_bytes;
unsigned write_start = 0;
while (write_size > 0) {
auto written = write(client_fd, &this->out_buffer[write_start], write_size);
if (written <= 0) {
fprintf(stderr, "jtag write() failed: %m\n");
break;
}
write_size -= written;
write_start += written;
}
}
close(client_fd);
this->dead.store(true, std::memory_order_relaxed);
}
|