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, 4 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.8: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# Content
1 /*
2 * ether_windows.cpp - Ethernet device driver
3 *
4 * Basilisk II (C) 1997-2008 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 (PrefsFindBool("routerenabled") || 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 if (dev_name == NULL || strcmp(name, "b2ether") != 0)
263 dev_name = name;
264 break;
265 case NET_IF_TAP:
266 dev_name = PrefsFindString("etherguid");
267 break;
268 }
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 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 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 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 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 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 }
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 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 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 case NET_IF_TAP:
1024 if (!tap_send_packet(fd, Packet, FALSE, TRUE)) {
1025 // already recycled if async
1026 }
1027 break;
1028 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 * 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 * 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 static unsigned int slirp_receive_func(void *arg)
1370 {
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 // 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 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 if(net_if_type == NET_IF_B2ETHER || net_if_type == NET_IF_TAP) {
1525 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 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 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