ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/ether_windows.cpp
Revision: 1.6
Committed: 2006-04-29T10:57:56Z (18 years, 7 months ago) by gbeauche
Branch: MAIN
Changes since 1.5: +1321 -1233 lines
Log Message:
slirp now works on windows

File Contents

# User Rev Content
1 gbeauche 1.6 /*
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