ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/ether_windows.cpp
Revision: 1.7
Committed: 2006-05-01T10:23:47Z (18 years, 6 months ago) by gbeauche
Branch: MAIN
Changes since 1.6: +320 -15 lines
Log Message:
Add experimental TAP-Win32 support. It looks rather sluggish to me, something
is probably wrong somewhere...

File Contents

# User Rev Content
1 gbeauche 1.6 /*
2     * ether_windows.cpp - Ethernet device driver
3     *
4     * Basilisk II (C) 1997-2005 Christian Bauer
5     *
6     * Windows platform specific code copyright (C) Lauri Pesonen
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation; either version 2 of the License, or
11     * (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21     */
22    
23 gbeauche 1.7 #include "sysdeps.h"
24    
25 gbeauche 1.6 #include <process.h>
26     #include <windowsx.h>
27 gbeauche 1.7 #include <winioctl.h>
28 gbeauche 1.6 #include <ctype.h>
29    
30     #include "cpu_emulation.h"
31     #include "main.h"
32     #include "macos_util.h"
33     #include "prefs.h"
34     #include "user_strings.h"
35     #include "ether.h"
36     #include "ether_defs.h"
37     #include "b2ether/multiopt.h"
38     #include "b2ether/inc/b2ether_hl.h"
39     #include "ether_windows.h"
40     #include "router/router.h"
41     #include "kernel_windows.h"
42     #include "libslirp.h"
43    
44     // Define to let the slirp library determine the right timeout for select()
45     #define USE_SLIRP_TIMEOUT 1
46    
47    
48     #define DEBUG 0
49     #define MONITOR 0
50    
51     #if DEBUG
52     #pragma optimize("",off)
53     #endif
54    
55     #include "debug.h"
56    
57    
58     // Ethernet device types
59     enum {
60     NET_IF_B2ETHER,
61     NET_IF_ROUTER,
62     NET_IF_SLIRP,
63 gbeauche 1.7 NET_IF_TAP,
64 gbeauche 1.6 NET_IF_FAKE,
65     };
66    
67 gbeauche 1.7 // TAP-Win32 constants
68     #define TAP_VERSION_MIN_MAJOR 7
69     #define TAP_VERSION_MIN_MINOR 1
70    
71     #define TAP_CONTROL_CODE(request, method) \
72     CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
73    
74     #define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED)
75     #define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED)
76     #define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED)
77     #define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED)
78     #define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
79     #define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED)
80     #define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED)
81     #define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED)
82     #define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED)
83    
84     #define OLD_TAP_CONTROL_CODE(request, method) \
85     CTL_CODE (FILE_DEVICE_PHYSICAL_NETCARD | 8000, request, method, FILE_ANY_ACCESS)
86    
87     #define OLD_TAP_IOCTL_GET_VERSION OLD_TAP_CONTROL_CODE (3, METHOD_BUFFERED)
88    
89 gbeauche 1.6 // Options
90     bool ether_use_permanent = true;
91     static int16 ether_multi_mode = ETHER_MULTICAST_MAC;
92    
93     // Global variables
94     HANDLE ether_th;
95     unsigned int ether_tid;
96     HANDLE ether_th1;
97     HANDLE ether_th2;
98 gbeauche 1.7 static int net_if_type = -1; // Ethernet device type
99 gbeauche 1.6 #ifdef SHEEPSHAVER
100 gbeauche 1.7 static bool net_open = false; // Flag: initialization succeeded, network device open
101     uint8 ether_addr[6]; // Our Ethernet address
102 gbeauche 1.6 #endif
103    
104     // These are protected by queue_csection
105     // Controls transfer for read thread to feed thread
106     static CRITICAL_SECTION queue_csection;
107     typedef struct _win_queue_t {
108     uint8 *buf;
109     int sz;
110     } win_queue_t;
111     #define MAX_QUEUE_ITEMS 1024
112     static win_queue_t queue[MAX_QUEUE_ITEMS];
113     static int queue_head = 0;
114     static int queue_inx = 0;
115     static bool wait_request = true;
116    
117    
118    
119     // Read thread protected packet pool
120     static CRITICAL_SECTION fetch_csection;
121     // Some people use pools as large as 64.
122     #define PACKET_POOL_COUNT 10
123     static LPPACKET packets[PACKET_POOL_COUNT];
124     static bool wait_request2 = false;
125    
126    
127    
128     // Write thread packet queue
129     static CRITICAL_SECTION send_csection;
130     static LPPACKET send_queue = 0;
131    
132    
133     // Write thread free packet pool
134     static CRITICAL_SECTION wpool_csection;
135     static LPPACKET write_packet_pool = 0;
136    
137    
138    
139     // Try to deal with echos. Protected by fetch_csection.
140     // The code should be moved to the driver. No need to lift
141     // the echo packets to the application level.
142     // MAX_ECHO must be a power of two.
143     #define MAX_ECHO (1<<2)
144     static int echo_count = 0;
145     typedef uint8 echo_t[1514];
146     static echo_t pending_packet[MAX_ECHO];
147     static int pending_packet_sz[MAX_ECHO];
148    
149    
150     // List of attached protocols
151     struct NetProtocol {
152     NetProtocol *next;
153     uint16 type;
154     uint32 handler;
155     };
156    
157     static NetProtocol *prot_list = NULL;
158    
159    
160     static LPADAPTER fd = 0;
161     static bool thread_active = false;
162     static bool thread_active_1 = false;
163     static bool thread_active_2 = false;
164     static bool thread_active_3 = false;
165     static HANDLE int_ack = 0;
166     static HANDLE int_sig = 0;
167     static HANDLE int_sig2 = 0;
168     static HANDLE int_send_now = 0;
169    
170     // Prototypes
171 gbeauche 1.7 static LPADAPTER tap_open_adapter(const char *dev_name);
172     static void tap_close_adapter(LPADAPTER fd);
173     static bool tap_check_version(LPADAPTER fd);
174     static bool tap_set_status(LPADAPTER fd, ULONG status);
175     static bool tap_get_mac(LPADAPTER fd, LPBYTE addr);
176     static bool tap_receive_packet(LPADAPTER fd, LPPACKET lpPacket, BOOLEAN Sync);
177     static bool tap_send_packet(LPADAPTER fd, LPPACKET lpPacket, BOOLEAN Sync, BOOLEAN recycle);
178 gbeauche 1.6 static WINAPI unsigned int slirp_receive_func(void *arg);
179     static WINAPI unsigned int ether_thread_feed_int(void *arg);
180     static WINAPI unsigned int ether_thread_get_packets_nt(void *arg);
181     static WINAPI unsigned int ether_thread_write_packets(void *arg);
182     static void init_queue(void);
183     static void final_queue(void);
184     static bool allocate_read_packets(void);
185     static void free_read_packets(void);
186     static void free_write_packets(void);
187     static int16 ether_do_add_multicast(uint8 *addr);
188     static int16 ether_do_del_multicast(uint8 *addr);
189     static int16 ether_do_write(uint32 arg);
190     static void ether_do_interrupt(void);
191    
192    
193     /*
194     * Find protocol in list
195     */
196    
197     static NetProtocol *find_protocol(uint16 type)
198     {
199     // All 802.2 types are the same
200     if (type <= 1500)
201     type = 0;
202    
203     // Search list (we could use hashing here but there are usually only three
204     // handlers installed: 0x0000 for AppleTalk and 0x0800/0x0806 for TCP/IP)
205     NetProtocol *p = prot_list;
206     while (p) {
207     if (p->type == type)
208     return p;
209     p = p->next;
210     }
211     return NULL;
212     }
213    
214    
215     /*
216     * Initialization
217     */
218    
219     bool ether_init(void)
220     {
221     char str[256];
222    
223     // Do nothing if no Ethernet device specified
224     const char *name = PrefsFindString("ether");
225     if (name == NULL)
226     return false;
227    
228     ether_multi_mode = PrefsFindInt32("ethermulticastmode");
229     ether_use_permanent = PrefsFindBool("etherpermanentaddress");
230    
231     // Determine Ethernet device type
232     net_if_type = -1;
233     if (strcmp(name, "router") == 0)
234     net_if_type = NET_IF_ROUTER;
235     else if (strcmp(name, "slirp") == 0)
236     net_if_type = NET_IF_SLIRP;
237 gbeauche 1.7 else if (strcmp(name, "tap") == 0)
238     net_if_type = NET_IF_TAP;
239 gbeauche 1.6 else
240     net_if_type = NET_IF_B2ETHER;
241    
242     // Initialize NAT-Router
243     if (net_if_type == NET_IF_ROUTER) {
244     if (!router_init())
245     net_if_type = NET_IF_FAKE;
246     }
247    
248     // Initialize slirp library
249     if (net_if_type == NET_IF_SLIRP) {
250     if (slirp_init() < 0) {
251     sprintf(str, GetString(STR_SLIRP_NO_DNS_FOUND_WARN));
252     WarningAlert(str);
253     return false;
254     }
255     }
256    
257     // Open ethernet device
258     const char *dev_name;
259     switch (net_if_type) {
260     case NET_IF_B2ETHER:
261     dev_name = PrefsFindString("etherguid");
262     break;
263 gbeauche 1.7 case NET_IF_TAP:
264     dev_name = PrefsFindString("etherguid");
265     break;
266 gbeauche 1.6 }
267     if (net_if_type == NET_IF_B2ETHER) {
268     if (dev_name == NULL) {
269     WarningAlert("No ethernet device GUID specified. Ethernet is not available.");
270     goto open_error;
271     }
272    
273     fd = PacketOpenAdapter( dev_name, ether_multi_mode );
274     if (!fd) {
275     sprintf(str, "Could not open ethernet adapter %s.", dev_name);
276     WarningAlert(str);
277     goto open_error;
278     }
279    
280     // Get Ethernet address
281     if(!PacketGetMAC(fd,ether_addr,ether_use_permanent)) {
282     sprintf(str, "Could not get hardware address of device %s. Ethernet is not available.", dev_name);
283     WarningAlert(str);
284     goto open_error;
285     }
286     D(bug("Real 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]));
287    
288     const char *ether_fake_address;
289     ether_fake_address = PrefsFindString("etherfakeaddress");
290     if(ether_fake_address && strlen(ether_fake_address) == 12) {
291     char sm[10];
292     strcpy( sm, "0x00" );
293     for( int i=0; i<6; i++ ) {
294     sm[2] = ether_fake_address[i*2];
295     sm[3] = ether_fake_address[i*2+1];
296     ether_addr[i] = (uint8)strtoul(sm,0,0);
297     }
298     D(bug("Fake 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]));
299     }
300     }
301 gbeauche 1.7 else if (net_if_type == NET_IF_TAP) {
302     if (dev_name == NULL) {
303     WarningAlert("No ethernet device GUID specified. Ethernet is not available.");
304     goto open_error;
305     }
306    
307     fd = tap_open_adapter(dev_name);
308     if (!fd) {
309     sprintf(str, "Could not open ethernet adapter %s.", dev_name);
310     WarningAlert(str);
311     goto open_error;
312     }
313    
314     if (!tap_check_version(fd)) {
315     sprintf(str, "Minimal TAP-Win32 version supported is %d.%d.", TAP_VERSION_MIN_MAJOR, TAP_VERSION_MIN_MINOR);
316     WarningAlert(str);
317     goto open_error;
318     }
319    
320     if (!tap_set_status(fd, true)) {
321     sprintf(str, "Could not set media status to connected.");
322     WarningAlert(str);
323     goto open_error;
324     }
325    
326     if (!tap_get_mac(fd, ether_addr)) {
327     sprintf(str, "Could not get hardware address of device %s. Ethernet is not available.", dev_name);
328     WarningAlert(str);
329     goto open_error;
330     }
331     D(bug("Real 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]));
332    
333     const char *ether_fake_address;
334     ether_fake_address = PrefsFindString("etherfakeaddress");
335     if (ether_fake_address && strlen(ether_fake_address) == 12) {
336     char sm[10];
337     strcpy( sm, "0x00" );
338     for( int i=0; i<6; i++ ) {
339     sm[2] = ether_fake_address[i*2];
340     sm[3] = ether_fake_address[i*2+1];
341     ether_addr[i] = (uint8)strtoul(sm,0,0);
342     }
343     }
344     #if 1
345     /*
346     If we bridge the underlying ethernet connection and the TAP
347     device altogether, we have to use a fake address.
348     */
349     else {
350     ether_addr[0] = 0x52;
351     ether_addr[1] = 0x54;
352     ether_addr[2] = 0x00;
353     }
354     #endif
355     D(bug("Fake 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]));
356     }
357 gbeauche 1.6 else if (net_if_type == NET_IF_SLIRP) {
358     ether_addr[0] = 0x52;
359     ether_addr[1] = 0x54;
360     ether_addr[2] = 0x00;
361     ether_addr[3] = 0x12;
362     ether_addr[4] = 0x34;
363     ether_addr[5] = 0x56;
364     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]));
365     }
366     else {
367     memcpy( ether_addr, router_mac_addr, 6 );
368     D(bug("Fake ethernet address (same as router) %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]));
369     }
370    
371     // Start packet reception thread
372     int_ack = CreateSemaphore( 0, 0, 1, NULL);
373     if(!int_ack) {
374     WarningAlert("WARNING: Cannot create int_ack semaphore");
375     goto open_error;
376     }
377    
378     // nonsignaled
379     int_sig = CreateSemaphore( 0, 0, 1, NULL);
380     if(!int_sig) {
381     WarningAlert("WARNING: Cannot create int_sig semaphore");
382     goto open_error;
383     }
384    
385     int_sig2 = CreateSemaphore( 0, 0, 1, NULL);
386     if(!int_sig2) {
387     WarningAlert("WARNING: Cannot create int_sig2 semaphore");
388     goto open_error;
389     }
390    
391     int_send_now = CreateSemaphore( 0, 0, 1, NULL);
392     if(!int_send_now) {
393     WarningAlert("WARNING: Cannot create int_send_now semaphore");
394     goto open_error;
395     }
396    
397     init_queue();
398    
399     if(!allocate_read_packets()) goto open_error;
400    
401     // No need to enter wait state if we can avoid it.
402     // These all terminate fast.
403    
404     if(pfnInitializeCriticalSectionAndSpinCount) {
405     pfnInitializeCriticalSectionAndSpinCount( &fetch_csection, 5000 );
406     } else {
407     InitializeCriticalSection( &fetch_csection );
408     }
409     if(pfnInitializeCriticalSectionAndSpinCount) {
410     pfnInitializeCriticalSectionAndSpinCount( &queue_csection, 5000 );
411     } else {
412     InitializeCriticalSection( &queue_csection );
413     }
414     if(pfnInitializeCriticalSectionAndSpinCount) {
415     pfnInitializeCriticalSectionAndSpinCount( &send_csection, 5000 );
416     } else {
417     InitializeCriticalSection( &send_csection );
418     }
419     if(pfnInitializeCriticalSectionAndSpinCount) {
420     pfnInitializeCriticalSectionAndSpinCount( &wpool_csection, 5000 );
421     } else {
422     InitializeCriticalSection( &wpool_csection );
423     }
424    
425     ether_th = (HANDLE)_beginthreadex( 0, 0, ether_thread_feed_int, 0, 0, &ether_tid );
426     if (!ether_th) {
427     D(bug("Failed to create ethernet thread\n"));
428     goto open_error;
429     }
430     thread_active = true;
431    
432     unsigned int dummy;
433 gbeauche 1.7 unsigned int (WINAPI *receive_func)(void *);
434     switch (net_if_type) {
435     case NET_IF_SLIRP:
436     receive_func = slirp_receive_func;
437     break;
438     default:
439     receive_func = ether_thread_get_packets_nt;
440     break;
441     }
442     ether_th2 = (HANDLE)_beginthreadex( 0, 0, receive_func, 0, 0, &dummy );
443 gbeauche 1.6 ether_th1 = (HANDLE)_beginthreadex( 0, 0, ether_thread_write_packets, 0, 0, &dummy );
444    
445     // Everything OK
446     return true;
447    
448     open_error:
449     if (thread_active) {
450     TerminateThread(ether_th,0);
451     ether_th = 0;
452     if (int_ack)
453     CloseHandle(int_ack);
454     int_ack = 0;
455     if(int_sig)
456     CloseHandle(int_sig);
457     int_sig = 0;
458     if(int_sig2)
459     CloseHandle(int_sig2);
460     int_sig2 = 0;
461     if(int_send_now)
462     CloseHandle(int_send_now);
463     int_send_now = 0;
464     thread_active = false;
465     }
466 gbeauche 1.7 if (fd) {
467     switch (net_if_type) {
468     case NET_IF_B2ETHER:
469     PacketCloseAdapter(fd);
470     break;
471     case NET_IF_TAP:
472     tap_close_adapter(fd);
473     break;
474     }
475     fd = 0;
476 gbeauche 1.6 }
477     return false;
478     }
479    
480    
481     /*
482     * Deinitialization
483     */
484    
485     void ether_exit(void)
486     {
487     D(bug("EtherExit\n"));
488    
489     // Stop reception thread
490     thread_active = false;
491    
492     if(int_ack) ReleaseSemaphore(int_ack,1,NULL);
493     if(int_sig) ReleaseSemaphore(int_sig,1,NULL);
494     if(int_sig2) ReleaseSemaphore(int_sig2,1,NULL);
495     if(int_send_now) ReleaseSemaphore(int_send_now,1,NULL);
496    
497     D(bug("CancelIO if needed\n"));
498     if (fd && fd->hFile && pfnCancelIo)
499     pfnCancelIo(fd->hFile);
500    
501     // Wait max 2 secs to shut down pending io. After that, kill them.
502     D(bug("Wait delay\n"));
503     for( int i=0; i<10; i++ ) {
504     if(!thread_active_1 && !thread_active_2 && !thread_active_3) break;
505     Sleep(200);
506     }
507    
508     if(thread_active_1) {
509     D(bug("Ether killing ether_th1\n"));
510     if(ether_th1) TerminateThread(ether_th1,0);
511     thread_active_1 = false;
512     }
513     if(thread_active_2) {
514     D(bug("Ether killing ether_th2\n"));
515     if(ether_th2) TerminateThread(ether_th2,0);
516     thread_active_2 = false;
517     }
518     if(thread_active_3) {
519     D(bug("Ether killing thread\n"));
520     if(ether_th) TerminateThread(ether_th,0);
521     thread_active_3 = false;
522     }
523    
524     ether_th1 = 0;
525     ether_th2 = 0;
526     ether_th = 0;
527    
528     D(bug("Closing semaphores\n"));
529     if(int_ack) {
530     CloseHandle(int_ack);
531     int_ack = 0;
532     }
533     if(int_sig) {
534     CloseHandle(int_sig);
535     int_sig = 0;
536     }
537     if(int_sig2) {
538     CloseHandle(int_sig2);
539     int_sig2 = 0;
540     }
541     if(int_send_now) {
542     CloseHandle(int_send_now);
543     int_send_now = 0;
544     }
545    
546     // Close ethernet device
547 gbeauche 1.7 if (fd) {
548     switch (net_if_type) {
549     case NET_IF_B2ETHER:
550     PacketCloseAdapter(fd);
551     break;
552     case NET_IF_TAP:
553     tap_close_adapter(fd);
554     break;
555     }
556 gbeauche 1.6 fd = 0;
557     }
558    
559     // Remove all protocols
560     D(bug("Removing protocols\n"));
561     NetProtocol *p = prot_list;
562     while (p) {
563     NetProtocol *next = p->next;
564     delete p;
565     p = next;
566     }
567     prot_list = 0;
568    
569     D(bug("Deleting sections\n"));
570     DeleteCriticalSection( &fetch_csection );
571     DeleteCriticalSection( &queue_csection );
572     DeleteCriticalSection( &send_csection );
573     DeleteCriticalSection( &wpool_csection );
574    
575     D(bug("Freeing read packets\n"));
576     free_read_packets();
577    
578     D(bug("Freeing write packets\n"));
579     free_write_packets();
580    
581     D(bug("Finalizing queue\n"));
582     final_queue();
583    
584     if (net_if_type == NET_IF_ROUTER) {
585     D(bug("Stopping router\n"));
586     router_final();
587     }
588    
589     D(bug("EtherExit done\n"));
590     }
591    
592    
593     /*
594     * Glue around low-level implementation
595     */
596    
597     #ifdef SHEEPSHAVER
598     // Error codes
599     enum {
600     eMultiErr = -91,
601     eLenErr = -92,
602     lapProtErr = -94,
603     excessCollsns = -95
604     };
605    
606     // Initialize ethernet
607     void EtherInit(void)
608     {
609     net_open = false;
610    
611     // Do nothing if the user disabled the network
612     if (PrefsFindBool("nonet"))
613     return;
614    
615     net_open = ether_init();
616     }
617    
618     // Exit ethernet
619     void EtherExit(void)
620     {
621     ether_exit();
622     net_open = false;
623     }
624    
625     // Get ethernet hardware address
626     void AO_get_ethernet_address(uint32 arg)
627     {
628     uint8 *addr = Mac2HostAddr(arg);
629     if (net_open)
630     OTCopy48BitAddress(ether_addr, addr);
631     else {
632     addr[0] = 0x12;
633     addr[1] = 0x34;
634     addr[2] = 0x56;
635     addr[3] = 0x78;
636     addr[4] = 0x9a;
637     addr[5] = 0xbc;
638     }
639     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]));
640     }
641    
642     // Add multicast address
643     void AO_enable_multicast(uint32 addr)
644     {
645     if (net_open)
646     ether_do_add_multicast(Mac2HostAddr(addr));
647     }
648    
649     // Disable multicast address
650     void AO_disable_multicast(uint32 addr)
651     {
652     if (net_open)
653     ether_do_del_multicast(Mac2HostAddr(addr));
654     }
655    
656     // Transmit one packet
657     void AO_transmit_packet(uint32 mp)
658     {
659     if (net_open) {
660     switch (ether_do_write(mp)) {
661     case noErr:
662     num_tx_packets++;
663     break;
664     case excessCollsns:
665     num_tx_buffer_full++;
666     break;
667     }
668     }
669     }
670    
671     // Copy packet data from message block to linear buffer
672     static inline int ether_arg_to_buffer(uint32 mp, uint8 *p)
673     {
674     return ether_msgb_to_buffer(mp, p);
675     }
676    
677     // Ethernet interrupt
678     void EtherIRQ(void)
679     {
680     D(bug("EtherIRQ\n"));
681     num_ether_irq++;
682    
683     OTEnterInterrupt();
684     ether_do_interrupt();
685     OTLeaveInterrupt();
686    
687     // Acknowledge interrupt to reception thread
688     D(bug(" EtherIRQ done\n"));
689     ReleaseSemaphore(int_ack,1,NULL);
690     }
691     #else
692     // Add multicast address
693     int16 ether_add_multicast(uint32 pb)
694     {
695     return ether_do_add_multicast(Mac2HostAddr(pb + eMultiAddr));
696     }
697    
698     // Disable multicast address
699     int16 ether_del_multicast(uint32 pb)
700     {
701     return ether_do_del_multicast(Mac2HostAddr(pb + eMultiAddr));
702     }
703    
704     // Transmit one packet
705     int16 ether_write(uint32 wds)
706     {
707     return ether_do_write(wds);
708     }
709    
710     // Copy packet data from WDS to linear buffer
711     static inline int ether_arg_to_buffer(uint32 wds, uint8 *p)
712     {
713     return ether_wds_to_buffer(wds, p);
714     }
715    
716     // Dispatch packet to protocol handler
717     static void ether_dispatch_packet(uint32 packet, uint32 length)
718     {
719     // Get packet type
720     uint16 type = ReadMacInt16(packet + 12);
721    
722     // Look for protocol
723     NetProtocol *prot = find_protocol(type);
724     if (prot == NULL)
725     return;
726    
727     // No default handler
728     if (prot->handler == 0)
729     return;
730    
731     // Copy header to RHA
732     Mac2Mac_memcpy(ether_data + ed_RHA, packet, 14);
733     D(bug(" header %08lx%04lx %08lx%04lx %04lx\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)));
734    
735     // Call protocol handler
736     M68kRegisters r;
737     r.d[0] = type; // Packet type
738     r.d[1] = length - 14; // Remaining packet length (without header, for ReadPacket)
739     r.a[0] = packet + 14; // Pointer to packet (Mac address, for ReadPacket)
740     r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA
741     r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines
742     D(bug(" calling protocol handler %08lx, type %08lx, length %08lx, data %08lx, rha %08lx, read_packet %08lx\n", prot->handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4]));
743     Execute68k(prot->handler, &r);
744     }
745    
746     // Ethernet interrupt
747     void EtherInterrupt(void)
748     {
749     D(bug("EtherIRQ\n"));
750     ether_do_interrupt();
751    
752     // Acknowledge interrupt to reception thread
753     D(bug(" EtherIRQ done\n"));
754     ReleaseSemaphore(int_ack,1,NULL);
755     }
756     #endif
757    
758    
759     /*
760     * Reset
761     */
762    
763     void ether_reset(void)
764     {
765     D(bug("EtherReset\n"));
766    
767     // Remove all protocols
768     NetProtocol *p = prot_list;
769     while (p) {
770     NetProtocol *next = p->next;
771     delete p;
772     p = next;
773     }
774     prot_list = NULL;
775     }
776    
777    
778     /*
779     * Add multicast address
780     */
781    
782     static int16 ether_do_add_multicast(uint8 *addr)
783     {
784     D(bug("ether_add_multicast\n"));
785    
786     // We wouldn't need to do this
787     // if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr;
788    
789     switch (net_if_type) {
790     case NET_IF_B2ETHER:
791     if (!PacketAddMulticast( fd, addr)) {
792     D(bug("WARNING: couldn't enable multicast address\n"));
793     return eMultiErr;
794     }
795     default:
796     D(bug("ether_add_multicast: noErr\n"));
797     return noErr;
798     }
799     }
800    
801    
802     /*
803     * Delete multicast address
804     */
805    
806     int16 ether_do_del_multicast(uint8 *addr)
807     {
808     D(bug("ether_del_multicast\n"));
809    
810     // We wouldn't need to do this
811     // if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr;
812    
813     switch (net_if_type) {
814     case NET_IF_B2ETHER:
815     if (!PacketDelMulticast( fd, addr)) {
816     D(bug("WARNING: couldn't disable multicast address\n"));
817     return eMultiErr;
818     }
819     default:
820     return noErr;
821     }
822     }
823    
824    
825     /*
826     * Attach protocol handler
827     */
828    
829     int16 ether_attach_ph(uint16 type, uint32 handler)
830     {
831     D(bug("ether_attach_ph type=0x%x, handler=0x%x\n",(int)type,handler));
832    
833     // Already attached?
834     NetProtocol *p = find_protocol(type);
835     if (p != NULL) {
836     D(bug("ether_attach_ph: lapProtErr\n"));
837     return lapProtErr;
838     } else {
839     // No, create and attach
840     p = new NetProtocol;
841     p->next = prot_list;
842     p->type = type;
843     p->handler = handler;
844     prot_list = p;
845     D(bug("ether_attach_ph: noErr\n"));
846     return noErr;
847     }
848     }
849    
850    
851     /*
852     * Detach protocol handler
853     */
854    
855     int16 ether_detach_ph(uint16 type)
856     {
857     D(bug("ether_detach_ph type=%08lx\n",(int)type));
858    
859     NetProtocol *p = find_protocol(type);
860     if (p != NULL) {
861     NetProtocol *previous = 0;
862     NetProtocol *q = prot_list;
863     while(q) {
864     if (q == p) {
865     if(previous) {
866     previous->next = q->next;
867     } else {
868     prot_list = q->next;
869     }
870     delete p;
871     return noErr;
872     }
873     previous = q;
874     q = q->next;
875     }
876     }
877     return lapProtErr;
878     }
879    
880     #if MONITOR
881     static void dump_packet( uint8 *packet, int length )
882     {
883     char buf[1000], sm[10];
884    
885     *buf = 0;
886    
887     if(length > 256) length = 256;
888    
889     for (int i=0; i<length; i++) {
890     sprintf(sm," %02x", (int)packet[i]);
891     strcat( buf, sm );
892     }
893     strcat( buf, "\n" );
894     bug(buf);
895     }
896     #endif
897    
898    
899     /*
900     * Transmit raw ethernet packet
901     */
902    
903     static void insert_send_queue( LPPACKET Packet )
904     {
905     EnterCriticalSection( &send_csection );
906     Packet->next = 0;
907     if(send_queue) {
908     LPPACKET p = send_queue;
909     // The queue is short. It would be larger overhead to double-link it.
910     while(p->next) p = p->next;
911     p->next = Packet;
912     } else {
913     send_queue = Packet;
914     }
915     LeaveCriticalSection( &send_csection );
916     }
917    
918     static LPPACKET get_send_head( void )
919     {
920     LPPACKET Packet = 0;
921    
922     EnterCriticalSection( &send_csection );
923     if(send_queue) {
924     Packet = send_queue;
925     send_queue = send_queue->next;
926     }
927     LeaveCriticalSection( &send_csection );
928    
929     return Packet;
930     }
931    
932     static int get_write_packet_pool_sz( void )
933     {
934     LPPACKET t = write_packet_pool;
935     int sz = 0;
936    
937     while(t) {
938     t = t->next;
939     sz++;
940     }
941     return(sz);
942     }
943    
944     static void free_write_packets( void )
945     {
946     LPPACKET next;
947     int i = 0;
948     while(write_packet_pool) {
949     next = write_packet_pool->next;
950     D(bug("Freeing write packet %ld\n",++i));
951     PacketFreePacket(write_packet_pool);
952     write_packet_pool = next;
953     }
954     }
955    
956     void recycle_write_packet( LPPACKET Packet )
957     {
958     EnterCriticalSection( &wpool_csection );
959     Packet->next = write_packet_pool;
960     write_packet_pool = Packet;
961     D(bug("Pool size after recycling = %ld\n",get_write_packet_pool_sz()));
962     LeaveCriticalSection( &wpool_csection );
963     }
964    
965     static LPPACKET get_write_packet( UINT len )
966     {
967     LPPACKET Packet = 0;
968    
969     EnterCriticalSection( &wpool_csection );
970     if(write_packet_pool) {
971     Packet = write_packet_pool;
972     write_packet_pool = write_packet_pool->next;
973     Packet->OverLapped.Offset = 0;
974     Packet->OverLapped.OffsetHigh = 0;
975     Packet->Length = len;
976     Packet->BytesReceived = 0;
977     Packet->bIoComplete = FALSE;
978     Packet->free = TRUE;
979     Packet->next = 0;
980     // actually an auto-reset event.
981     if(Packet->OverLapped.hEvent) ResetEvent(Packet->OverLapped.hEvent);
982     } else {
983     Packet = PacketAllocatePacket(fd,len);
984     }
985    
986     D(bug("Pool size after get wr packet = %ld\n",get_write_packet_pool_sz()));
987    
988     LeaveCriticalSection( &wpool_csection );
989    
990     return Packet;
991     }
992    
993     static unsigned int ether_thread_write_packets(void *arg)
994     {
995     LPPACKET Packet;
996    
997     thread_active_1 = true;
998    
999     D(bug("ether_thread_write_packets start\n"));
1000    
1001     while(thread_active) {
1002     // must be alertable, otherwise write completion is never called
1003     WaitForSingleObjectEx(int_send_now,INFINITE,TRUE);
1004     while( thread_active && (Packet = get_send_head()) != 0 ) {
1005     switch (net_if_type) {
1006     case NET_IF_ROUTER:
1007     if(router_write_packet((uint8 *)Packet->Buffer, Packet->Length)) {
1008     Packet->bIoComplete = TRUE;
1009     recycle_write_packet(Packet);
1010     }
1011     break;
1012     case NET_IF_FAKE:
1013     Packet->bIoComplete = TRUE;
1014     recycle_write_packet(Packet);
1015     break;
1016     case NET_IF_B2ETHER:
1017     if(!PacketSendPacket( fd, Packet, FALSE, TRUE )) {
1018     // already recycled if async
1019     }
1020     break;
1021 gbeauche 1.7 case NET_IF_TAP:
1022     if (!tap_send_packet(fd, Packet, FALSE, TRUE)) {
1023     // already recycled if async
1024     }
1025     break;
1026 gbeauche 1.6 case NET_IF_SLIRP:
1027     slirp_input((uint8 *)Packet->Buffer, Packet->Length);
1028     Packet->bIoComplete = TRUE;
1029     recycle_write_packet(Packet);
1030     break;
1031     }
1032     }
1033     }
1034    
1035     D(bug("ether_thread_write_packets exit\n"));
1036    
1037     thread_active_1 = false;
1038    
1039     return(0);
1040     }
1041    
1042     static BOOL write_packet( uint8 *packet, int len )
1043     {
1044     LPPACKET Packet;
1045    
1046     D(bug("write_packet\n"));
1047    
1048     Packet = get_write_packet(len);
1049     if(Packet) {
1050     memcpy( Packet->Buffer, packet, len );
1051    
1052     EnterCriticalSection( &fetch_csection );
1053     pending_packet_sz[echo_count] = min(sizeof(pending_packet),len);
1054     memcpy( pending_packet[echo_count], packet, pending_packet_sz[echo_count] );
1055     echo_count = (echo_count+1) & (~(MAX_ECHO-1));
1056     LeaveCriticalSection( &fetch_csection );
1057    
1058     insert_send_queue( Packet );
1059    
1060     ReleaseSemaphore(int_send_now,1,NULL);
1061     return(TRUE);
1062     } else {
1063     return(FALSE);
1064     }
1065     }
1066    
1067     static int16 ether_do_write(uint32 arg)
1068     {
1069     D(bug("ether_write\n"));
1070    
1071     // Copy packet to buffer
1072     uint8 packet[1514], *p = packet;
1073     int len = ether_arg_to_buffer(arg, p);
1074    
1075     if(len > 1514) {
1076     D(bug("illegal packet length: %d\n",len));
1077     return eLenErr;
1078     } else {
1079     #if MONITOR
1080     bug("Sending Ethernet packet (%d bytes):\n",(int)len);
1081     dump_packet( packet, len );
1082     #endif
1083     }
1084    
1085     // Transmit packet
1086     if (!write_packet(packet, len)) {
1087     D(bug("WARNING: couldn't transmit packet\n"));
1088     return excessCollsns;
1089     } else {
1090     // It's up to the protocol drivers to do the error checking. Even if the
1091     // i/o completion routine returns ok, there can be errors, so there is
1092     // no point to wait for write completion and try to make some sense of the
1093     // possible error codes.
1094     return noErr;
1095     }
1096     }
1097    
1098    
1099     static void init_queue(void)
1100     {
1101     queue_inx = 0;
1102     queue_head = 0;
1103    
1104     for( int i=0; i<MAX_QUEUE_ITEMS; i++ ) {
1105     queue[i].buf = (uint8 *)malloc( 1514 );
1106     queue[i].sz = 0;
1107     }
1108     }
1109    
1110     static void final_queue(void)
1111     {
1112     for( int i=0; i<MAX_QUEUE_ITEMS; i++ ) {
1113     if(queue[i].buf) free(queue[i].buf);
1114     }
1115     }
1116    
1117     void enqueue_packet( const uint8 *buf, int sz )
1118     {
1119     EnterCriticalSection( &queue_csection );
1120     if(queue[queue_inx].sz > 0) {
1121     D(bug("ethernet queue full, packet dropped\n"));
1122     } else {
1123     if(sz > 1514) sz = 1514;
1124     queue[queue_inx].sz = sz;
1125     memcpy( queue[queue_inx].buf, buf, sz );
1126     queue_inx++;
1127     if(queue_inx >= MAX_QUEUE_ITEMS) queue_inx = 0;
1128     if(wait_request) {
1129     wait_request = false;
1130     ReleaseSemaphore(int_sig,1,NULL);
1131     }
1132     }
1133     LeaveCriticalSection( &queue_csection );
1134     }
1135    
1136     static int dequeue_packet( uint8 *buf )
1137     {
1138     int sz;
1139    
1140     if(!thread_active) return(0);
1141    
1142     EnterCriticalSection( &queue_csection );
1143     sz = queue[queue_head].sz;
1144     if(sz > 0) {
1145     memcpy( buf, queue[queue_head].buf, sz );
1146     queue[queue_head].sz = 0;
1147     queue_head++;
1148     if(queue_head >= MAX_QUEUE_ITEMS) queue_head = 0;
1149     }
1150     LeaveCriticalSection( &queue_csection );
1151     return(sz);
1152     }
1153    
1154     static void trigger_queue(void)
1155     {
1156     EnterCriticalSection( &queue_csection );
1157     if( queue[queue_head].sz > 0 ) {
1158     D(bug(" packet received, triggering Ethernet interrupt\n"));
1159     SetInterruptFlag(INTFLAG_ETHER);
1160     TriggerInterrupt();
1161     // of course can't wait here.
1162     }
1163     LeaveCriticalSection( &queue_csection );
1164     }
1165    
1166     static bool set_wait_request(void)
1167     {
1168     bool result;
1169     EnterCriticalSection( &queue_csection );
1170     if(queue[queue_head].sz) {
1171     result = true;
1172     } else {
1173     result = false;
1174     wait_request = true;
1175     }
1176     LeaveCriticalSection( &queue_csection );
1177     return(result);
1178     }
1179    
1180    
1181     /*
1182 gbeauche 1.7 * TAP-Win32 glue
1183     */
1184    
1185     static LPADAPTER tap_open_adapter(const char *dev_name)
1186     {
1187     fd = (LPADAPTER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(*fd));
1188     if (fd == NULL)
1189     return NULL;
1190    
1191     char dev_path[MAX_PATH];
1192     snprintf(dev_path, sizeof(dev_path),
1193     "\\\\.\\Global\\%s.tap", dev_name);
1194    
1195     HANDLE handle = CreateFile(
1196     dev_path,
1197     GENERIC_READ | GENERIC_WRITE,
1198     0,
1199     NULL,
1200     OPEN_EXISTING,
1201     FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
1202     NULL);
1203     if (handle == NULL || handle == INVALID_HANDLE_VALUE)
1204     return NULL;
1205    
1206     fd->hFile = handle;
1207     return fd;
1208     }
1209    
1210     static void tap_close_adapter(LPADAPTER fd)
1211     {
1212     if (fd) {
1213     if (fd->hFile) {
1214     tap_set_status(fd, false);
1215     CloseHandle(fd->hFile);
1216     }
1217     GlobalFreePtr(fd);
1218     }
1219     }
1220    
1221     static bool tap_check_version(LPADAPTER fd)
1222     {
1223     ULONG len;
1224     ULONG info[3] = { 0, };
1225    
1226     if (!DeviceIoControl(fd->hFile, TAP_IOCTL_GET_VERSION,
1227     &info, sizeof(info),
1228     &info, sizeof(info), &len, NULL)
1229     && !DeviceIoControl(fd->hFile, OLD_TAP_IOCTL_GET_VERSION,
1230     &info, sizeof(info),
1231     &info, sizeof(info), &len, NULL))
1232     return false;
1233    
1234     if (info[0] > TAP_VERSION_MIN_MAJOR)
1235     return true;
1236     if (info[0] == TAP_VERSION_MIN_MAJOR && info[1] >= TAP_VERSION_MIN_MINOR)
1237     return true;
1238    
1239     return false;
1240     }
1241    
1242     static bool tap_set_status(LPADAPTER fd, ULONG status)
1243     {
1244     DWORD len = 0;
1245     return DeviceIoControl(fd->hFile, TAP_IOCTL_SET_MEDIA_STATUS,
1246     &status, sizeof (status),
1247     &status, sizeof (status), &len, NULL);
1248     }
1249    
1250     static bool tap_get_mac(LPADAPTER fd, LPBYTE addr)
1251     {
1252     DWORD len = 0;
1253     return DeviceIoControl(fd->hFile, TAP_IOCTL_GET_MAC,
1254     addr, 6,
1255     addr, 6, &len, NULL);
1256    
1257     }
1258    
1259     static VOID CALLBACK tap_write_completion(
1260     DWORD dwErrorCode,
1261     DWORD dwNumberOfBytesTransfered,
1262     LPOVERLAPPED lpOverLapped
1263     )
1264     {
1265     LPPACKET lpPacket = CONTAINING_RECORD(lpOverLapped, PACKET, OverLapped);
1266    
1267     lpPacket->bIoComplete = TRUE;
1268     recycle_write_packet(lpPacket);
1269     }
1270    
1271     static bool tap_send_packet(
1272     LPADAPTER fd,
1273     LPPACKET lpPacket,
1274     BOOLEAN Sync,
1275     BOOLEAN RecyclingAllowed)
1276     {
1277     BOOLEAN Result;
1278    
1279     lpPacket->OverLapped.Offset = 0;
1280     lpPacket->OverLapped.OffsetHigh = 0;
1281     lpPacket->bIoComplete = FALSE;
1282    
1283     if (Sync) {
1284     Result = WriteFile(fd->hFile,
1285     lpPacket->Buffer,
1286     lpPacket->Length,
1287     &lpPacket->BytesReceived,
1288     &lpPacket->OverLapped);
1289     if (Result) {
1290     GetOverlappedResult(fd->hFile,
1291     &lpPacket->OverLapped,
1292     &lpPacket->BytesReceived,
1293     TRUE);
1294     }
1295     lpPacket->bIoComplete = TRUE;
1296     if (RecyclingAllowed)
1297     PacketFreePacket(lpPacket);
1298     }
1299     else {
1300     Result = WriteFileEx(fd->hFile,
1301     lpPacket->Buffer,
1302     lpPacket->Length,
1303     &lpPacket->OverLapped,
1304     tap_write_completion);
1305    
1306     if (!Result && RecyclingAllowed)
1307     recycle_write_packet(lpPacket);
1308     }
1309    
1310     return Result;
1311     }
1312    
1313     static bool tap_receive_packet(LPADAPTER fd, LPPACKET lpPacket, BOOLEAN Sync)
1314     {
1315     BOOLEAN Result;
1316    
1317     lpPacket->OverLapped.Offset = 0;
1318     lpPacket->OverLapped.OffsetHigh = 0;
1319     lpPacket->bIoComplete = FALSE;
1320    
1321     if (Sync) {
1322     Result = ReadFile(fd->hFile,
1323     lpPacket->Buffer,
1324     lpPacket->Length,
1325     &lpPacket->BytesReceived,
1326     &lpPacket->OverLapped);
1327     if (Result) {
1328     Result = GetOverlappedResult(fd->hFile,
1329     &lpPacket->OverLapped,
1330     &lpPacket->BytesReceived,
1331     TRUE);
1332     if (Result)
1333     lpPacket->bIoComplete = TRUE;
1334     else
1335     lpPacket->free = TRUE;
1336     }
1337     }
1338     else {
1339     Result = ReadFileEx(fd->hFile,
1340     lpPacket->Buffer,
1341     lpPacket->Length,
1342     &lpPacket->OverLapped,
1343     packet_read_completion);
1344    
1345     if (!Result)
1346     lpPacket->BytesReceived = 0;
1347     }
1348    
1349     return Result;
1350     }
1351    
1352    
1353     /*
1354 gbeauche 1.6 * SLIRP output buffer glue
1355     */
1356    
1357     int slirp_can_output(void)
1358     {
1359     return 1;
1360     }
1361    
1362     void slirp_output(const uint8 *packet, int len)
1363     {
1364     enqueue_packet(packet, len);
1365     }
1366    
1367 gbeauche 1.7 static unsigned int slirp_receive_func(void *arg)
1368 gbeauche 1.6 {
1369     D(bug("slirp_receive_func\n"));
1370     thread_active_2 = true;
1371    
1372     while (thread_active) {
1373     // Wait for packets to arrive
1374     fd_set rfds, wfds, xfds;
1375     int nfds, ret, timeout;
1376    
1377     // ... in the output queue
1378     nfds = -1;
1379     FD_ZERO(&rfds);
1380     FD_ZERO(&wfds);
1381     FD_ZERO(&xfds);
1382     timeout = slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
1383     #if ! USE_SLIRP_TIMEOUT
1384     timeout = 10000;
1385     #endif
1386     if (nfds < 0) {
1387     /* Windows does not honour the timeout if there is not
1388     descriptor to wait for */
1389     Delay_usec(timeout);
1390     ret = 0;
1391     }
1392     else {
1393     struct timeval tv;
1394     tv.tv_sec = 0;
1395     tv.tv_usec = timeout;
1396     ret = select(0, &rfds, &wfds, &xfds, &tv);
1397     }
1398     if (ret >= 0)
1399     slirp_select_poll(&rfds, &wfds, &xfds);
1400     }
1401    
1402     D(bug("slirp_receive_func exit\n"));
1403     thread_active_2 = false;
1404     return 0;
1405     }
1406    
1407    
1408     /*
1409     * Packet reception threads
1410     */
1411    
1412     VOID CALLBACK packet_read_completion(
1413     DWORD dwErrorCode,
1414     DWORD dwNumberOfBytesTransfered,
1415     LPOVERLAPPED lpOverlapped
1416     )
1417     {
1418     EnterCriticalSection( &fetch_csection );
1419    
1420     LPPACKET lpPacket = CONTAINING_RECORD(lpOverlapped,PACKET,OverLapped);
1421    
1422     D(bug("packet_read_completion bytes=%d, error code=%d\n",dwNumberOfBytesTransfered,dwErrorCode));
1423    
1424     if(thread_active && !dwErrorCode) {
1425     int count = min(dwNumberOfBytesTransfered,1514);
1426     if(count) {
1427     int j = echo_count;
1428     for(int i=MAX_ECHO; i; i--) {
1429     j--;
1430     if(j < 0) j = MAX_ECHO-1;
1431     if(count == pending_packet_sz[j] &&
1432     memcmp(pending_packet[j],lpPacket->Buffer,count) == 0)
1433     {
1434     D(bug("packet_read_completion discarding own packet.\n"));
1435     dwNumberOfBytesTransfered = 0;
1436    
1437     j = (j+1) & (~(MAX_ECHO-1));
1438     if(j != echo_count) {
1439     D(bug("Wow, this fix made some good after all...\n"));
1440     }
1441    
1442     break;
1443     }
1444     }
1445 gbeauche 1.7 // XXX drop packets that are not for us
1446     if (net_if_type == NET_IF_TAP) {
1447     if (memcmp((LPBYTE)lpPacket->Buffer, ether_addr, 6) != 0)
1448     dwNumberOfBytesTransfered = 0;
1449     }
1450 gbeauche 1.6 if(dwNumberOfBytesTransfered) {
1451     if(net_if_type != NET_IF_ROUTER || !router_read_packet((uint8 *)lpPacket->Buffer, dwNumberOfBytesTransfered)) {
1452     enqueue_packet( (LPBYTE)lpPacket->Buffer, dwNumberOfBytesTransfered );
1453     }
1454     }
1455     }
1456     }
1457    
1458     // actually an auto-reset event.
1459     if(lpPacket->OverLapped.hEvent) ResetEvent(lpPacket->OverLapped.hEvent);
1460    
1461     lpPacket->free = TRUE;
1462     lpPacket->bIoComplete = TRUE;
1463    
1464     if(wait_request2) {
1465     wait_request2 = false;
1466     ReleaseSemaphore(int_sig2,1,NULL);
1467     }
1468    
1469     LeaveCriticalSection( &fetch_csection );
1470     }
1471    
1472     static BOOL has_no_completed_io(void)
1473     {
1474     BOOL result = TRUE;
1475    
1476     EnterCriticalSection( &fetch_csection );
1477    
1478     for( int i=0; i<PACKET_POOL_COUNT; i++ ) {
1479     if(packets[i]->bIoComplete) {
1480     result = FALSE;
1481     break;
1482     }
1483     }
1484     if(result) wait_request2 = true;
1485    
1486     LeaveCriticalSection( &fetch_csection );
1487     return(result);
1488     }
1489    
1490     static bool allocate_read_packets(void)
1491     {
1492     for( int i=0; i<PACKET_POOL_COUNT; i++ ) {
1493     packets[i] = PacketAllocatePacket(fd,1514);
1494     if(!packets[i]) {
1495     D(bug("allocate_read_packets: out of memory\n"));
1496     return(false);
1497     }
1498     }
1499     return(true);
1500     }
1501    
1502     static void free_read_packets(void)
1503     {
1504     for( int i=0; i<PACKET_POOL_COUNT; i++ ) {
1505     PacketFreePacket(packets[i]);
1506     }
1507     }
1508    
1509     static unsigned int ether_thread_get_packets_nt(void *arg)
1510     {
1511     static uint8 packet[1514];
1512     int i, packet_sz = 0;
1513    
1514     thread_active_2 = true;
1515    
1516     D(bug("ether_thread_get_packets_nt start\n"));
1517    
1518     // Wait for packets to arrive.
1519     // Obey the golden rules; keep the reads pending.
1520     while(thread_active) {
1521    
1522 gbeauche 1.7 if(net_if_type == NET_IF_B2ETHER || net_if_type == NET_IF_TAP) {
1523 gbeauche 1.6 D(bug("Pending reads\n"));
1524     for( i=0; thread_active && i<PACKET_POOL_COUNT; i++ ) {
1525     if(packets[i]->free) {
1526     packets[i]->free = FALSE;
1527 gbeauche 1.7 BOOLEAN Result;
1528     switch (net_if_type) {
1529     case NET_IF_B2ETHER:
1530     Result = PacketReceivePacket(fd, packets[i], FALSE);
1531     break;
1532     case NET_IF_TAP:
1533     Result = tap_receive_packet(fd, packets[i], FALSE);
1534     break;
1535     }
1536     if (Result) {
1537 gbeauche 1.6 if(packets[i]->bIoComplete) {
1538     D(bug("Early io completion...\n"));
1539     packet_read_completion(
1540     ERROR_SUCCESS,
1541     packets[i]->BytesReceived,
1542     &packets[i]->OverLapped
1543     );
1544     }
1545     } else {
1546     packets[i]->free = TRUE;
1547     }
1548     }
1549     }
1550     }
1551    
1552     if(thread_active && has_no_completed_io()) {
1553     D(bug("Waiting for int_sig2\n"));
1554     // "problem": awakens twice in a row. Fix if you increase the pool size.
1555     WaitForSingleObjectEx(int_sig2,INFINITE,TRUE);
1556     }
1557     }
1558    
1559     D(bug("ether_thread_get_packets_nt exit\n"));
1560    
1561     thread_active_2 = false;
1562    
1563     return 0;
1564     }
1565    
1566     static unsigned int ether_thread_feed_int(void *arg)
1567     {
1568     bool looping;
1569    
1570     thread_active_3 = true;
1571    
1572     D(bug("ether_thread_feed_int start\n"));
1573    
1574     while(thread_active) {
1575     D(bug("Waiting for int_sig\n"));
1576     WaitForSingleObject(int_sig,INFINITE);
1577     // Looping this way to avoid a race condition.
1578     D(bug("Triggering\n"));
1579     looping = true;
1580     while(thread_active && looping) {
1581     trigger_queue();
1582     // Wait for interrupt acknowledge by EtherInterrupt()
1583     WaitForSingleObject(int_ack,INFINITE);
1584     if(thread_active) looping = set_wait_request();
1585     }
1586     D(bug("Queue empty.\n"));
1587     }
1588    
1589     D(bug("ether_thread_feed_int exit\n"));
1590    
1591     thread_active_3 = false;
1592    
1593     return 0;
1594     }
1595    
1596    
1597     /*
1598     * Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers
1599     */
1600    
1601     static void ether_do_interrupt(void)
1602     {
1603     // Call protocol handler for received packets
1604     EthernetPacket ether_packet;
1605     uint32 packet = ether_packet.addr();
1606     ssize_t length;
1607     for (;;) {
1608    
1609     // Read packet from Ethernet device
1610     length = dequeue_packet(Mac2HostAddr(packet));
1611     if (length < 14)
1612     break;
1613    
1614     #if MONITOR
1615     bug("Receiving Ethernet packet (%d bytes):\n",(int)length);
1616     dump_packet( Mac2HostAddr(packet), length );
1617     #endif
1618    
1619     // Dispatch packet
1620     ether_dispatch_packet(packet, length);
1621     }
1622     }
1623    
1624     #if DEBUG
1625     #pragma optimize("",on)
1626     #endif