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

Comparing BasiliskII/src/Windows/ether_windows.cpp (file contents):
Revision 1.5 by gbeauche, 2006-04-23T15:36:51Z vs.
Revision 1.7 by gbeauche, 2006-05-01T10:23:47Z

# Line 1 | Line 1
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 <process.h>
24 < #include <windowsx.h>
25 < #include <ctype.h>
26 <
27 < #include "sysdeps.h"
28 < #include "cpu_emulation.h"
29 < #include "main.h"
30 < #include "macos_util.h"
31 < #include "prefs.h"
32 < #include "user_strings.h"
33 < #include "ether.h"
34 < #include "ether_defs.h"
35 < #include "b2ether/multiopt.h"
36 < #include "b2ether/inc/b2ether_hl.h"
37 < #include "ether_windows.h"
38 < #include "router/router.h"
39 < #include "kernel_windows.h"
40 <
41 <
42 < #define DEBUG 0
43 < #define MONITOR 0
44 <
45 < #if DEBUG
46 < #pragma optimize("",off)
47 < #endif
48 <
49 < #include "debug.h"
50 <
51 <
52 < // Ethernet device types
53 < enum {
54 <        NET_IF_B2ETHER,
55 <        NET_IF_ROUTER,
56 <        NET_IF_FAKE,
57 < };
58 <
59 < // Options
60 < bool ether_use_permanent = true;
61 < static int16 ether_multi_mode = ETHER_MULTICAST_MAC;
62 <
63 < // Global variables
64 < HANDLE ether_th;
65 < unsigned int ether_tid;
66 < HANDLE ether_th1;
67 < HANDLE ether_th2;
68 < static int net_if_type = -1;                            // Ethernet device type
69 < #ifdef SHEEPSHAVER
70 < static bool net_open = false;                           // Flag: initialization succeeded, network device open
71 < uint8 ether_addr[6];                                            // Our Ethernet address
72 < #endif
73 <
74 < // These are protected by queue_csection
75 < // Controls transfer for read thread to feed thread
76 < static CRITICAL_SECTION queue_csection;
77 < typedef struct _win_queue_t {
78 <        uint8 *buf;
79 <        int sz;
80 < } win_queue_t;
81 < #define MAX_QUEUE_ITEMS 1024
82 < static win_queue_t queue[MAX_QUEUE_ITEMS];
83 < static int queue_head = 0;
84 < static int queue_inx = 0;
85 < static bool wait_request = true;
86 <
87 <
88 <
89 < // Read thread protected packet pool
90 < static CRITICAL_SECTION fetch_csection;
91 < // Some people use pools as large as 64.
92 < #define PACKET_POOL_COUNT 10
93 < static LPPACKET packets[PACKET_POOL_COUNT];
94 < static bool wait_request2 = false;
95 <
96 <
97 <
98 < // Write thread packet queue
99 < static CRITICAL_SECTION send_csection;
100 < static LPPACKET send_queue = 0;
101 <
102 <
103 < // Write thread free packet pool
104 < static CRITICAL_SECTION wpool_csection;
105 < static LPPACKET write_packet_pool = 0;
106 <
107 <
108 <
109 < // Try to deal with echos. Protected by fetch_csection.
110 < // The code should be moved to the driver. No need to lift
111 < // the echo packets to the application level.
112 < // MAX_ECHO must be a power of two.
113 < #define MAX_ECHO (1<<2)
114 < static int echo_count = 0;
115 < typedef uint8 echo_t[1514];
116 < static echo_t pending_packet[MAX_ECHO];
117 < static int pending_packet_sz[MAX_ECHO];
118 <
119 <
120 < // List of attached protocols
121 < struct NetProtocol {
122 <        NetProtocol *next;
123 <        uint16 type;
124 <        uint32 handler;
125 < };
126 <
127 < static NetProtocol *prot_list = NULL;
128 <
129 <
130 < static LPADAPTER fd = 0;
131 < static bool thread_active = false;
132 < static bool thread_active_1 = false;
133 < static bool thread_active_2 = false;
134 < static bool thread_active_3 = false;
135 < static HANDLE int_ack = 0;
136 < static HANDLE int_sig = 0;
137 < static HANDLE int_sig2 = 0;
138 < static HANDLE int_send_now = 0;
139 <
140 < // Prototypes
141 < static WINAPI unsigned int ether_thread_feed_int(void *arg);
142 < static WINAPI unsigned int ether_thread_get_packets_nt(void *arg);
143 < static WINAPI unsigned int ether_thread_write_packets(void *arg);
144 < static void init_queue(void);
145 < static void final_queue(void);
146 < static bool allocate_read_packets(void);
147 < static void free_read_packets(void);
148 < static void free_write_packets(void);
149 < static int16 ether_do_add_multicast(uint8 *addr);
150 < static int16 ether_do_del_multicast(uint8 *addr);
151 < static int16 ether_do_write(uint32 arg);
152 < static void ether_do_interrupt(void);
153 <
154 <
155 < /*
156 < *  Find protocol in list
157 < */
158 <
159 < static NetProtocol *find_protocol(uint16 type)
160 < {
161 <        // All 802.2 types are the same
162 <        if (type <= 1500)
163 <                type = 0;
164 <
165 <        // Search list (we could use hashing here but there are usually only three
166 <        // handlers installed: 0x0000 for AppleTalk and 0x0800/0x0806 for TCP/IP)
167 <        NetProtocol *p = prot_list;
168 <        while (p) {
169 <                if (p->type == type)
170 <                        return p;
171 <                p = p->next;
172 <        }
173 <        return NULL;
174 < }
175 <
176 <
177 < /*
178 < *  Initialization
179 < */
180 <
181 < bool ether_init(void)
182 < {
183 <        char str[256];
184 <
185 <        // Do nothing if no Ethernet device specified
186 <        const char *name = PrefsFindString("ether");
187 <        if (name == NULL)
188 <                return false;
189 <
190 <        ether_multi_mode = PrefsFindInt32("ethermulticastmode");
191 <        ether_use_permanent = PrefsFindBool("etherpermanentaddress");
192 <
193 <        // Determine Ethernet device type
194 <        net_if_type = -1;
195 <        if (strcmp(name, "router") == 0)
196 <                net_if_type = NET_IF_ROUTER;
197 <        else
198 <                net_if_type = NET_IF_B2ETHER;
199 <
200 <        // Initialize NAT-Router
201 <        if (net_if_type == NET_IF_ROUTER) {
202 <                if (!router_init())
203 <                        net_if_type = NET_IF_FAKE;
204 <        }
205 <
206 <        // Open ethernet device
207 <        const char *dev_name;
208 <        switch (net_if_type) {
209 <        case NET_IF_B2ETHER:
210 <                dev_name = PrefsFindString("etherguid");
211 <                break;
212 <        }
213 <        if (net_if_type == NET_IF_B2ETHER) {
214 <                if (dev_name == NULL) {
215 <                        WarningAlert("No ethernet device GUID specified. Ethernet is not available.");
216 <                        goto open_error;
217 <                }
218 <
219 <                fd = PacketOpenAdapter( dev_name, ether_multi_mode );
220 <                if (!fd) {
221 <                        sprintf(str, "Could not open ethernet adapter %s.", dev_name);
222 <                        WarningAlert(str);
223 <                        goto open_error;
224 <                }
225 <
226 <                // Get Ethernet address
227 <                if(!PacketGetMAC(fd,ether_addr,ether_use_permanent)) {
228 <                        sprintf(str, "Could not get hardware address of device %s. Ethernet is not available.", dev_name);
229 <                        WarningAlert(str);
230 <                        goto open_error;
231 <                }
232 <                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]));
233 <
234 <                const char *ether_fake_address;
235 <                ether_fake_address = PrefsFindString("etherfakeaddress");
236 <                if(ether_fake_address && strlen(ether_fake_address) == 12) {
237 <                        char sm[10];
238 <                        strcpy( sm, "0x00" );
239 <                        for( int i=0; i<6; i++ ) {
240 <                                sm[2] = ether_fake_address[i*2];
241 <                                sm[3] = ether_fake_address[i*2+1];
242 <                                ether_addr[i] = (uint8)strtoul(sm,0,0);
243 <                        }
244 <                        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]));
245 <                }
246 <        }
247 <        else {
248 <                memcpy( ether_addr, router_mac_addr, 6 );
249 <                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]));
250 <        }
251 <
252 <        // Start packet reception thread
253 <        int_ack = CreateSemaphore( 0, 0, 1, NULL);
254 <        if(!int_ack) {
255 <                WarningAlert("WARNING: Cannot create int_ack semaphore");
256 <                goto open_error;
257 <        }
258 <
259 <        // nonsignaled
260 <        int_sig = CreateSemaphore( 0, 0, 1, NULL);
261 <        if(!int_sig) {
262 <                WarningAlert("WARNING: Cannot create int_sig semaphore");
263 <                goto open_error;
264 <        }
265 <
266 <        int_sig2 = CreateSemaphore( 0, 0, 1, NULL);
267 <        if(!int_sig2) {
268 <                WarningAlert("WARNING: Cannot create int_sig2 semaphore");
269 <                goto open_error;
270 <        }
271 <
272 <        int_send_now = CreateSemaphore( 0, 0, 1, NULL);
273 <        if(!int_send_now) {
274 <                WarningAlert("WARNING: Cannot create int_send_now semaphore");
275 <                goto open_error;
276 <        }
277 <
278 <        init_queue();
279 <
280 <        if(!allocate_read_packets()) goto open_error;
281 <
282 <        // No need to enter wait state if we can avoid it.
283 <        // These all terminate fast.
284 <
285 <        if(pfnInitializeCriticalSectionAndSpinCount) {
286 <                pfnInitializeCriticalSectionAndSpinCount( &fetch_csection, 5000 );
287 <        } else {
288 <                InitializeCriticalSection( &fetch_csection );
289 <        }
290 <        if(pfnInitializeCriticalSectionAndSpinCount) {
291 <                pfnInitializeCriticalSectionAndSpinCount( &queue_csection, 5000 );
292 <        } else {
293 <                InitializeCriticalSection( &queue_csection );
294 <        }
295 <        if(pfnInitializeCriticalSectionAndSpinCount) {
296 <                pfnInitializeCriticalSectionAndSpinCount( &send_csection, 5000 );
297 <        } else {
298 <                InitializeCriticalSection( &send_csection );
299 <        }
300 <        if(pfnInitializeCriticalSectionAndSpinCount) {
301 <                pfnInitializeCriticalSectionAndSpinCount( &wpool_csection, 5000 );
302 <        } else {
303 <                InitializeCriticalSection( &wpool_csection );
304 <        }
305 <
306 <        ether_th = (HANDLE)_beginthreadex( 0, 0, ether_thread_feed_int, 0, 0, &ether_tid );
307 <        if (!ether_th) {
308 <                D(bug("Failed to create ethernet thread\n"));
309 <                goto open_error;
310 <        }
311 <        thread_active = true;
312 <
313 <        unsigned int dummy;
314 <        ether_th2 = (HANDLE)_beginthreadex( 0, 0, ether_thread_get_packets_nt, 0, 0, &dummy );
315 <        ether_th1 = (HANDLE)_beginthreadex( 0, 0, ether_thread_write_packets, 0, 0, &dummy );
316 <
317 <        // Everything OK
318 <        return true;
319 <
320 < open_error:
321 <        if (thread_active) {
322 <                TerminateThread(ether_th,0);
323 <                ether_th = 0;
324 <                if (int_ack)
325 <                        CloseHandle(int_ack);
326 <                int_ack = 0;
327 <                if(int_sig)
328 <                        CloseHandle(int_sig);
329 <                int_sig = 0;
330 <                if(int_sig2)
331 <                        CloseHandle(int_sig2);
332 <                int_sig2 = 0;
333 <                if(int_send_now)
334 <                        CloseHandle(int_send_now);
335 <                int_send_now = 0;
336 <                thread_active = false;
337 <        }
338 <        if(net_if_type == NET_IF_B2ETHER) {
339 <                PacketCloseAdapter(fd);
340 <        }
341 <        fd = 0;
342 <        return false;
343 < }
344 <
345 <
346 < /*
347 < *  Deinitialization
348 < */
349 <
350 < void ether_exit(void)
351 < {
352 <        D(bug("EtherExit\n"));
353 <
354 <        // Stop reception thread
355 <        thread_active = false;
356 <
357 <        if(int_ack) ReleaseSemaphore(int_ack,1,NULL);
358 <        if(int_sig) ReleaseSemaphore(int_sig,1,NULL);
359 <        if(int_sig2) ReleaseSemaphore(int_sig2,1,NULL);
360 <        if(int_send_now) ReleaseSemaphore(int_send_now,1,NULL);
361 <
362 <        D(bug("CancelIO if needed\n"));
363 <        if (fd && fd->hFile && pfnCancelIo)
364 <                pfnCancelIo(fd->hFile);
365 <
366 <        // Wait max 2 secs to shut down pending io. After that, kill them.
367 <        D(bug("Wait delay\n"));
368 <        for( int i=0; i<10; i++ ) {
369 <                if(!thread_active_1 && !thread_active_2 && !thread_active_3) break;
370 <                Sleep(200);
371 <        }
372 <
373 <        if(thread_active_1) {
374 <                D(bug("Ether killing ether_th1\n"));
375 <                if(ether_th1) TerminateThread(ether_th1,0);
376 <                thread_active_1 = false;
377 <        }
378 <        if(thread_active_2) {
379 <                D(bug("Ether killing ether_th2\n"));
380 <                if(ether_th2) TerminateThread(ether_th2,0);
381 <                thread_active_2 = false;
382 <        }
383 <        if(thread_active_3) {
384 <                D(bug("Ether killing thread\n"));
385 <                if(ether_th) TerminateThread(ether_th,0);
386 <                thread_active_3 = false;
387 <        }
388 <
389 <        ether_th1 = 0;
390 <        ether_th2 = 0;
391 <        ether_th = 0;
392 <
393 <        D(bug("Closing semaphores\n"));
394 <        if(int_ack) {
395 <                CloseHandle(int_ack);
396 <                int_ack = 0;
397 <        }
398 <        if(int_sig) {
399 <                CloseHandle(int_sig);
400 <                int_sig = 0;
401 <        }
402 <        if(int_sig2) {
403 <                CloseHandle(int_sig2);
404 <                int_sig2 = 0;
405 <        }
406 <        if(int_send_now) {
407 <                CloseHandle(int_send_now);
408 <                int_send_now = 0;
409 <        }
410 <
411 <        // Close ethernet device
412 <        if(fd) {
413 <                PacketCloseAdapter(fd);
414 <                fd = 0;
415 <        }
416 <
417 <        // Remove all protocols
418 <        D(bug("Removing protocols\n"));
419 <        NetProtocol *p = prot_list;
420 <        while (p) {
421 <                NetProtocol *next = p->next;
422 <                delete p;
423 <                p = next;
424 <        }
425 <        prot_list = 0;
426 <
427 <        D(bug("Deleting sections\n"));
428 <        DeleteCriticalSection( &fetch_csection );
429 <        DeleteCriticalSection( &queue_csection );
430 <        DeleteCriticalSection( &send_csection );
431 <        DeleteCriticalSection( &wpool_csection );
432 <
433 <        D(bug("Freeing read packets\n"));
434 <        free_read_packets();
435 <
436 <        D(bug("Freeing write packets\n"));
437 <        free_write_packets();
438 <
439 <        D(bug("Finalizing queue\n"));
440 <        final_queue();
441 <
442 <        if (net_if_type == NET_IF_ROUTER) {
443 <                D(bug("Stopping router\n"));
444 <                router_final();
445 <        }
446 <
447 <        D(bug("EtherExit done\n"));
448 < }
449 <
450 <
451 < /*
452 < *  Glue around low-level implementation
453 < */
454 <
455 < #ifdef SHEEPSHAVER
456 < // Error codes
457 < enum {
458 <        eMultiErr               = -91,
459 <        eLenErr                 = -92,
460 <        lapProtErr              = -94,
461 <        excessCollsns   = -95
462 < };
463 <
464 < // Initialize ethernet
465 < void EtherInit(void)
466 < {
467 <        net_open = false;
468 <
469 <        // Do nothing if the user disabled the network
470 <        if (PrefsFindBool("nonet"))
471 <                return;
472 <
473 <        net_open = ether_init();
474 < }
475 <
476 < // Exit ethernet
477 < void EtherExit(void)
478 < {
479 <        ether_exit();
480 <        net_open = false;
481 < }
482 <
483 < // Get ethernet hardware address
484 < void AO_get_ethernet_address(uint32 arg)
485 < {
486 <        uint8 *addr = Mac2HostAddr(arg);
487 <        if (net_open)
488 <                OTCopy48BitAddress(ether_addr, addr);
489 <        else {
490 <                addr[0] = 0x12;
491 <                addr[1] = 0x34;
492 <                addr[2] = 0x56;
493 <                addr[3] = 0x78;
494 <                addr[4] = 0x9a;
495 <                addr[5] = 0xbc;
496 <        }
497 <        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]));
498 < }
499 <
500 < // Add multicast address
501 < void AO_enable_multicast(uint32 addr)
502 < {
503 <        if (net_open)
504 <                ether_do_add_multicast(Mac2HostAddr(addr));
505 < }
506 <
507 < // Disable multicast address
508 < void AO_disable_multicast(uint32 addr)
509 < {
510 <        if (net_open)
511 <                ether_do_del_multicast(Mac2HostAddr(addr));
512 < }
513 <
514 < // Transmit one packet
515 < void AO_transmit_packet(uint32 mp)
516 < {
517 <        if (net_open) {
518 <                switch (ether_do_write(mp)) {
519 <                case noErr:
520 <                        num_tx_packets++;
521 <                        break;
522 <                case excessCollsns:
523 <                        num_tx_buffer_full++;
524 <                        break;
525 <                }
526 <        }
527 < }
528 <
529 < // Copy packet data from message block to linear buffer
530 < static inline int ether_arg_to_buffer(uint32 mp, uint8 *p)
531 < {
532 <        return ether_msgb_to_buffer(mp, p);
533 < }
534 <
535 < // Ethernet interrupt
536 < void EtherIRQ(void)
537 < {
538 <        D(bug("EtherIRQ\n"));
539 <        num_ether_irq++;
540 <
541 <        OTEnterInterrupt();
542 <        ether_do_interrupt();
543 <        OTLeaveInterrupt();
544 <
545 <        // Acknowledge interrupt to reception thread
546 <        D(bug(" EtherIRQ done\n"));
547 <        ReleaseSemaphore(int_ack,1,NULL);
548 < }
549 < #else
550 < // Add multicast address
551 < int16 ether_add_multicast(uint32 pb)
552 < {
553 <        return ether_do_add_multicast(Mac2HostAddr(pb + eMultiAddr));
554 < }
555 <
556 < // Disable multicast address
557 < int16 ether_del_multicast(uint32 pb)
558 < {
559 <        return ether_do_del_multicast(Mac2HostAddr(pb + eMultiAddr));
560 < }
561 <
562 < // Transmit one packet
563 < int16 ether_write(uint32 wds)
564 < {
565 <        return ether_do_write(wds);
566 < }
567 <
568 < // Copy packet data from WDS to linear buffer
569 < static inline int ether_arg_to_buffer(uint32 wds, uint8 *p)
570 < {
571 <        return ether_wds_to_buffer(wds, p);
572 < }
573 <
574 < // Dispatch packet to protocol handler
575 < static void ether_dispatch_packet(uint32 packet, uint32 length)
576 < {
577 <        // Get packet type
578 <        uint16 type = ReadMacInt16(packet + 12);
579 <
580 <        // Look for protocol
581 <        NetProtocol *prot = find_protocol(type);
582 <        if (prot == NULL)
583 <                return;
584 <
585 <        // No default handler
586 <        if (prot->handler == 0)
587 <                return;
588 <
589 <        // Copy header to RHA
590 <        Mac2Mac_memcpy(ether_data + ed_RHA, packet, 14);
591 <        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)));
592 <
593 <        // Call protocol handler
594 <        M68kRegisters r;
595 <        r.d[0] = type;                                                          // Packet type
596 <        r.d[1] = length - 14;                                           // Remaining packet length (without header, for ReadPacket)
597 <        r.a[0] = packet + 14;                                           // Pointer to packet (Mac address, for ReadPacket)
598 <        r.a[3] = ether_data + ed_RHA + 14;                      // Pointer behind header in RHA
599 <        r.a[4] = ether_data + ed_ReadPacket;            // Pointer to ReadPacket/ReadRest routines
600 <        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]));
601 <        Execute68k(prot->handler, &r);
602 < }
603 <
604 < // Ethernet interrupt
605 < void EtherInterrupt(void)
606 < {
607 <        D(bug("EtherIRQ\n"));
608 <        ether_do_interrupt();
609 <
610 <        // Acknowledge interrupt to reception thread
611 <        D(bug(" EtherIRQ done\n"));
612 <        ReleaseSemaphore(int_ack,1,NULL);
613 < }
614 < #endif
615 <
616 <
617 < /*
618 < *  Reset
619 < */
620 <
621 < void ether_reset(void)
622 < {
623 <        D(bug("EtherReset\n"));
624 <
625 <        // Remove all protocols
626 <        NetProtocol *p = prot_list;
627 <        while (p) {
628 <                NetProtocol *next = p->next;
629 <                delete p;
630 <                p = next;
631 <        }
632 <        prot_list = NULL;
633 < }
634 <
635 <
636 < /*
637 < *  Add multicast address
638 < */
639 <
640 < static int16 ether_do_add_multicast(uint8 *addr)
641 < {
642 <        D(bug("ether_add_multicast\n"));
643 <
644 <        // We wouldn't need to do this
645 <        // if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr;
646 <
647 <        switch (net_if_type) {
648 <        case NET_IF_B2ETHER:
649 <                if (!PacketAddMulticast( fd, addr)) {
650 <                        D(bug("WARNING: couldn't enable multicast address\n"));
651 <                        return eMultiErr;
652 <                }
653 <        default:
654 <                D(bug("ether_add_multicast: noErr\n"));
655 <                return noErr;
656 <        }
657 < }
658 <
659 <
660 < /*
661 < *  Delete multicast address
662 < */
663 <
664 < int16 ether_do_del_multicast(uint8 *addr)
665 < {
666 <        D(bug("ether_del_multicast\n"));
667 <
668 <        // We wouldn't need to do this
669 <        // if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr;
670 <
671 <        switch (net_if_type) {
672 <        case NET_IF_B2ETHER:
673 <                if (!PacketDelMulticast( fd, addr)) {
674 <                        D(bug("WARNING: couldn't disable multicast address\n"));
675 <                        return eMultiErr;
676 <                }
677 <        default:
678 <                return noErr;
679 <        }
680 < }
681 <
682 <
683 < /*
684 < *  Attach protocol handler
685 < */
686 <
687 < int16 ether_attach_ph(uint16 type, uint32 handler)
688 < {
689 <        D(bug("ether_attach_ph type=0x%x, handler=0x%x\n",(int)type,handler));
690 <
691 <        // Already attached?
692 <        NetProtocol *p = find_protocol(type);
693 <        if (p != NULL) {
694 <                D(bug("ether_attach_ph: lapProtErr\n"));
695 <                return lapProtErr;
696 <        } else {
697 <                // No, create and attach
698 <                p = new NetProtocol;
699 <                p->next = prot_list;
700 <                p->type = type;
701 <                p->handler = handler;
702 <                prot_list = p;
703 <                D(bug("ether_attach_ph: noErr\n"));
704 <                return noErr;
705 <        }
706 < }
707 <
708 <
709 < /*
710 < *  Detach protocol handler
711 < */
712 <
713 < int16 ether_detach_ph(uint16 type)
714 < {
715 <        D(bug("ether_detach_ph type=%08lx\n",(int)type));
716 <
717 <        NetProtocol *p = find_protocol(type);
718 <        if (p != NULL) {
719 <                NetProtocol *previous = 0;
720 <                NetProtocol *q = prot_list;
721 <                while(q) {
722 <                        if (q == p) {
723 <                                if(previous) {
724 <                                        previous->next = q->next;
725 <                                } else {
726 <                                        prot_list = q->next;
727 <                                }
728 <                                delete p;
729 <                                return noErr;
730 <                        }
731 <                        previous = q;
732 <                        q = q->next;
733 <                }
734 <        }
735 <        return lapProtErr;
736 < }
737 <
738 < #if MONITOR
739 < static void dump_packet( uint8 *packet, int length )
740 < {
741 <        char buf[1000], sm[10];
742 <
743 <        *buf = 0;
744 <
745 <        if(length > 256) length = 256;
746 <
747 <        for (int i=0; i<length; i++) {
748 <                sprintf(sm," %02x", (int)packet[i]);
749 <                strcat( buf, sm );
750 <        }
751 <        strcat( buf, "\n" );
752 <        bug(buf);
753 < }
754 < #endif
755 <
756 <
757 < /*
758 < *  Transmit raw ethernet packet
759 < */
760 <
761 < static void insert_send_queue( LPPACKET Packet )
762 < {
763 <        EnterCriticalSection( &send_csection );
764 <        Packet->next = 0;
765 <        if(send_queue) {
766 <                LPPACKET p = send_queue;
767 <                // The queue is short. It would be larger overhead to double-link it.
768 <                while(p->next) p = p->next;
769 <                p->next = Packet;
770 <        } else {
771 <                send_queue = Packet;
772 <        }
773 <        LeaveCriticalSection( &send_csection );
774 < }
775 <
776 < static LPPACKET get_send_head( void )
777 < {
778 <        LPPACKET Packet = 0;
779 <
780 <        EnterCriticalSection( &send_csection );
781 <        if(send_queue) {
782 <                Packet = send_queue;
783 <                send_queue = send_queue->next;
784 <        }
785 <        LeaveCriticalSection( &send_csection );
786 <
787 <        return Packet;
788 < }
789 <
790 < static int get_write_packet_pool_sz( void )
791 < {
792 <        LPPACKET t = write_packet_pool;
793 <        int sz = 0;
794 <
795 <        while(t) {
796 <                t = t->next;
797 <                sz++;
798 <        }
799 <        return(sz);
800 < }
801 <
802 < static void free_write_packets( void )
803 < {
804 <        LPPACKET next;
805 <        int i = 0;
806 <        while(write_packet_pool) {
807 <                next = write_packet_pool->next;
808 <                D(bug("Freeing write packet %ld\n",++i));
809 <                PacketFreePacket(write_packet_pool);
810 <                write_packet_pool = next;
811 <        }
812 < }
813 <
814 < void recycle_write_packet( LPPACKET Packet )
815 < {
816 <        EnterCriticalSection( &wpool_csection );
817 <        Packet->next = write_packet_pool;
818 <        write_packet_pool = Packet;
819 <        D(bug("Pool size after recycling = %ld\n",get_write_packet_pool_sz()));
820 <        LeaveCriticalSection( &wpool_csection );
821 < }
822 <
823 < static LPPACKET get_write_packet( UINT len )
824 < {
825 <        LPPACKET Packet = 0;
826 <
827 <        EnterCriticalSection( &wpool_csection );
828 <        if(write_packet_pool) {
829 <                Packet = write_packet_pool;
830 <                write_packet_pool = write_packet_pool->next;
831 <                Packet->OverLapped.Offset = 0;
832 <                Packet->OverLapped.OffsetHigh = 0;
833 <                Packet->Length = len;
834 <                Packet->BytesReceived   = 0;
835 <                Packet->bIoComplete     = FALSE;
836 <                Packet->free = TRUE;
837 <                Packet->next = 0;
838 <                // actually an auto-reset event.
839 <                if(Packet->OverLapped.hEvent) ResetEvent(Packet->OverLapped.hEvent);
840 <        } else {
841 <                Packet = PacketAllocatePacket(fd,len);
842 <        }
843 <
844 <        D(bug("Pool size after get wr packet = %ld\n",get_write_packet_pool_sz()));
845 <
846 <        LeaveCriticalSection( &wpool_csection );
847 <
848 <        return Packet;
849 < }
850 <
851 < static unsigned int ether_thread_write_packets(void *arg)
852 < {
853 <        LPPACKET Packet;
854 <
855 <        thread_active_1 = true;
856 <
857 <        D(bug("ether_thread_write_packets start\n"));
858 <
859 <        while(thread_active) {
860 <                // must be alertable, otherwise write completion is never called
861 <                WaitForSingleObjectEx(int_send_now,INFINITE,TRUE);
862 <                while( thread_active && (Packet = get_send_head()) != 0 ) {
863 <                        switch (net_if_type) {
864 <                        case NET_IF_ROUTER:
865 <                                if(router_write_packet((uint8 *)Packet->Buffer, Packet->Length)) {
866 <                                        Packet->bIoComplete = TRUE;
867 <                                        recycle_write_packet(Packet);
868 <                                }
869 <                                break;
870 <                        case NET_IF_FAKE:
871 <                                Packet->bIoComplete = TRUE;
872 <                                recycle_write_packet(Packet);
873 <                                break;
874 <                        case NET_IF_B2ETHER:
875 <                                if(!PacketSendPacket( fd, Packet, FALSE, TRUE )) {
876 <                                        // already recycled if async
877 <                                }
878 <                                break;
879 <                        }
880 <                }
881 <        }
882 <
883 <        D(bug("ether_thread_write_packets exit\n"));
884 <
885 <        thread_active_1 = false;
886 <
887 <        return(0);
888 < }
889 <
890 < static BOOL write_packet( uint8 *packet, int len )
891 < {
892 <        LPPACKET Packet;
893 <
894 <        D(bug("write_packet\n"));
895 <
896 <        Packet = get_write_packet(len);
897 <        if(Packet) {
898 <                memcpy( Packet->Buffer, packet, len );
899 <
900 <                EnterCriticalSection( &fetch_csection );
901 <                pending_packet_sz[echo_count] = min(sizeof(pending_packet),len);
902 <                memcpy( pending_packet[echo_count], packet, pending_packet_sz[echo_count] );
903 <                echo_count = (echo_count+1) & (~(MAX_ECHO-1));
904 <                LeaveCriticalSection( &fetch_csection );
905 <
906 <                insert_send_queue( Packet );
907 <
908 <                ReleaseSemaphore(int_send_now,1,NULL);
909 <                return(TRUE);
910 <        } else {
911 <                return(FALSE);
912 <        }
913 < }
914 <
915 < static int16 ether_do_write(uint32 arg)
916 < {
917 <        D(bug("ether_write\n"));
918 <
919 <        // Copy packet to buffer
920 <        uint8 packet[1514], *p = packet;
921 <        int len = ether_arg_to_buffer(arg, p);
922 <
923 <        if(len > 1514) {
924 <                D(bug("illegal packet length: %d\n",len));
925 <                return eLenErr;
926 <        } else {
927 < #if MONITOR
928 <                bug("Sending Ethernet packet (%d bytes):\n",(int)len);
929 <                dump_packet( packet, len );
930 < #endif
931 <        }
932 <
933 <        // Transmit packet
934 <        if (!write_packet(packet, len)) {
935 <                D(bug("WARNING: couldn't transmit packet\n"));
936 <                return excessCollsns;
937 <        } else {
938 <                // It's up to the protocol drivers to do the error checking. Even if the
939 <                // i/o completion routine returns ok, there can be errors, so there is
940 <                // no point to wait for write completion and try to make some sense of the
941 <                // possible error codes.
942 <                return noErr;
943 <        }
944 < }
945 <
946 <
947 < static void init_queue(void)
948 < {
949 <        queue_inx = 0;
950 <        queue_head = 0;
951 <
952 <        for( int i=0; i<MAX_QUEUE_ITEMS; i++ ) {
953 <                queue[i].buf = (uint8 *)malloc( 1514 );
954 <                queue[i].sz = 0;
955 <        }
956 < }
957 <
958 < static void final_queue(void)
959 < {
960 <        for( int i=0; i<MAX_QUEUE_ITEMS; i++ ) {
961 <                if(queue[i].buf) free(queue[i].buf);
962 <        }
963 < }
964 <
965 < void enqueue_packet( uint8 *buf, int sz )
966 < {
967 <        EnterCriticalSection( &queue_csection );
968 <        if(queue[queue_inx].sz > 0) {
969 <                D(bug("ethernet queue full, packet dropped\n"));
970 <        } else {
971 <                if(sz > 1514) sz = 1514;
972 <                queue[queue_inx].sz = sz;
973 <                memcpy( queue[queue_inx].buf, buf, sz );
974 <                queue_inx++;
975 <                if(queue_inx >= MAX_QUEUE_ITEMS) queue_inx = 0;
976 <                if(wait_request) {
977 <                        wait_request = false;
978 <                        ReleaseSemaphore(int_sig,1,NULL);
979 <                }
980 <        }
981 <        LeaveCriticalSection( &queue_csection );
982 < }
983 <
984 < static int dequeue_packet( uint8 *buf )
985 < {
986 <        int sz;
987 <
988 <        if(!thread_active) return(0);
989 <
990 <        EnterCriticalSection( &queue_csection );
991 <        sz = queue[queue_head].sz;
992 <        if(sz > 0) {
993 <                memcpy( buf, queue[queue_head].buf, sz );
994 <                queue[queue_head].sz = 0;
995 <                queue_head++;
996 <                if(queue_head >= MAX_QUEUE_ITEMS) queue_head = 0;
997 <        }
998 <        LeaveCriticalSection( &queue_csection );
999 <        return(sz);
1000 < }
1001 <
1002 < static void trigger_queue(void)
1003 < {
1004 <        EnterCriticalSection( &queue_csection );
1005 <        if( queue[queue_head].sz > 0 ) {
1006 <                D(bug(" packet received, triggering Ethernet interrupt\n"));
1007 <                SetInterruptFlag(INTFLAG_ETHER);
1008 <                TriggerInterrupt();
1009 <                // of course can't wait here.
1010 <        }
1011 <        LeaveCriticalSection( &queue_csection );
1012 < }
1013 <
1014 < static bool set_wait_request(void)
1015 < {
1016 <        bool result;
1017 <        EnterCriticalSection( &queue_csection );
1018 <        if(queue[queue_head].sz) {
1019 <                result = true;
1020 <        } else {
1021 <                result = false;
1022 <                wait_request = true;
1023 <        }
1024 <        LeaveCriticalSection( &queue_csection );
1025 <        return(result);
1026 < }
1027 <
1028 <
1029 < /*
1030 < *  Packet reception threads
1031 < */
1032 <
1033 < VOID CALLBACK packet_read_completion(
1034 <        DWORD dwErrorCode,
1035 <        DWORD dwNumberOfBytesTransfered,
1036 <        LPOVERLAPPED lpOverlapped
1037 <        )
1038 < {
1039 <        EnterCriticalSection( &fetch_csection );
1040 <
1041 <        LPPACKET lpPacket = CONTAINING_RECORD(lpOverlapped,PACKET,OverLapped);
1042 <
1043 <        D(bug("packet_read_completion bytes=%d, error code=%d\n",dwNumberOfBytesTransfered,dwErrorCode));
1044 <
1045 <        if(thread_active && !dwErrorCode) {
1046 <                int count = min(dwNumberOfBytesTransfered,1514);
1047 <                if(count) {
1048 <                        int j = echo_count;
1049 <                        for(int i=MAX_ECHO; i; i--) {
1050 <                                j--;
1051 <                                if(j < 0) j = MAX_ECHO-1;
1052 <                                if(count == pending_packet_sz[j] &&
1053 <                                   memcmp(pending_packet[j],lpPacket->Buffer,count) == 0)
1054 <                                {
1055 <                                        D(bug("packet_read_completion discarding own packet.\n"));
1056 <                                        dwNumberOfBytesTransfered = 0;
1057 <
1058 <                                        j = (j+1) & (~(MAX_ECHO-1));
1059 <                                        if(j != echo_count) {
1060 <                                                D(bug("Wow, this fix made some good after all...\n"));
1061 <                                        }
1062 <
1063 <                                        break;
1064 <                                }
1065 <                        }
1066 <                        if(dwNumberOfBytesTransfered) {
1067 <                                if(net_if_type != NET_IF_ROUTER || !router_read_packet((uint8 *)lpPacket->Buffer, dwNumberOfBytesTransfered)) {
1068 <                                        enqueue_packet( (LPBYTE)lpPacket->Buffer, dwNumberOfBytesTransfered );
1069 <                                }
1070 <                        }
1071 <                }
1072 <        }
1073 <
1074 <        // actually an auto-reset event.
1075 <        if(lpPacket->OverLapped.hEvent) ResetEvent(lpPacket->OverLapped.hEvent);
1076 <
1077 <        lpPacket->free = TRUE;
1078 <        lpPacket->bIoComplete = TRUE;
1079 <
1080 <        if(wait_request2) {
1081 <                wait_request2 = false;
1082 <                ReleaseSemaphore(int_sig2,1,NULL);
1083 <        }
1084 <
1085 <        LeaveCriticalSection( &fetch_csection );
1086 < }
1087 <
1088 < static BOOL has_no_completed_io(void)
1089 < {
1090 <        BOOL result = TRUE;
1091 <
1092 <        EnterCriticalSection( &fetch_csection );
1093 <
1094 <        for( int i=0; i<PACKET_POOL_COUNT; i++ ) {
1095 <                if(packets[i]->bIoComplete) {
1096 <                        result = FALSE;
1097 <                        break;
1098 <                }
1099 <        }
1100 <        if(result) wait_request2 = true;
1101 <
1102 <        LeaveCriticalSection( &fetch_csection );
1103 <        return(result);
1104 < }
1105 <
1106 < static bool allocate_read_packets(void)
1107 < {
1108 <        for( int i=0; i<PACKET_POOL_COUNT; i++ ) {
1109 <                packets[i] = PacketAllocatePacket(fd,1514);
1110 <                if(!packets[i]) {
1111 <                        D(bug("allocate_read_packets: out of memory\n"));
1112 <                        return(false);
1113 <                }
1114 <        }
1115 <        return(true);
1116 < }
1117 <
1118 < static void free_read_packets(void)
1119 < {
1120 <        for( int i=0; i<PACKET_POOL_COUNT; i++ ) {
1121 <                PacketFreePacket(packets[i]);
1122 <        }
1123 < }
1124 <
1125 < static unsigned int ether_thread_get_packets_nt(void *arg)
1126 < {
1127 <        static uint8 packet[1514];
1128 <        int i, packet_sz = 0;
1129 <
1130 <        thread_active_2 = true;
1131 <
1132 <        D(bug("ether_thread_get_packets_nt start\n"));
1133 <
1134 <        // Wait for packets to arrive.
1135 <        // Obey the golden rules; keep the reads pending.
1136 <        while(thread_active) {
1137 <
1138 <                if(net_if_type == NET_IF_B2ETHER) {
1139 <                        D(bug("Pending reads\n"));
1140 <                        for( i=0; thread_active && i<PACKET_POOL_COUNT; i++ ) {
1141 <                                if(packets[i]->free) {
1142 <                                        packets[i]->free = FALSE;
1143 <                                        if(PacketReceivePacket(fd,packets[i],FALSE)) {
1144 <                                                if(packets[i]->bIoComplete) {
1145 <                                                        D(bug("Early io completion...\n"));
1146 <                                                        packet_read_completion(
1147 <                                                                ERROR_SUCCESS,
1148 <                                                                packets[i]->BytesReceived,
1149 <                                                                &packets[i]->OverLapped
1150 <                                                                );
1151 <                                                }
1152 <                                        } else {
1153 <                                                packets[i]->free = TRUE;
1154 <                                        }
1155 <                                }
1156 <                        }
1157 <                }
1158 <
1159 <                if(thread_active && has_no_completed_io()) {
1160 <                        D(bug("Waiting for int_sig2\n"));
1161 <                        // "problem": awakens twice in a row. Fix if you increase the pool size.
1162 <                        WaitForSingleObjectEx(int_sig2,INFINITE,TRUE);
1163 <                }
1164 <        }
1165 <
1166 <        D(bug("ether_thread_get_packets_nt exit\n"));
1167 <
1168 <        thread_active_2 = false;
1169 <
1170 <        return 0;
1171 < }
1172 <
1173 < static unsigned int ether_thread_feed_int(void *arg)
1174 < {
1175 <        bool looping;
1176 <
1177 <        thread_active_3 = true;
1178 <
1179 <        D(bug("ether_thread_feed_int start\n"));
1180 <
1181 <        while(thread_active) {
1182 <                D(bug("Waiting for int_sig\n"));
1183 <                WaitForSingleObject(int_sig,INFINITE);
1184 <                // Looping this way to avoid a race condition.
1185 <                D(bug("Triggering\n"));
1186 <                looping = true;
1187 <                while(thread_active && looping) {
1188 <                        trigger_queue();
1189 <                        // Wait for interrupt acknowledge by EtherInterrupt()
1190 <                        WaitForSingleObject(int_ack,INFINITE);
1191 <                        if(thread_active) looping = set_wait_request();
1192 <                }
1193 <                D(bug("Queue empty.\n"));
1194 <        }
1195 <
1196 <        D(bug("ether_thread_feed_int exit\n"));
1197 <
1198 <        thread_active_3 = false;
1199 <
1200 <        return 0;
1201 < }
1202 <
1203 <
1204 < /*
1205 < *  Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers
1206 < */
1207 <
1208 < static void ether_do_interrupt(void)
1209 < {
1210 <        // Call protocol handler for received packets
1211 <        EthernetPacket ether_packet;
1212 <        uint32 packet = ether_packet.addr();
1213 <        ssize_t length;
1214 <        for (;;) {
1215 <
1216 <                // Read packet from Ethernet device
1217 <                length = dequeue_packet(Mac2HostAddr(packet));
1218 <                if (length < 14)
1219 <                        break;
1220 <
1221 < #if MONITOR
1222 <                bug("Receiving Ethernet packet (%d bytes):\n",(int)length);
1223 <                dump_packet( Mac2HostAddr(packet), length );
1224 < #endif
1225 <
1226 <                // Dispatch packet
1227 <                ether_dispatch_packet(packet, length);
1228 <        }
1229 < }
1230 <
1231 < #if DEBUG
1232 < #pragma optimize("",on)
1233 < #endif
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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines