~ubuntu-branches/ubuntu/feisty/basilisk2/feisty

« back to all changes in this revision

Viewing changes to src/Windows/ether_windows.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2006-06-01 01:11:16 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060601011116-xjhegbgyfsxag5fl
Tags: 0.9.20060529-1
* New upstream CVS snapshot.
* Update local cdbs snippet copyright-check.mk:
  + Broaden scan to also look for "(c)" by default.
  + Make egrep options configurable.
  + Ignore auto-tools files.
* Bump up standards-version to 3.7.2 (no changes needed).
* Let dh_strip do the stripping (not the make install target).

Show diffs side-by-side

added added

removed removed

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