ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/ether_windows.cpp
Revision: 1.9
Committed: 2008-01-01T09:40:33Z (16 years, 5 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.8: +1 -1 lines
Log Message:
Happy New Year!

File Contents

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