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, 5 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

# Content
1 /*
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 #include "sysdeps.h"
24
25 #include <process.h>
26 #include <windowsx.h>
27 #include <winioctl.h>
28 #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 NET_IF_TAP,
64 NET_IF_FAKE,
65 };
66
67 // 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 // 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 static int net_if_type = -1; // Ethernet device type
99 #ifdef SHEEPSHAVER
100 static bool net_open = false; // Flag: initialization succeeded, network device open
101 uint8 ether_addr[6]; // Our Ethernet address
102 #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 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 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 else if (strcmp(name, "tap") == 0)
238 net_if_type = NET_IF_TAP;
239 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 case NET_IF_TAP:
264 dev_name = PrefsFindString("etherguid");
265 break;
266 }
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 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 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 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 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 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 }
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 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 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 case NET_IF_TAP:
1022 if (!tap_send_packet(fd, Packet, FALSE, TRUE)) {
1023 // already recycled if async
1024 }
1025 break;
1026 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 * 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 * 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 static unsigned int slirp_receive_func(void *arg)
1368 {
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 // 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 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 if(net_if_type == NET_IF_B2ETHER || net_if_type == NET_IF_TAP) {
1523 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 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 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