ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/ether_windows.cpp
Revision: 1.6
Committed: 2006-04-29T10:57:56Z (18 years, 5 months ago) by gbeauche
Branch: MAIN
Changes since 1.5: +1321 -1233 lines
Log Message:
slirp now works on windows

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