ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/ether_windows.cpp
Revision: 1.1
Committed: 2004-12-06T23:31:03Z (19 years, 7 months ago) by gbeauche
Branch: MAIN
Log Message:
Raw import of ether_windows.cpp from original Basilisk II for Windows.
Fix code so that it builds in Cygwin/Mingw32.

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * ether_windows.cpp - Ethernet device driver
3     *
4     * Basilisk II (C) 1997-2004 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