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.2 by gbeauche, 2005-01-30T21:42:15Z vs.
Revision 1.6 by gbeauche, 2006-04-29T10:57:56Z

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines