~ubuntu-branches/ubuntu/vivid/basilisk2/vivid

« back to all changes in this revision

Viewing changes to src/Windows/ether_windows.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2008-03-06 19:33:01 UTC
  • mfrom: (2.1.4 gutsy)
  • Revision ID: james.westby@ubuntu.com-20080306193301-cc2ofn705nfsq3y0
Tags: 0.9.20070407-4
* Update copyright-check cdbs snippet to parse licensecheck using perl:
  + No longer randomly drops newlines
  + More compact hint file (and ordered more like wiki-proposed new copyright
    syntax).
  + No longer ignore files without copyright.
* Update copyright_hints.

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 "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