ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/ether_unix.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/ether_unix.cpp (file contents):
Revision 1.9 by gbeauche, 2004-05-09T16:11:45Z vs.
Revision 1.32 by asvitkine, 2011-12-28T20:22:25Z

# Line 1 | Line 1
1   /*
2   *  ether_unix.cpp - Ethernet device driver, Unix specific stuff (Linux and FreeBSD)
3   *
4 < *  Basilisk II (C) 1997-2004 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
# Line 20 | Line 20
20  
21   #include "sysdeps.h"
22  
23 < #include <sys/ioctl.h>
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
42 + #include <sys/ioctl.h>
43   #include <sys/socket.h>
44   #include <sys/wait.h>
45   #include <netinet/in.h>
# Line 29 | Line 47
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)
53 > #if defined(__FreeBSD__) || defined(sgi) || (defined(__APPLE__) && defined(__MACH__))
54   #include <net/if.h>
55   #endif
56  
# Line 45 | Line 64
64   #include <net/if_tun.h>
65   #endif
66  
67 + #ifdef HAVE_SLIRP
68 + #include "libslirp.h"
69 + #endif
70 +
71   #include "cpu_emulation.h"
72   #include "main.h"
73   #include "macos_util.h"
# Line 60 | Line 83 | using std::map;
83   #define DEBUG 0
84   #include "debug.h"
85  
86 + #define STATISTICS 0
87   #define MONITOR 0
88  
89  
# Line 68 | Line 92 | enum {
92          NET_IF_SHEEPNET,
93          NET_IF_ETHERTAP,
94          NET_IF_TUNTAP,
95 +        NET_IF_SLIRP
96   };
97  
98   // Constants
# Line 81 | Line 106 | static bool thread_active = false;                     //
106   static sem_t int_ack;                                           // Interrupt acknowledge semaphore
107   static bool udp_tunnel;                                         // Flag: UDP tunnelling active, fd is the socket descriptor
108   static int net_if_type = -1;                            // Ethernet device type
109 < static const char *net_if_name = NULL;          // TUN/TAP device name
109 > static char *net_if_name = NULL;                        // TUN/TAP device name
110   static const char *net_if_script = NULL;        // Network config script
111 + static pthread_t slirp_thread;                          // Slirp reception thread
112 + static bool slirp_thread_active = false;        // Flag: Slirp reception threadinstalled
113 + static int slirp_output_fd = -1;                        // fd of slirp output pipe
114 + static int slirp_input_fds[2] = { -1, -1 };     // fds of slirp input pipe
115 + #ifdef SHEEPSHAVER
116 + static bool net_open = false;                           // Flag: initialization succeeded, network device open
117 + static uint8 ether_addr[6];                                     // Our Ethernet address
118 + #else
119 + const bool ether_driver_opened = true;          // Flag: is the MacOS driver opened?
120 + #endif
121  
122   // Attached network protocols, maps protocol type to MacOS handler address
123   static map<uint16, uint32> net_protocols;
124  
125   // Prototypes
126   static void *receive_func(void *arg);
127 + static void *slirp_receive_func(void *arg);
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);
131 + static void ether_do_interrupt(void);
132  
133  
134   /*
# Line 109 | Line 149 | static bool start_thread(void)
149                  return false;
150          }
151  
152 + #ifdef HAVE_SLIRP
153 +        if (net_if_type == NET_IF_SLIRP) {
154 +                slirp_thread_active = (pthread_create(&slirp_thread, NULL, slirp_receive_func, NULL) == 0);
155 +                if (!slirp_thread_active) {
156 +                        printf("WARNING: Cannot start slirp reception thread\n");
157 +                        return false;
158 +                }
159 +        }
160 + #endif
161 +
162          return true;
163   }
164  
# Line 119 | Line 169 | static bool start_thread(void)
169  
170   static void stop_thread(void)
171   {
172 + #ifdef HAVE_SLIRP
173 +        if (slirp_thread_active) {
174 + #ifdef HAVE_PTHREAD_CANCEL
175 +                pthread_cancel(slirp_thread);
176 + #endif
177 +                pthread_join(slirp_thread, NULL);
178 +                slirp_thread_active = false;
179 +        }
180 + #endif
181 +
182          if (thread_active) {
183 + #ifdef HAVE_PTHREAD_CANCEL
184                  pthread_cancel(ether_thread);
185 + #endif
186                  pthread_join(ether_thread, NULL);
187                  sem_destroy(&int_ack);
188                  thread_active = false;
# Line 142 | Line 204 | static bool execute_network_script(const
204                  if (pid == 0) {
205                          char *args[4];
206                          args[0] = (char *)net_if_script;
207 <                        args[1] = (char *)net_if_name;
207 >                        args[1] = net_if_name;
208                          args[2] = (char *)action;
209                          args[3] = NULL;
210                          execv(net_if_script, args);
# Line 163 | Line 225 | static bool execute_network_script(const
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
# Line 179 | Line 241 | bool ether_init(void)
241          else if (strcmp(name, "tun") == 0)
242                  net_if_type = NET_IF_TUNTAP;
243   #endif
244 + #ifdef HAVE_SLIRP
245 +        else if (strcmp(name, "slirp") == 0)
246 +                net_if_type = NET_IF_SLIRP;
247 + #endif
248          else
249                  net_if_type = NET_IF_SHEEPNET;
250  
251 <        // Open sheep_net or ethertap device
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) {
264 >                if (slirp_init() < 0) {
265 >                        sprintf(str, GetString(STR_SLIRP_NO_DNS_FOUND_WARN));
266 >                        WarningAlert(str);
267 >                        return false;
268 >                }
269 >
270 >                // Open slirp output pipe
271 >                int fds[2];
272 >                if (pipe(fds) < 0)
273 >                        return false;
274 >                fd = fds[0];
275 >                slirp_output_fd = fds[1];
276 >
277 >                // Open slirp input pipe
278 >                if (pipe(slirp_input_fds) < 0)
279 >                        return false;
280 >        }
281 > #endif
282 >
283 >        // Open sheep_net or ethertap or TUN/TAP device
284          char dev_name[16];
285          switch (net_if_type) {
286          case NET_IF_ETHERTAP:
287                  sprintf(dev_name, "/dev/%s", name);
288                  break;
289          case NET_IF_TUNTAP:
290 <                sprintf(dev_name, "/dev/net/tun", name);
290 >                strcpy(dev_name, "/dev/net/tun");
291                  break;
292          case NET_IF_SHEEPNET:
293                  strcpy(dev_name, "/dev/sheep_net");
294                  break;
295          }
296 <        fd = open(dev_name, O_RDWR);
297 <        if (fd < 0) {
298 <                sprintf(str, GetString(STR_NO_SHEEP_NET_DRIVER_WARN), dev_name, strerror(errno));
299 <                WarningAlert(str);
300 <                goto open_error;
296 >        if (net_if_type != NET_IF_SLIRP) {
297 >                fd = open(dev_name, O_RDWR);
298 >                if (fd < 0) {
299 >                        sprintf(str, GetString(STR_NO_SHEEP_NET_DRIVER_WARN), dev_name, strerror(errno));
300 >                        WarningAlert(str);
301 >                        goto open_error;
302 >                }
303          }
304  
305   #if ENABLE_TUNTAP
# Line 226 | Line 326 | bool ether_init(void)
326                          WarningAlert(str);
327                          goto open_error;
328                  }
329 <                net_if_name = ifr.ifr_name;
329 >                net_if_name = strdup(ifr.ifr_name);
330                  if (!execute_network_script("up")) {
331                          sprintf(str, GetString(STR_TUN_TAP_CONFIG_WARN), "script execute error");
332                          WarningAlert(str);
# Line 246 | Line 346 | bool ether_init(void)
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) {
# Line 257 | Line 370 | bool ether_init(void)
370                  ether_addr[3] = p >> 16;
371                  ether_addr[4] = p >> 8;
372                  ether_addr[5] = p;
373 + #ifdef HAVE_SLIRP
374 +        } else if (net_if_type == NET_IF_SLIRP) {
375 +                ether_addr[0] = 0x52;
376 +                ether_addr[1] = 0x54;
377 +                ether_addr[2] = 0x00;
378 +                ether_addr[3] = 0x12;
379 +                ether_addr[4] = 0x34;
380 +                ether_addr[5] = 0x56;
381 + #endif
382          } else
383                  ioctl(fd, SIOCGIFADDR, ether_addr);
384          D(bug("Ethernet address %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5]));
# Line 271 | Line 393 | bool ether_init(void)
393   open_error:
394          stop_thread();
395  
274        if (net_if_type == NET_IF_TUNTAP)
275                execute_network_script("down");
276
396          if (fd > 0) {
397                  close(fd);
398                  fd = -1;
399          }
400 +        if (slirp_input_fds[0] >= 0) {
401 +                close(slirp_input_fds[0]);
402 +                slirp_input_fds[0] = -1;
403 +        }
404 +        if (slirp_input_fds[1] >= 0) {
405 +                close(slirp_input_fds[1]);
406 +                slirp_input_fds[1] = -1;
407 +        }
408 +        if (slirp_output_fd >= 0) {
409 +                close(slirp_output_fd);
410 +                slirp_output_fd = -1;
411 +        }
412          return false;
413   }
414  
# Line 288 | Line 419 | open_error:
419  
420   void ether_exit(void)
421   {
422 <        // Stop reception thread
423 <        if (thread_active) {
424 <                pthread_cancel(ether_thread);
425 <                pthread_join(ether_thread, NULL);
426 <                sem_destroy(&int_ack);
427 <                thread_active = false;
428 <        }
422 >        // Stop reception threads
423 >        stop_thread();
424 >
425 >        // Shut down TUN/TAP interface
426 >        if (net_if_type == NET_IF_TUNTAP)
427 >                execute_network_script("down");
428 >
429 >        // Free TUN/TAP device name
430 >        if (net_if_name)
431 >                free(net_if_name);
432  
433          // Close sheep_net device
434          if (fd > 0)
435                  close(fd);
436 +
437 +        // Close slirp input buffer
438 +        if (slirp_input_fds[0] >= 0)
439 +                close(slirp_input_fds[0]);
440 +        if (slirp_input_fds[1] >= 0)
441 +                close(slirp_input_fds[1]);
442 +
443 +        // Close slirp output buffer
444 +        if (slirp_output_fd > 0)
445 +                close(slirp_output_fd);
446 +
447 + #if STATISTICS
448 +        // Show statistics
449 +        printf("%ld messages put on write queue\n", num_wput);
450 +        printf("%ld error acks\n", num_error_acks);
451 +        printf("%ld packets transmitted (%ld raw, %ld normal)\n", num_tx_packets, num_tx_raw_packets, num_tx_normal_packets);
452 +        printf("%ld tx packets dropped because buffer full\n", num_tx_buffer_full);
453 +        printf("%ld packets received\n", num_rx_packets);
454 +        printf("%ld packets passed upstream (%ld Fast Path, %ld normal)\n", num_rx_fastpath + num_unitdata_ind, num_rx_fastpath, num_unitdata_ind);
455 +        printf("EtherIRQ called %ld times\n", num_ether_irq);
456 +        printf("%ld rx packets dropped due to low memory\n", num_rx_no_mem);
457 +        printf("%ld rx packets dropped because no stream found\n", num_rx_dropped);
458 +        printf("%ld rx packets dropped because stream not ready\n", num_rx_stream_not_ready);
459 +        printf("%ld rx packets dropped because no memory for unitdata_ind\n", num_rx_no_unitdata_mem);
460 + #endif
461 + }
462 +
463 +
464 + /*
465 + *  Glue around low-level implementation
466 + */
467 +
468 + #ifdef SHEEPSHAVER
469 + // Error codes
470 + enum {
471 +        eMultiErr               = -91,
472 +        eLenErr                 = -92,
473 +        lapProtErr              = -94,
474 +        excessCollsns   = -95
475 + };
476 +
477 + // Initialize ethernet
478 + void EtherInit(void)
479 + {
480 +        net_open = false;
481 +
482 +        // Do nothing if the user disabled the network
483 +        if (PrefsFindBool("nonet"))
484 +                return;
485 +
486 +        net_open = ether_init();
487 + }
488 +
489 + // Exit ethernet
490 + void EtherExit(void)
491 + {
492 +        ether_exit();
493 +        net_open = false;
494 + }
495 +
496 + // Get ethernet hardware address
497 + void AO_get_ethernet_address(uint32 arg)
498 + {
499 +        uint8 *addr = Mac2HostAddr(arg);
500 +        if (net_open)
501 +                OTCopy48BitAddress(ether_addr, addr);
502 +        else {
503 +                addr[0] = 0x12;
504 +                addr[1] = 0x34;
505 +                addr[2] = 0x56;
506 +                addr[3] = 0x78;
507 +                addr[4] = 0x9a;
508 +                addr[5] = 0xbc;
509 +        }
510 +        D(bug("AO_get_ethernet_address: got address %02x%02x%02x%02x%02x%02x\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]));
511 + }
512 +
513 + // Add multicast address
514 + void AO_enable_multicast(uint32 addr)
515 + {
516 +        if (net_open)
517 +                ether_do_add_multicast(Mac2HostAddr(addr));
518 + }
519 +
520 + // Disable multicast address
521 + void AO_disable_multicast(uint32 addr)
522 + {
523 +        if (net_open)
524 +                ether_do_del_multicast(Mac2HostAddr(addr));
525 + }
526 +
527 + // Transmit one packet
528 + void AO_transmit_packet(uint32 mp)
529 + {
530 +        if (net_open) {
531 +                switch (ether_do_write(mp)) {
532 +                case noErr:
533 +                        num_tx_packets++;
534 +                        break;
535 +                case excessCollsns:
536 +                        num_tx_buffer_full++;
537 +                        break;
538 +                }
539 +        }
540 + }
541 +
542 + // Copy packet data from message block to linear buffer
543 + static inline int ether_arg_to_buffer(uint32 mp, uint8 *p)
544 + {
545 +        return ether_msgb_to_buffer(mp, p);
546 + }
547 +
548 + // Ethernet interrupt
549 + void EtherIRQ(void)
550 + {
551 +        D(bug("EtherIRQ\n"));
552 +        num_ether_irq++;
553 +
554 +        OTEnterInterrupt();
555 +        ether_do_interrupt();
556 +        OTLeaveInterrupt();
557 +
558 +        // Acknowledge interrupt to reception thread
559 +        D(bug(" EtherIRQ done\n"));
560 +        sem_post(&int_ack);
561 + }
562 + #else
563 + // Add multicast address
564 + int16 ether_add_multicast(uint32 pb)
565 + {
566 +        return ether_do_add_multicast(Mac2HostAddr(pb + eMultiAddr));
567 + }
568 +
569 + // Disable multicast address
570 + int16 ether_del_multicast(uint32 pb)
571 + {
572 +        return ether_do_del_multicast(Mac2HostAddr(pb + eMultiAddr));
573 + }
574 +
575 + // Transmit one packet
576 + int16 ether_write(uint32 wds)
577 + {
578 +        return ether_do_write(wds);
579   }
580  
581 + // Copy packet data from WDS to linear buffer
582 + static inline int ether_arg_to_buffer(uint32 wds, uint8 *p)
583 + {
584 +        return ether_wds_to_buffer(wds, p);
585 + }
586 +
587 + // Dispatch packet to protocol handler
588 + static void ether_dispatch_packet(uint32 p, uint32 length)
589 + {
590 +        // Get packet type
591 +        uint16 type = ReadMacInt16(p + 12);
592 +
593 +        // Look for protocol
594 +        uint16 search_type = (type <= 1500 ? 0 : type);
595 +        if (net_protocols.find(search_type) == net_protocols.end())
596 +                return;
597 +        uint32 handler = net_protocols[search_type];
598 +
599 +        // No default handler
600 +        if (handler == 0)
601 +                return;
602 +
603 +        // Copy header to RHA
604 +        Mac2Mac_memcpy(ether_data + ed_RHA, p, 14);
605 +        D(bug(" header %08x%04x %08x%04x %04x\n", ReadMacInt32(ether_data + ed_RHA), ReadMacInt16(ether_data + ed_RHA + 4), ReadMacInt32(ether_data + ed_RHA + 6), ReadMacInt16(ether_data + ed_RHA + 10), ReadMacInt16(ether_data + ed_RHA + 12)));
606 +
607 +        // Call protocol handler
608 +        M68kRegisters r;
609 +        r.d[0] = type;                                                                  // Packet type
610 +        r.d[1] = length - 14;                                                   // Remaining packet length (without header, for ReadPacket)
611 +        r.a[0] = p + 14;                                                                // Pointer to packet (Mac address, for ReadPacket)
612 +        r.a[3] = ether_data + ed_RHA + 14;                              // Pointer behind header in RHA
613 +        r.a[4] = ether_data + ed_ReadPacket;                    // Pointer to ReadPacket/ReadRest routines
614 +        D(bug(" calling protocol handler %08x, type %08x, length %08x, data %08x, rha %08x, read_packet %08x\n", handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4]));
615 +        Execute68k(handler, &r);
616 + }
617 +
618 + // Ethernet interrupt
619 + void EtherInterrupt(void)
620 + {
621 +        D(bug("EtherIRQ\n"));
622 +        ether_do_interrupt();
623 +
624 +        // Acknowledge interrupt to reception thread
625 +        D(bug(" EtherIRQ done\n"));
626 +        sem_post(&int_ack);
627 + }
628 + #endif
629 +
630  
631   /*
632   *  Reset
# Line 316 | Line 642 | void ether_reset(void)
642   *  Add multicast address
643   */
644  
645 < int16 ether_add_multicast(uint32 pb)
645 > static int16 ether_do_add_multicast(uint8 *addr)
646   {
647 <        if (net_if_type != NET_IF_TUNTAP && ioctl(fd, SIOCADDMULTI, Mac2HostAddr(pb + eMultiAddr)) < 0) {
648 <                D(bug("WARNING: Couldn't enable multicast address\n"));
649 <                if (net_if_type == NET_IF_ETHERTAP)
650 <                        return noErr;
651 <                else
652 <                        return eMultiErr;
653 <        } else
647 >        switch (net_if_type) {
648 >        case NET_IF_ETHERTAP:
649 >        case NET_IF_SHEEPNET:
650 >                if (ioctl(fd, SIOCADDMULTI, addr) < 0) {
651 >                        D(bug("WARNING: Couldn't enable multicast address\n"));
652 >                        if (net_if_type == NET_IF_ETHERTAP)
653 >                                return noErr;
654 >                        else
655 >                                return eMultiErr;
656 >                }
657 >        default:
658                  return noErr;
659 +        }
660   }
661  
662  
# Line 333 | Line 664 | int16 ether_add_multicast(uint32 pb)
664   *  Delete multicast address
665   */
666  
667 < int16 ether_del_multicast(uint32 pb)
667 > static int16 ether_do_del_multicast(uint8 *addr)
668   {
669 <        if (net_if_type != NET_IF_TUNTAP && ioctl(fd, SIOCDELMULTI, Mac2HostAddr(pb + eMultiAddr)) < 0) {
670 <                D(bug("WARNING: Couldn't disable multicast address\n"));
671 <                return eMultiErr;
672 <        } else
669 >        switch (net_if_type) {
670 >        case NET_IF_ETHERTAP:
671 >        case NET_IF_SHEEPNET:
672 >                if (ioctl(fd, SIOCDELMULTI, addr) < 0) {
673 >                        D(bug("WARNING: Couldn't disable multicast address\n"));
674 >                        return eMultiErr;
675 >                }
676 >        default:
677                  return noErr;
678 +        }
679   }
680  
681  
# Line 372 | Line 708 | int16 ether_detach_ph(uint16 type)
708   *  Transmit raw ethernet packet
709   */
710  
711 < int16 ether_write(uint32 wds)
711 > static int16 ether_do_write(uint32 arg)
712   {
713          // Copy packet to buffer
714          uint8 packet[1516], *p = packet;
# Line 384 | Line 720 | int16 ether_write(uint32 wds)
720                  len += 2;
721          }
722   #endif
723 <        len += ether_wds_to_buffer(wds, p);
723 >        len += ether_arg_to_buffer(arg, p);
724  
725   #if MONITOR
726          bug("Sending Ethernet packet:\n");
# Line 395 | Line 731 | int16 ether_write(uint32 wds)
731   #endif
732  
733          // Transmit packet
734 + #ifdef HAVE_SLIRP
735 +        if (net_if_type == NET_IF_SLIRP) {
736 +                const int slirp_input_fd = slirp_input_fds[1];
737 +                write(slirp_input_fd, &len, sizeof(len));
738 +                write(slirp_input_fd, packet, len);
739 +                return noErr;
740 +        } else
741 + #endif
742          if (write(fd, packet, len) < 0) {
743                  D(bug("WARNING: Couldn't transmit packet\n"));
744                  return excessCollsns;
# Line 427 | Line 771 | void ether_stop_udp_thread(void)
771  
772  
773   /*
774 + *  SLIRP output buffer glue
775 + */
776 +
777 + #ifdef HAVE_SLIRP
778 + int slirp_can_output(void)
779 + {
780 +        return 1;
781 + }
782 +
783 + void slirp_output(const uint8 *packet, int len)
784 + {
785 +        write(slirp_output_fd, packet, len);
786 + }
787 +
788 + void *slirp_receive_func(void *arg)
789 + {
790 +        const int slirp_input_fd = slirp_input_fds[0];
791 +
792 +        for (;;) {
793 +                // Wait for packets to arrive
794 +                fd_set rfds, wfds, xfds;
795 +                int nfds;
796 +                struct timeval tv;
797 +
798 +                // ... in the input queue
799 +                FD_ZERO(&rfds);
800 +                FD_SET(slirp_input_fd, &rfds);
801 +                tv.tv_sec = 0;
802 +                tv.tv_usec = 0;
803 +                if (select(slirp_input_fd + 1, &rfds, NULL, NULL, &tv) > 0) {
804 +                        int len;
805 +                        read(slirp_input_fd, &len, sizeof(len));
806 +                        uint8 packet[1516];
807 +                        assert(len <= sizeof(packet));
808 +                        read(slirp_input_fd, packet, len);
809 +                        slirp_input(packet, len);
810 +                }
811 +
812 +                // ... in the output queue
813 +                nfds = -1;
814 +                FD_ZERO(&rfds);
815 +                FD_ZERO(&wfds);
816 +                FD_ZERO(&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 = timeout;
823 +                if (select(nfds + 1, &rfds, &wfds, &xfds, &tv) >= 0)
824 +                        slirp_select_poll(&rfds, &wfds, &xfds);
825 +
826 + #ifdef HAVE_PTHREAD_TESTCANCEL
827 +                // Explicit cancellation point if select() was not covered
828 +                // This seems to be the case on MacOS X 10.2
829 +                pthread_testcancel();
830 + #endif
831 +        }
832 +        return NULL;
833 + }
834 + #else
835 + int slirp_can_output(void)
836 + {
837 +        return 0;
838 + }
839 +
840 + void slirp_output(const uint8 *packet, int len)
841 + {
842 + }
843 + #endif
844 +
845 +
846 + /*
847   *  Packet reception thread
848   */
849  
# Line 435 | Line 852 | static void *receive_func(void *arg)
852          for (;;) {
853  
854                  // Wait for packets to arrive
855 + #if USE_POLL
856                  struct pollfd pf = {fd, POLLIN, 0};
857                  int res = poll(&pf, 1, -1);
858 + #else
859 +                fd_set rfds;
860 +                FD_ZERO(&rfds);
861 +                FD_SET(fd, &rfds);
862 +                // A NULL timeout could cause select() to block indefinitely,
863 +                // even if it is supposed to be a cancellation point [MacOS X]
864 +                struct timeval tv = { 0, 20000 };
865 +                int res = select(fd + 1, &rfds, NULL, NULL, &tv);
866 + #ifdef HAVE_PTHREAD_TESTCANCEL
867 +                pthread_testcancel();
868 + #endif
869 +                if (res == 0 || (res == -1 && errno == EINTR))
870 +                        continue;
871 + #endif
872                  if (res <= 0)
873                          break;
874  
875 <                // Trigger Ethernet interrupt
876 <                D(bug(" packet received, triggering Ethernet interrupt\n"));
877 <                SetInterruptFlag(INTFLAG_ETHER);
878 <                TriggerInterrupt();
879 <
880 <                // Wait for interrupt acknowledge by EtherInterrupt()
881 <                sem_wait(&int_ack);
875 >                if (ether_driver_opened) {
876 >                        // Trigger Ethernet interrupt
877 >                        D(bug(" packet received, triggering Ethernet interrupt\n"));
878 >                        SetInterruptFlag(INTFLAG_ETHER);
879 >                        TriggerInterrupt();
880 >
881 >                        // Wait for interrupt acknowledge by EtherInterrupt()
882 >                        sem_wait(&int_ack);
883 >                } else
884 >                        Delay_usec(20000);
885          }
886          return NULL;
887   }
# Line 456 | Line 891 | static void *receive_func(void *arg)
891   *  Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers
892   */
893  
894 < void EtherInterrupt(void)
894 > void ether_do_interrupt(void)
895   {
461        D(bug("EtherIRQ\n"));
462
896          // Call protocol handler for received packets
897 <        uint8 packet[1516];
897 >        EthernetPacket ether_packet;
898 >        uint32 packet = ether_packet.addr();
899          ssize_t length;
900          for (;;) {
901  
902 + #ifndef SHEEPSHAVER
903                  if (udp_tunnel) {
904  
905                          // Read packet from socket
906                          struct sockaddr_in from;
907                          socklen_t from_len = sizeof(from);
908 <                        length = recvfrom(fd, packet, 1514, 0, (struct sockaddr *)&from, &from_len);
908 >                        length = recvfrom(fd, Mac2HostAddr(packet), 1514, 0, (struct sockaddr *)&from, &from_len);
909                          if (length < 14)
910                                  break;
911                          ether_udp_read(packet, length, &from);
912  
913 <                } else {
913 >                } else
914 > #endif
915 >                {
916  
917                          // Read packet from sheep_net device
918   #if defined(__linux__)
919 <                        length = read(fd, packet, net_if_type == NET_IF_ETHERTAP ? 1516 : 1514);
919 >                        length = read(fd, Mac2HostAddr(packet), net_if_type == NET_IF_ETHERTAP ? 1516 : 1514);
920   #else
921 <                        length = read(fd, packet, 1514);
921 >                        length = read(fd, Mac2HostAddr(packet), 1514);
922   #endif
923                          if (length < 14)
924                                  break;
# Line 489 | Line 926 | void EtherInterrupt(void)
926   #if MONITOR
927                          bug("Receiving Ethernet packet:\n");
928                          for (int i=0; i<length; i++) {
929 <                                bug("%02x ", packet[i]);
929 >                                bug("%02x ", ReadMacInt8(packet + i));
930                          }
931                          bug("\n");
932   #endif
933  
934                          // Pointer to packet data (Ethernet header)
935 <                        uint8 *p = packet;
935 >                        uint32 p = packet;
936   #if defined(__linux__)
937                          if (net_if_type == NET_IF_ETHERTAP) {
938                                  p += 2;                 // Linux ethertap has two random bytes before the packet
# Line 503 | Line 940 | void EtherInterrupt(void)
940                          }
941   #endif
942  
943 <                        // Get packet type
944 <                        uint16 type = (p[12] << 8) | p[13];
508 <
509 <                        // Look for protocol
510 <                        uint16 search_type = (type <= 1500 ? 0 : type);
511 <                        if (net_protocols.find(search_type) == net_protocols.end())
512 <                                continue;
513 <                        uint32 handler = net_protocols[search_type];
514 <
515 <                        // No default handler
516 <                        if (handler == 0)
517 <                                continue;
518 <
519 <                        // Copy header to RHA
520 <                        Host2Mac_memcpy(ether_data + ed_RHA, p, 14);
521 <                        D(bug(" header %08x%04x %08x%04x %04x\n", ReadMacInt32(ether_data + ed_RHA), ReadMacInt16(ether_data + ed_RHA + 4), ReadMacInt32(ether_data + ed_RHA + 6), ReadMacInt16(ether_data + ed_RHA + 10), ReadMacInt16(ether_data + ed_RHA + 12)));
522 <
523 <                        // Call protocol handler
524 <                        M68kRegisters r;
525 <                        r.d[0] = type;                                                                  // Packet type
526 <                        r.d[1] = length - 14;                                                   // Remaining packet length (without header, for ReadPacket)
527 <                        r.a[0] = (uint32)p + 14;                                                // Pointer to packet (host address, for ReadPacket)
528 <                        r.a[3] = ether_data + ed_RHA + 14;                              // Pointer behind header in RHA
529 <                        r.a[4] = ether_data + ed_ReadPacket;                    // Pointer to ReadPacket/ReadRest routines
530 <                        D(bug(" calling protocol handler %08x, type %08x, length %08x, data %08x, rha %08x, read_packet %08x\n", handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4]));
531 <                        Execute68k(handler, &r);
943 >                        // Dispatch packet
944 >                        ether_dispatch_packet(p, length);
945                  }
946          }
534
535        // Acknowledge interrupt to reception thread
536        D(bug(" EtherIRQ done\n"));
537        sem_post(&int_ack);
947   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines