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

# 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 // 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 #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
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 typedef struct _win_queue_t {
74 uint8 *buf;
75 int sz;
76 } win_queue_t;
77 #define MAX_QUEUE_ITEMS 1024
78 static win_queue_t queue[MAX_QUEUE_ITEMS];
79 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 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
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 * 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 * 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 static int16 ether_do_add_multicast(uint8 *addr)
646 {
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 if (!ether_fake && !PacketAddMulticast( fd, addr)) {
653 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 int16 ether_do_del_multicast(uint8 *addr)
667 {
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 if (!ether_fake && !PacketDelMulticast( fd, addr)) {
674 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 sprintf(sm," %02x", (int)packet[i]);
747 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 static int16 ether_do_write(uint32 arg)
906 {
907 D(bug("ether_write\r\n"));
908
909 // Copy packet to buffer
910 uint8 packet[1514], *p = packet;
911 int len = ether_arg_to_buffer(arg, p);
912
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 static void ether_do_interrupt(void)
1199 {
1200 // Call protocol handler for received packets
1201 EthernetPacket ether_packet;
1202 uint32 packet = ether_packet.addr();
1203 ssize_t length;
1204 for (;;) {
1205
1206 // Read packet from Ethernet device
1207 length = dequeue_packet(Mac2HostAddr(packet));
1208 if (length < 14)
1209 break;
1210
1211 #if MONITOR
1212 bug("Receiving Ethernet packet (%d bytes):\n",(int)length);
1213 dump_packet( Mac2HostAddr(packet), length );
1214 #endif
1215
1216 // Dispatch packet
1217 ether_dispatch_packet(packet, length);
1218 }
1219 }
1220
1221 #if DEBUG
1222 #pragma optimize("",on)
1223 #endif