ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/ether_windows.cpp
Revision: 1.5
Committed: 2006-04-23T15:36:51Z (18 years, 6 months ago) by gbeauche
Branch: MAIN
Changes since 1.4: +132 -122 lines
Log Message:
Some clean-ups. Rewrite ethernet config interpreter. This implies some
prefs items changes but it should now be simpler to add other ethernet
emulation means (slirp, tap-win32).

# Basilisk II driver mode
	ether {guid}
becomes
	ether b2ether
	etherguid {guid}

# Basilisk II Router mode
	routerenabled true
becomes
	ether router

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