ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/ether_windows.cpp
Revision: 1.4
Committed: 2005-11-27T22:18:29Z (18 years, 7 months ago) by gbeauche
Branch: MAIN
CVS Tags: nigel-build-17
Changes since 1.3: +193 -63 lines
Log Message:
SheepShaver glue for Ethernet support. Remove duplicate "Set source address"
case from common code.

File Contents

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