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, 5 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

# Content
1 /*
2 * ether_windows.cpp - Ethernet device driver
3 *
4 * Basilisk II (C) 1997-2005 Christian Bauer
5 *
6 * Windows platform specific code copyright (C) Lauri Pesonen
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 #include <process.h>
24 #include <windowsx.h>
25 #include <ctype.h>
26
27 #include "sysdeps.h"
28 #include "cpu_emulation.h"
29 #include "main.h"
30 #include "macos_util.h"
31 #include "prefs.h"
32 #include "user_strings.h"
33 #include "ether.h"
34 #include "ether_defs.h"
35 #include "b2ether/multiopt.h"
36 #include "b2ether/inc/b2ether_hl.h"
37 #include "ether_windows.h"
38 #include "router/router.h"
39 #include "kernel_windows.h"
40
41
42 #define DEBUG 0
43 #define MONITOR 0
44
45 #if DEBUG
46 #pragma optimize("",off)
47 #endif
48
49 #include "debug.h"
50
51
52 // Ethernet device types
53 enum {
54 NET_IF_B2ETHER,
55 NET_IF_ROUTER,
56 NET_IF_FAKE,
57 };
58
59 // 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 static int net_if_type = -1; // Ethernet device type
69 #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
74 // These are protected by queue_csection
75 // Controls transfer for read thread to feed thread
76 static CRITICAL_SECTION queue_csection;
77 typedef struct _win_queue_t {
78 uint8 *buf;
79 int sz;
80 } win_queue_t;
81 #define MAX_QUEUE_ITEMS 1024
82 static win_queue_t queue[MAX_QUEUE_ITEMS];
83 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 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
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 if (name == NULL)
188 return false;
189
190 ether_multi_mode = PrefsFindInt32("ethermulticastmode");
191 ether_use_permanent = PrefsFindBool("etherpermanentaddress");
192
193 // 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 }
205
206 // 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
219 fd = PacketOpenAdapter( dev_name, ether_multi_mode );
220 if (!fd) {
221 sprintf(str, "Could not open ethernet adapter %s.", dev_name);
222 WarningAlert(str);
223 goto open_error;
224 }
225
226 // Get Ethernet address
227 if(!PacketGetMAC(fd,ether_addr,ether_use_permanent)) {
228 sprintf(str, "Could not get hardware address of device %s. Ethernet is not available.", dev_name);
229 WarningAlert(str);
230 goto open_error;
231 }
232 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
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 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 }
246 }
247 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
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 D(bug("Failed to create ethernet thread\n"));
309 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 if(net_if_type == NET_IF_B2ETHER) {
339 PacketCloseAdapter(fd);
340 }
341 fd = 0;
342 return false;
343 }
344
345
346 /*
347 * Deinitialization
348 */
349
350 void ether_exit(void)
351 {
352 D(bug("EtherExit\n"));
353
354 // Stop reception thread
355 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 D(bug("CancelIO if needed\n"));
363 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 D(bug("Wait delay\n"));
368 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 D(bug("Ether killing ether_th1\n"));
375 if(ether_th1) TerminateThread(ether_th1,0);
376 thread_active_1 = false;
377 }
378 if(thread_active_2) {
379 D(bug("Ether killing ether_th2\n"));
380 if(ether_th2) TerminateThread(ether_th2,0);
381 thread_active_2 = false;
382 }
383 if(thread_active_3) {
384 D(bug("Ether killing thread\n"));
385 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 D(bug("Closing semaphores\n"));
394 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 D(bug("Removing protocols\n"));
419 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 D(bug("Deleting sections\n"));
428 DeleteCriticalSection( &fetch_csection );
429 DeleteCriticalSection( &queue_csection );
430 DeleteCriticalSection( &send_csection );
431 DeleteCriticalSection( &wpool_csection );
432
433 D(bug("Freeing read packets\n"));
434 free_read_packets();
435
436 D(bug("Freeing write packets\n"));
437 free_write_packets();
438
439 D(bug("Finalizing queue\n"));
440 final_queue();
441
442 if (net_if_type == NET_IF_ROUTER) {
443 D(bug("Stopping router\n"));
444 router_final();
445 }
446
447 D(bug("EtherExit done\n"));
448 }
449
450
451 /*
452 * 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 D(bug(" EtherIRQ done\n"));
547 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 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
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 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 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 D(bug(" EtherIRQ done\n"));
612 ReleaseSemaphore(int_ack,1,NULL);
613 }
614 #endif
615
616
617 /*
618 * Reset
619 */
620
621 void ether_reset(void)
622 {
623 D(bug("EtherReset\n"));
624
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 static int16 ether_do_add_multicast(uint8 *addr)
641 {
642 D(bug("ether_add_multicast\n"));
643
644 // We wouldn't need to do this
645 // if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr;
646
647 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 return noErr;
656 }
657 }
658
659
660 /*
661 * Delete multicast address
662 */
663
664 int16 ether_do_del_multicast(uint8 *addr)
665 {
666 D(bug("ether_del_multicast\n"));
667
668 // We wouldn't need to do this
669 // if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr;
670
671 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 return noErr;
679 }
680 }
681
682
683 /*
684 * Attach protocol handler
685 */
686
687 int16 ether_attach_ph(uint16 type, uint32 handler)
688 {
689 D(bug("ether_attach_ph type=0x%x, handler=0x%x\n",(int)type,handler));
690
691 // Already attached?
692 NetProtocol *p = find_protocol(type);
693 if (p != NULL) {
694 D(bug("ether_attach_ph: lapProtErr\n"));
695 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 D(bug("ether_attach_ph: noErr\n"));
704 return noErr;
705 }
706 }
707
708
709 /*
710 * Detach protocol handler
711 */
712
713 int16 ether_detach_ph(uint16 type)
714 {
715 D(bug("ether_detach_ph type=%08lx\n",(int)type));
716
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 sprintf(sm," %02x", (int)packet[i]);
749 strcat( buf, sm );
750 }
751 strcat( buf, "\n" );
752 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 D(bug("Freeing write packet %ld\n",++i));
809 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 D(bug("Pool size after recycling = %ld\n",get_write_packet_pool_sz()));
820 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 D(bug("Pool size after get wr packet = %ld\n",get_write_packet_pool_sz()));
845
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 D(bug("ether_thread_write_packets start\n"));
858
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 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 Packet->bIoComplete = TRUE;
872 recycle_write_packet(Packet);
873 break;
874 case NET_IF_B2ETHER:
875 if(!PacketSendPacket( fd, Packet, FALSE, TRUE )) {
876 // already recycled if async
877 }
878 break;
879 }
880 }
881 }
882
883 D(bug("ether_thread_write_packets exit\n"));
884
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 D(bug("write_packet\n"));
895
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 static int16 ether_do_write(uint32 arg)
916 {
917 D(bug("ether_write\n"));
918
919 // Copy packet to buffer
920 uint8 packet[1514], *p = packet;
921 int len = ether_arg_to_buffer(arg, p);
922
923 if(len > 1514) {
924 D(bug("illegal packet length: %d\n",len));
925 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 D(bug("WARNING: couldn't transmit packet\n"));
936 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 D(bug("ethernet queue full, packet dropped\n"));
970 } 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 D(bug(" packet received, triggering Ethernet interrupt\n"));
1007 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 D(bug("packet_read_completion discarding own packet.\n"));
1056 dwNumberOfBytesTransfered = 0;
1057
1058 j = (j+1) & (~(MAX_ECHO-1));
1059 if(j != echo_count) {
1060 D(bug("Wow, this fix made some good after all...\n"));
1061 }
1062
1063 break;
1064 }
1065 }
1066 if(dwNumberOfBytesTransfered) {
1067 if(net_if_type != NET_IF_ROUTER || !router_read_packet((uint8 *)lpPacket->Buffer, dwNumberOfBytesTransfered)) {
1068 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 D(bug("allocate_read_packets: out of memory\n"));
1112 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 D(bug("ether_thread_get_packets_nt start\n"));
1133
1134 // Wait for packets to arrive.
1135 // Obey the golden rules; keep the reads pending.
1136 while(thread_active) {
1137
1138 if(net_if_type == NET_IF_B2ETHER) {
1139 D(bug("Pending reads\n"));
1140 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 D(bug("Early io completion...\n"));
1146 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 D(bug("Waiting for int_sig2\n"));
1161 // "problem": awakens twice in a row. Fix if you increase the pool size.
1162 WaitForSingleObjectEx(int_sig2,INFINITE,TRUE);
1163 }
1164 }
1165
1166 D(bug("ether_thread_get_packets_nt exit\n"));
1167
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 D(bug("ether_thread_feed_int start\n"));
1180
1181 while(thread_active) {
1182 D(bug("Waiting for int_sig\n"));
1183 WaitForSingleObject(int_sig,INFINITE);
1184 // Looping this way to avoid a race condition.
1185 D(bug("Triggering\n"));
1186 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 D(bug("Queue empty.\n"));
1194 }
1195
1196 D(bug("ether_thread_feed_int exit\n"));
1197
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 static void ether_do_interrupt(void)
1209 {
1210 // Call protocol handler for received packets
1211 EthernetPacket ether_packet;
1212 uint32 packet = ether_packet.addr();
1213 ssize_t length;
1214 for (;;) {
1215
1216 // Read packet from Ethernet device
1217 length = dequeue_packet(Mac2HostAddr(packet));
1218 if (length < 14)
1219 break;
1220
1221 #if MONITOR
1222 bug("Receiving Ethernet packet (%d bytes):\n",(int)length);
1223 dump_packet( Mac2HostAddr(packet), length );
1224 #endif
1225
1226 // Dispatch packet
1227 ether_dispatch_packet(packet, length);
1228 }
1229 }
1230
1231 #if DEBUG
1232 #pragma optimize("",on)
1233 #endif