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.4 by gbeauche, 2005-11-27T22:18:29Z vs.
Revision 1.8 by gbeauche, 2006-05-01T10:42:00Z

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines