Skip to content

Commit e7fa61a

Browse files
committed
MEGA65: WIP, first try of new ethertap #242
1 parent 0e50c6f commit e7fa61a

File tree

7 files changed

+617
-484
lines changed

7 files changed

+617
-484
lines changed

targets/mega65/ethernet65.c

Lines changed: 449 additions & 426 deletions
Large diffs are not rendered by default.

targets/mega65/ethernet65.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
1919
#ifndef XEMU_MEGA65_ETHERNET65_H_INCLUDED
2020
#define XEMU_MEGA65_ETHERNET65_H_INCLUDED
2121

22+
extern Uint8 eth_rx_buf[0x800];
23+
extern Uint8 eth_tx_buf[0x800];
24+
2225
extern int eth65_init ( const char *options );
26+
#ifdef HAVE_ETHERTAP
27+
extern unsigned int eth65_get_stat ( char *buf, const unsigned int buf_size, unsigned int *rxcnt, unsigned int *txcnt );
28+
#endif
2329
extern void eth65_shutdown ( void );
2430
extern void eth65_reset ( void );
25-
extern Uint8 eth65_buffer_reader ( const Uint32 offset );
26-
extern void eth65_buffer_writer ( const Uint32 offset, const Uint8 data );
2731
extern Uint8 eth65_read_reg ( const unsigned int addr );
2832
extern void eth65_write_reg ( const unsigned int addr, const Uint8 data );
2933

targets/mega65/io_mapper.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ Uint8 io_read ( unsigned int addr )
377377
/* $D800-$DFFF: in case of ethernet I/O mode only! */
378378
/* ----------------------------------------------- */
379379
case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E: case 0x2F:
380-
return eth65_buffer_reader(addr);
380+
return eth_rx_buf[addr - 0x2800U];
381381
/* ----------------------- */
382382
/* $D800-$DBFF: COLOUR RAM */
383383
/* ----------------------- */
@@ -650,7 +650,7 @@ void io_write ( unsigned int addr, Uint8 data )
650650
/* $D800-$DFFF: in case of ethernet I/O mode only! */
651651
/* ----------------------------------------------- */
652652
case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E: case 0x2F:
653-
eth65_buffer_writer(addr, data);
653+
eth_tx_buf[addr - 0x2800U] = data;
654654
return;
655655
/* ----------------------- */
656656
/* $D800-$DBFF: COLOUR RAM */

targets/mega65/matrix_mode.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,24 @@ static void cmd_serialtcp ( char *p )
627627
#endif
628628

629629

630+
#ifdef HAVE_ETHERTAP
631+
#include "ethernet65.h"
632+
static void cmd_eth ( char *p )
633+
{
634+
if (*p) {
635+
MATRIX("Trying to (re)start ethertap with params: \"%s\"\n", p);
636+
eth65_shutdown();
637+
eth65_init(p);
638+
}
639+
char stat[128];
640+
unsigned int rxcnt, txcnt;
641+
(void)eth65_get_stat(stat, sizeof stat, &rxcnt, &txcnt);
642+
if (rxcnt || txcnt)
643+
MATRIX("%s\nRX/TX traffic: %u/%u pckts", stat, rxcnt, txcnt);
644+
}
645+
#endif
646+
647+
630648
static void cmd_help ( char *p );
631649

632650

@@ -653,6 +671,9 @@ static const struct command_tab_st {
653671
{ "vic", cmd_vic, NULL },
654672
# ifdef XEMU_HAS_SOCKET_API
655673
{ "serialtcp", cmd_serialtcp, NULL },
674+
# endif
675+
# ifdef HAVE_ETHERTAP
676+
{ "eth", cmd_eth, NULL },
656677
# endif
657678
{ .cmdname = NULL },
658679
};

targets/mega65/memory_mapper.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ static Uint8 disk_buffer_user_reader ( const Uint32 addr32 ) {
248248
static void disk_buffer_user_writer ( const Uint32 addr32, const Uint8 data ) {
249249
disk_buffer_cpu_view[(addr32 - 0xFFD6000U) & 0x1FF] = data;
250250
}
251+
static Uint8 eth_buffer_reader ( const Uint32 addr32 ) {
252+
return eth_rx_buf[addr32 - 0xFFDE800U];
253+
}
254+
static void eth_buffer_writer ( const Uint32 addr32, const Uint8 data ) {
255+
eth_tx_buf[addr32 - 0xFFDE800U] = data;
256+
}
251257
static Uint8 slow_devices_reader ( const Uint32 addr32 ) {
252258
return cart_read_byte(addr32 - 0x4000000U);
253259
}
@@ -508,8 +514,12 @@ static void resolve_linear_slot ( const Uint32 slot, const Uint32 addr )
508514
}
509515
break;
510516
case MEM_SLOT_TYPE_ETH_BUFFER:
511-
mem_slot_rd_func[slot] = eth65_buffer_reader; // from ethernet65.h
512-
mem_slot_wr_func[slot] = eth65_buffer_writer; // -- "" --
517+
mem_slot_rd_func[slot] = eth_buffer_reader;
518+
mem_slot_wr_func[slot] = eth_buffer_writer;
519+
#ifdef MEM_USE_DATA_POINTERS
520+
mem_slot_rd_data[slot] = eth_rx_buf + addr - 0xFFDE800U;
521+
mem_slot_wr_data[slot] = eth_tx_buf + addr - 0xFFDE800U;
522+
#endif
513523
break;
514524
case MEM_SLOT_TYPE_OPL3:
515525
mem_slot_rd_func[slot] = dummy_reader; // TODO: what should I do here?

xemu/ethertap.c

Lines changed: 121 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* Part of the Xemu project, please visit: https://github.com/lgblgblgb/xemu
2-
Copyright (C)2018,2020-2021 LGB (Gábor Lénárt) <[email protected]>
2+
Copyright (C)2018,2020-2021,2025 LGB (Gábor Lénárt) <[email protected]>
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License as published by
@@ -76,6 +76,8 @@ able to configure the device for itself, hmmm ...) */
7676

7777
static volatile int tuntap_fd = -1;
7878
static int nonblocking = 0;
79+
static char tuntap_name[32];
80+
static struct ifreq ifr;
7981

8082

8183
static int xemu_tuntap_set_nonblocking ( int fd, int is_nonblocking )
@@ -105,62 +107,37 @@ int xemu_tuntap_close ( void )
105107
}
106108

107109

108-
int xemu_tuntap_read ( void *buffer, int min_size, int max_size )
110+
int xemu_tuntap_read ( void *buffer, const int max_size )
109111
{
110-
int got = 0;
111-
if (tuntap_fd < 0)
112-
return 0;
113-
while (got < min_size) {
114-
int r = read(tuntap_fd, buffer, max_size);
115-
printf("ETH-LOW: read ret %d %s\n", r, r >= 0 ? "NO-ERROR-CONDITION" : strerror(errno));
116-
if (!r) {
117-
return got;
118-
} else if (r < 0) {
119-
if (errno == EINTR) {
120-
continue; // try again if it's interrupted. I am not sure if it's the correct behaviour
121-
} else if (errno == EAGAIN || errno == EWOULDBLOCK) {
122-
if (nonblocking)
123-
return (got > 0) ? got : -2; // -2: signal initial EAGAIN situation
124-
else
125-
return -1;
126-
} else {
112+
for (;;) {
113+
const int r = read(tuntap_fd, buffer, max_size);
114+
if (r >= 0) {
115+
return r;
116+
} else {
117+
if (errno == EAGAIN || errno == EWOULDBLOCK)
118+
return nonblocking ? -2 : -1;
119+
else if (errno != EINTR)
127120
return -1;
128-
}
121+
// if EINTR: try again if it's interrupted
129122
}
130-
max_size -= r;
131-
got += r;
132-
buffer += r;
133123
}
134-
return got;
135124
}
136125

137126

138-
int xemu_tuntap_write ( void *buffer, int size )
127+
int xemu_tuntap_write ( const void *buffer, const int size )
139128
{
140-
int did = 0;
141-
if (tuntap_fd < 0)
142-
return 0;
143-
while (size > 0) {
144-
int w = write(tuntap_fd, buffer, size);
145-
if (!w) {
146-
return did;
147-
} else if (w < 0) {
148-
if (errno == EINTR) {
149-
continue;
150-
} else if (errno == EAGAIN || errno == EWOULDBLOCK) {
151-
if (nonblocking)
152-
return (did > 0) ? did : -2;
153-
else
154-
return -1;
155-
} else {
129+
for (;;) {
130+
const int r = write(tuntap_fd, buffer, size);
131+
if (r >= 0) {
132+
return r;
133+
} else {
134+
if (errno == EAGAIN || errno == EWOULDBLOCK)
135+
return nonblocking ? -2 : -1;
136+
else if (errno != EINTR)
156137
return -1;
157-
}
138+
// if EINTR: try again if it's interrupted
158139
}
159-
size -= w;
160-
did += w;
161-
buffer += w;
162140
}
163-
return did;
164141
}
165142

166143

@@ -211,7 +188,6 @@ int xemu_tuntap_alloc ( const char *dev_in, char *dev_out, int dev_out_size, uns
211188
return tuntap_fd;
212189
if (dev_in && strlen(dev_in) > IFNAMSIZ - 1)
213190
return -1;
214-
struct ifreq ifr;
215191
int fd, err;
216192
nonblocking = 0;
217193
memset(&ifr, 0, sizeof(ifr));
@@ -238,13 +214,21 @@ int xemu_tuntap_alloc ( const char *dev_in, char *dev_out, int dev_out_size, uns
238214
close(fd);
239215
return err;
240216
}
217+
#if 0
218+
int persist = 1;
219+
if ((err = ioctl(fd, TUNSETPERSIST, persist)) < 0) {
220+
close(fd);
221+
return err;
222+
}
223+
#endif
241224
if (dev_out) {
242225
if (strlen(ifr.ifr_name) >= dev_out_size) {
243226
close(fd);
244227
return -1;
245228
} else
246229
strcpy(dev_out, ifr.ifr_name);
247230
}
231+
snprintf(tuntap_name, sizeof tuntap_name, "%s", ifr.ifr_name);
248232
if (flags & XEMU_TUNTAP_NONBLOCKING_IO) {
249233
// sets non blocking I/O up, if requested
250234
if (xemu_tuntap_set_nonblocking(fd, 1)) {
@@ -256,4 +240,94 @@ int xemu_tuntap_alloc ( const char *dev_in, char *dev_out, int dev_out_size, uns
256240
return fd; // also return the FD, but note, that it should not be used too much currently outside of this source
257241
}
258242

243+
244+
const char *xemu_tuntap_error ( void )
245+
{
246+
return strerror(errno);
247+
}
248+
249+
250+
int xemu_tuntap_get_mac ( unsigned char mac[6] )
251+
{
252+
if (ioctl(tuntap_fd, SIOCGIFHWADDR, &ifr) == -1)
253+
return -1;
254+
memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
255+
return 0;
256+
}
257+
258+
#include <netinet/in.h>
259+
#include <ifaddrs.h>
260+
261+
unsigned int xemu_tuntap_get_ipv4 ( void )
262+
{
263+
#if 1
264+
int s = socket(AF_INET, SOCK_DGRAM, 0);
265+
if (ioctl(s, SIOCGIFADDR, &ifr) == -1)
266+
return 0;
267+
close(s);
268+
struct sockaddr_in *ipaddr = (struct sockaddr_in *)&ifr.ifr_addr;
269+
return ntohl(ipaddr->sin_addr.s_addr);
270+
#else
271+
struct ifaddrs *ifaddr;
272+
if (getifaddrs(&ifaddr) == -1)
273+
return 0;
274+
for (struct ifaddrs *ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
275+
if (ifa->ifa_addr == NULL)
276+
continue;
277+
if (strcmp(ifa->ifa_name, tuntap_name) == 0 && ifa->ifa_addr->sa_family == AF_INET) {
278+
const unsigned int ip = ntohl(((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr);
279+
freeifaddrs(ifaddr);
280+
return ip;
281+
}
282+
}
283+
freeifaddrs(ifaddr);
284+
return 0;
285+
#endif
286+
}
287+
288+
289+
#if 0
290+
291+
// NOTE: this would need to link with -lresolv to be safe, as it's only 1-2 years old change
292+
// in glibc's to have built-in. However that needs my build system a bit!!!! TODO/FIXME
293+
// It seems on BSDs it's always in libreslv, and MacOS is a bit unpredictable in this regard ...
294+
295+
#include <resolv.h>
296+
297+
unsigned int xemu_tuntap_get_dns_server ( void )
298+
{
299+
#if 1
300+
// newer style interface
301+
struct __res_state res;
302+
const int ret = res_ninit(&res);
303+
const int num = res.nscount;
304+
# define rres res
305+
#else
306+
// older style interface
307+
const int ret = res_init();
308+
const int num = _res.nscount;
309+
# define rres _res
310+
#endif
311+
312+
// TODO: use res_ninit
313+
if (ret) {
314+
// perror("res_init");
315+
return 0;
316+
}
317+
for (int i = 0; i < num; i++) {
318+
const unsigned int ip = ntohl(rres.nsaddr_list[i].sin_addr.s_addr);
319+
// TODO: allow 127.x.y.z to be returned the caller may use xemu_tuntap_get_ipv4() then to use that for DNS server
320+
if ((ip >> 24) != 127 || i == num - 1)
321+
return ip;
322+
//char buf[INET6_ADDRSTRLEN];
323+
//if (inet_ntop(AF_INET, &_res.nsaddr_list[i].sin_addr, buf, sizeof(buf))) {
324+
// printf("DNS server: %s\n", buf);
325+
//}
326+
}
327+
return 0;
328+
}
329+
330+
#endif
331+
332+
259333
#endif

xemu/ethertap.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* Part of the Xemu project, please visit: https://github.com/lgblgblgb/xemu
2-
Copyright (C)2018,2020-2021 LGB (Gábor Lénárt) <[email protected]>
2+
Copyright (C)2018,2020-2021,2025 LGB (Gábor Lénárt) <[email protected]>
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License as published by
@@ -19,14 +19,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
1919
#define XEMU_COMMON_ETHERTAP_H_INCLUDED
2020
#ifdef HAVE_ETHERTAP
2121

22-
#include "xemu/emutools_basicdefs.h"
23-
2422
extern int xemu_tuntap_close ( void );
2523
extern int xemu_tuntap_alloc ( const char *dev_in, char *dev_out, int dev_out_size, unsigned int flags );
26-
extern int xemu_tuntap_read ( void *buffer, int min_size, int max_size );
27-
extern int xemu_tuntap_write ( void *buffer, int size );
24+
extern int xemu_tuntap_read ( void *buffer, const int max_size );
25+
extern int xemu_tuntap_write ( const void *buffer, const int size );
2826
extern int xemu_tuntap_select ( int flags, int timeout_usecs );
2927

28+
extern const char *xemu_tuntap_error ( void );
29+
extern int xemu_tuntap_get_mac ( unsigned char mac[6] );
30+
extern unsigned int xemu_tuntap_get_ipv4 ( void );
3031

3132
// for xemu_tuntap_alloc():
3233

0 commit comments

Comments
 (0)