ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/ether_windows.cpp
Revision: 1.2
Committed: 2005-01-30T21:42:15Z (19 years, 9 months ago) by gbeauche
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
Happy New Year!

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