1 |
|
/* |
2 |
|
* ether_unix.cpp - Ethernet device driver, Unix specific stuff (Linux and FreeBSD) |
3 |
|
* |
4 |
< |
* Basilisk II (C) 1997-2005 Christian Bauer |
4 |
> |
* Basilisk II (C) 1997-2008 Christian Bauer |
5 |
|
* |
6 |
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
* it under the terms of the GNU General Public License as published by |
20 |
|
|
21 |
|
#include "sysdeps.h" |
22 |
|
|
23 |
+ |
/* |
24 |
+ |
* NOTES concerning MacOS X issues: |
25 |
+ |
* - poll() does not exist in 10.2.8, but is available in 10.4.4 |
26 |
+ |
* - select(), and very likely poll(), are not cancellation points. So |
27 |
+ |
* the ethernet thread doesn't stop on exit. An explicit check is |
28 |
+ |
* performed to workaround this problem. |
29 |
+ |
*/ |
30 |
+ |
#if (defined __APPLE__ && defined __MACH__) || ! defined HAVE_POLL |
31 |
+ |
#define USE_POLL 0 |
32 |
+ |
#else |
33 |
+ |
#define USE_POLL 1 |
34 |
+ |
#endif |
35 |
+ |
|
36 |
+ |
// Define to let the slirp library determine the right timeout for select() |
37 |
+ |
#define USE_SLIRP_TIMEOUT 1 |
38 |
+ |
|
39 |
|
#ifdef HAVE_SYS_POLL_H |
40 |
|
#include <sys/poll.h> |
41 |
|
#endif |
47 |
|
#include <semaphore.h> |
48 |
|
#include <errno.h> |
49 |
|
#include <stdio.h> |
50 |
+ |
#include <signal.h> |
51 |
|
#include <map> |
52 |
|
|
53 |
|
#if defined(__FreeBSD__) || defined(sgi) || (defined(__APPLE__) && defined(__MACH__)) |
125 |
|
// Prototypes |
126 |
|
static void *receive_func(void *arg); |
127 |
|
static void *slirp_receive_func(void *arg); |
111 |
– |
static int poll_fd(int fd); |
128 |
|
static int16 ether_do_add_multicast(uint8 *addr); |
129 |
|
static int16 ether_do_del_multicast(uint8 *addr); |
130 |
|
static int16 ether_do_write(uint32 arg); |
183 |
|
#ifdef HAVE_PTHREAD_CANCEL |
184 |
|
pthread_cancel(ether_thread); |
185 |
|
#endif |
170 |
– |
#ifdef AQUA |
171 |
– |
// This call, which waits for ether_thread to terminate, |
172 |
– |
// never returns when used in Nigel's OS X port. |
173 |
– |
#else |
186 |
|
pthread_join(ether_thread, NULL); |
175 |
– |
#endif |
187 |
|
sem_destroy(&int_ack); |
188 |
|
thread_active = false; |
189 |
|
} |
225 |
|
|
226 |
|
bool ether_init(void) |
227 |
|
{ |
228 |
< |
int nonblock = 1; |
228 |
> |
int val, nonblock = 1; |
229 |
|
char str[256]; |
230 |
|
|
231 |
|
// Do nothing if no Ethernet device specified |
248 |
|
else |
249 |
|
net_if_type = NET_IF_SHEEPNET; |
250 |
|
|
251 |
+ |
// Don't raise SIGPIPE, let errno be set to EPIPE |
252 |
+ |
struct sigaction sigpipe_sa; |
253 |
+ |
if (sigaction(SIGPIPE, NULL, &sigpipe_sa) == 0) { |
254 |
+ |
assert(sigpipe_sa.sa_handler == SIG_DFL || sigpipe_sa.sa_handler == SIG_IGN); |
255 |
+ |
sigfillset(&sigpipe_sa.sa_mask); |
256 |
+ |
sigpipe_sa.sa_flags = 0; |
257 |
+ |
sigpipe_sa.sa_handler = SIG_IGN; |
258 |
+ |
sigaction(SIGPIPE, &sigpipe_sa, NULL); |
259 |
+ |
} |
260 |
+ |
|
261 |
|
#ifdef HAVE_SLIRP |
262 |
|
// Initialize slirp library |
263 |
|
if (net_if_type == NET_IF_SLIRP) { |
346 |
|
#endif |
347 |
|
|
348 |
|
// Set nonblocking I/O |
349 |
< |
ioctl(fd, FIONBIO, &nonblock); |
349 |
> |
#ifdef USE_FIONBIO |
350 |
> |
if (ioctl(fd, FIONBIO, &nonblock) < 0) { |
351 |
> |
sprintf(str, GetString(STR_BLOCKING_NET_SOCKET_WARN), strerror(errno)); |
352 |
> |
WarningAlert(str); |
353 |
> |
goto open_error; |
354 |
> |
} |
355 |
> |
#else |
356 |
> |
val = fcntl(fd, F_GETFL, 0); |
357 |
> |
if (val < 0 || fcntl(fd, F_SETFL, val | O_NONBLOCK) < 0) { |
358 |
> |
sprintf(str, GetString(STR_BLOCKING_NET_SOCKET_WARN), strerror(errno)); |
359 |
> |
WarningAlert(str); |
360 |
> |
goto open_error; |
361 |
> |
} |
362 |
> |
#endif |
363 |
|
|
364 |
|
// Get Ethernet address |
365 |
|
if (net_if_type == NET_IF_ETHERTAP) { |
814 |
|
FD_ZERO(&rfds); |
815 |
|
FD_ZERO(&wfds); |
816 |
|
FD_ZERO(&xfds); |
817 |
< |
slirp_select_fill(&nfds, &rfds, &wfds, &xfds); |
817 |
> |
int timeout = slirp_select_fill(&nfds, &rfds, &wfds, &xfds); |
818 |
> |
#if ! USE_SLIRP_TIMEOUT |
819 |
> |
timeout = 10000; |
820 |
> |
#endif |
821 |
|
tv.tv_sec = 0; |
822 |
< |
tv.tv_usec = 10000; |
822 |
> |
tv.tv_usec = timeout; |
823 |
|
if (select(nfds + 1, &rfds, &wfds, &xfds, &tv) >= 0) |
824 |
|
slirp_select_poll(&rfds, &wfds, &xfds); |
825 |
|
|
852 |
|
for (;;) { |
853 |
|
|
854 |
|
// Wait for packets to arrive |
855 |
< |
#if HAVE_POLL |
855 |
> |
#if USE_POLL |
856 |
|
struct pollfd pf = {fd, POLLIN, 0}; |
857 |
|
int res = poll(&pf, 1, -1); |
858 |
|
#else |
881 |
|
// Wait for interrupt acknowledge by EtherInterrupt() |
882 |
|
sem_wait(&int_ack); |
883 |
|
} else |
884 |
< |
usleep(20000); |
884 |
> |
Delay_usec(20000); |
885 |
|
} |
886 |
|
return NULL; |
887 |
|
} |