2
* ether_windows.cpp - Ethernet device driver
4
* Basilisk II (C) 1997-2005 Christian Bauer
6
* Windows platform specific code copyright (C) Lauri Pesonen
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.
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.
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
28
#include "cpu_emulation.h"
30
#include "macos_util.h"
32
#include "user_strings.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"
46
#pragma optimize("",off)
53
bool ether_use_permanent = true;
54
static int16 ether_multi_mode = ETHER_MULTICAST_MAC;
58
unsigned int ether_tid;
63
// Need to fake a NIC if there is none but the router module is activated.
64
bool ether_fake = false;
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 {
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;
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;
90
// Write thread packet queue
91
static CRITICAL_SECTION send_csection;
92
static LPPACKET send_queue = 0;
95
// Write thread free packet pool
96
static CRITICAL_SECTION wpool_csection;
97
static LPPACKET write_packet_pool = 0;
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];
112
// List of attached protocols
119
static NetProtocol *prot_list = NULL;
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;
132
static char edevice[512];
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);
147
* Find protocol in list
150
static NetProtocol *find_protocol(uint16 type)
152
// All 802.2 types are the same
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;
172
bool ether_init(void)
176
// Initialize NAT-Router
179
// Do nothing if no Ethernet device specified
180
const char *name = PrefsFindString("ether");
182
strcpy(edevice, name);
184
bool there_is_a_router = PrefsFindBool("routerenabled");
186
if (!name || !*name) {
187
if( there_is_a_router ) {
188
strcpy( edevice, "None" );
195
ether_use_permanent = PrefsFindBool("etherpermanentaddress");
196
ether_multi_mode = PrefsFindInt32("ethermulticastmode");
198
// Open ethernet device
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]));
203
fd = PacketOpenAdapter( name, ether_multi_mode );
205
sprintf(str, "Could not open ethernet adapter %s.", name);
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);
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]));
218
const char *ether_fake_address;
219
ether_fake_address = PrefsFindString("etherfakeaddress");
220
if(ether_fake_address && strlen(ether_fake_address) == 12) {
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);
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]));
232
// Start packet reception thread
233
int_ack = CreateSemaphore( 0, 0, 1, NULL);
235
WarningAlert("WARNING: Cannot create int_ack semaphore");
240
int_sig = CreateSemaphore( 0, 0, 1, NULL);
242
WarningAlert("WARNING: Cannot create int_sig semaphore");
246
int_sig2 = CreateSemaphore( 0, 0, 1, NULL);
248
WarningAlert("WARNING: Cannot create int_sig2 semaphore");
252
int_send_now = CreateSemaphore( 0, 0, 1, NULL);
254
WarningAlert("WARNING: Cannot create int_send_now semaphore");
260
if(!allocate_read_packets()) goto open_error;
262
// No need to enter wait state if we can avoid it.
263
// These all terminate fast.
265
if(pfnInitializeCriticalSectionAndSpinCount) {
266
pfnInitializeCriticalSectionAndSpinCount( &fetch_csection, 5000 );
268
InitializeCriticalSection( &fetch_csection );
270
if(pfnInitializeCriticalSectionAndSpinCount) {
271
pfnInitializeCriticalSectionAndSpinCount( &queue_csection, 5000 );
273
InitializeCriticalSection( &queue_csection );
275
if(pfnInitializeCriticalSectionAndSpinCount) {
276
pfnInitializeCriticalSectionAndSpinCount( &send_csection, 5000 );
278
InitializeCriticalSection( &send_csection );
280
if(pfnInitializeCriticalSectionAndSpinCount) {
281
pfnInitializeCriticalSectionAndSpinCount( &wpool_csection, 5000 );
283
InitializeCriticalSection( &wpool_csection );
286
ether_th = (HANDLE)_beginthreadex( 0, 0, ether_thread_feed_int, 0, 0, ðer_tid );
288
D(bug("Failed to create ethernet thread\r\n"));
291
thread_active = true;
293
SetThreadPriority( ether_th, threads[THREAD_ETHER].priority_running );
294
SetThreadAffinityMask( ether_th, threads[THREAD_ETHER].affinity_mask );
298
ether_th2 = (HANDLE)_beginthreadex( 0, 0, ether_thread_get_packets_nt, 0, 0, &dummy );
300
SetThreadPriority( ether_th2, threads[THREAD_ETHER].priority_running );
301
SetThreadAffinityMask( ether_th2, threads[THREAD_ETHER].affinity_mask );
304
ether_th1 = (HANDLE)_beginthreadex( 0, 0, ether_thread_write_packets, 0, 0, &dummy );
306
SetThreadPriority( ether_th1, threads[THREAD_ETHER].priority_running );
307
SetThreadAffinityMask( ether_th1, threads[THREAD_ETHER].affinity_mask );
315
TerminateThread(ether_th,0);
318
CloseHandle(int_ack);
321
CloseHandle(int_sig);
324
CloseHandle(int_sig2);
327
CloseHandle(int_send_now);
329
thread_active = false;
332
PacketCloseAdapter(fd);
343
void ether_exit(void)
345
D(bug("EtherExit\r\n"));
347
// Take them down in a controlled way.
348
thread_active = false;
352
D(bug("Closing ethernet device %s\r\n",edevice));
354
if(!*edevice) return;
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);
361
D(bug("CancelIO if needed\r\n"));
362
if (fd && fd->hFile && pfnCancelIo)
363
pfnCancelIo(fd->hFile);
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;
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;
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;
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;
392
D(bug("Closing semaphores\r\n"));
394
CloseHandle(int_ack);
398
CloseHandle(int_sig);
402
CloseHandle(int_sig2);
406
CloseHandle(int_send_now);
410
// Close ethernet device
412
PacketCloseAdapter(fd);
416
// Remove all protocols
417
D(bug("Removing protocols\r\n"));
418
NetProtocol *p = prot_list;
420
NetProtocol *next = p->next;
426
D(bug("Deleting sections\r\n"));
427
DeleteCriticalSection( &fetch_csection );
428
DeleteCriticalSection( &queue_csection );
429
DeleteCriticalSection( &send_csection );
430
DeleteCriticalSection( &wpool_csection );
432
D(bug("Freeing read packets\r\n"));
435
D(bug("Freeing write packets\r\n"));
436
free_write_packets();
438
D(bug("Finalizing queue\r\n"));
441
D(bug("Stopping router\r\n"));
444
D(bug("EtherExit done\r\n"));
452
void ether_reset(void)
454
D(bug("EtherReset\r\n"));
456
// Remove all protocols
457
NetProtocol *p = prot_list;
459
NetProtocol *next = p->next;
468
* Add multicast address
471
int16 ether_add_multicast(uint32 pb)
473
D(bug("ether_add_multicast\r\n"));
475
// We wouldn't need to do this
476
// if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr;
478
if (!ether_fake && !PacketAddMulticast( fd, Mac2HostAddr(pb + eMultiAddr))) {
479
D(bug("WARNING: couldn't enable multicast address\r\n"));
482
D(bug("ether_add_multicast: noErr\r\n"));
489
* Delete multicast address
492
int16 ether_del_multicast(uint32 pb)
494
D(bug("ether_del_multicast\r\n"));
496
// We wouldn't need to do this
497
// if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr;
499
if (!ether_fake && !PacketDelMulticast( fd, Mac2HostAddr(pb + eMultiAddr))) {
500
D(bug("WARNING: couldn't disable multicast address\r\n"));
508
* Attach protocol handler
511
int16 ether_attach_ph(uint16 type, uint32 handler)
513
D(bug("ether_attach_ph type=0x%x, handler=0x%x\r\n",(int)type,handler));
516
NetProtocol *p = find_protocol(type);
518
D(bug("ether_attach_ph: lapProtErr\r\n"));
521
// No, create and attach
525
p->handler = handler;
527
D(bug("ether_attach_ph: noErr\r\n"));
534
* Detach protocol handler
537
int16 ether_detach_ph(uint16 type)
539
D(bug("ether_detach_ph type=%08lx\r\n",(int)type));
541
NetProtocol *p = find_protocol(type);
543
NetProtocol *previous = 0;
544
NetProtocol *q = prot_list;
548
previous->next = q->next;
563
static void dump_packet( uint8 *packet, int length )
565
char buf[1000], sm[10];
569
if(length > 256) length = 256;
571
for (int i=0; i<length; i++) {
572
sprintf(sm,"%02x", (int)packet[i]);
575
strcat( buf, "\r\n" );
582
* Transmit raw ethernet packet
585
static void insert_send_queue( LPPACKET Packet )
587
EnterCriticalSection( &send_csection );
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;
597
LeaveCriticalSection( &send_csection );
600
static LPPACKET get_send_head( void )
604
EnterCriticalSection( &send_csection );
607
send_queue = send_queue->next;
609
LeaveCriticalSection( &send_csection );
614
static int get_write_packet_pool_sz( void )
616
LPPACKET t = write_packet_pool;
626
static void free_write_packets( void )
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;
638
void recycle_write_packet( LPPACKET Packet )
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 );
647
static LPPACKET get_write_packet( UINT len )
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;
662
// actually an auto-reset event.
663
if(Packet->OverLapped.hEvent) ResetEvent(Packet->OverLapped.hEvent);
665
Packet = PacketAllocatePacket(fd,len);
668
D(bug("Pool size after get wr packet = %ld\r\n",get_write_packet_pool_sz()));
670
LeaveCriticalSection( &wpool_csection );
675
static unsigned int ether_thread_write_packets(void *arg)
679
thread_active_1 = true;
681
D(bug("ether_thread_write_packets start\r\n"));
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
699
D(bug("ether_thread_write_packets exit\r\n"));
701
thread_active_1 = false;
706
static BOOL write_packet( uint8 *packet, int len )
710
D(bug("write_packet\r\n"));
712
Packet = get_write_packet(len);
714
memcpy( Packet->Buffer, packet, len );
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 );
722
insert_send_queue( Packet );
724
ReleaseSemaphore(int_send_now,1,NULL);
731
int16 ether_write(uint32 wds)
733
D(bug("ether_write\r\n"));
735
// Set source address
736
uint32 hdr = ReadMacInt32(wds + 2);
737
memcpy(Mac2HostAddr(hdr + 6), ether_addr, 6);
739
// Copy packet to buffer
740
uint8 packet[1514], *p = packet;
743
uint16 w = (uint16)ReadMacInt16(wds);
746
memcpy(p, Mac2HostAddr(ReadMacInt32(wds + 2)), w);
753
D(bug("illegal packet length: %d\r\n",len));
757
bug("Sending Ethernet packet (%d bytes):\n",(int)len);
758
dump_packet( packet, len );
763
if (!write_packet(packet, len)) {
764
D(bug("WARNING: couldn't transmit packet\r\n"));
765
return excessCollsns;
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.
776
static void init_queue(void)
781
for( int i=0; i<MAX_QUEUE_ITEMS; i++ ) {
782
queue[i].buf = (uint8 *)malloc( 1514 );
787
static void final_queue(void)
789
for( int i=0; i<MAX_QUEUE_ITEMS; i++ ) {
790
if(queue[i].buf) free(queue[i].buf);
794
void enqueue_packet( uint8 *buf, int sz )
796
EnterCriticalSection( &queue_csection );
797
if(queue[queue_inx].sz > 0) {
798
D(bug("ethernet queue full, packet dropped\r\n"));
800
if(sz > 1514) sz = 1514;
801
queue[queue_inx].sz = sz;
802
memcpy( queue[queue_inx].buf, buf, sz );
804
if(queue_inx >= MAX_QUEUE_ITEMS) queue_inx = 0;
806
wait_request = false;
807
ReleaseSemaphore(int_sig,1,NULL);
810
LeaveCriticalSection( &queue_csection );
813
static int dequeue_packet( uint8 *buf )
817
if(!thread_active) return(0);
819
EnterCriticalSection( &queue_csection );
820
sz = queue[queue_head].sz;
822
memcpy( buf, queue[queue_head].buf, sz );
823
queue[queue_head].sz = 0;
825
if(queue_head >= MAX_QUEUE_ITEMS) queue_head = 0;
827
LeaveCriticalSection( &queue_csection );
831
static void trigger_queue(void)
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);
838
// of course can't wait here.
840
LeaveCriticalSection( &queue_csection );
843
static bool set_wait_request(void)
846
EnterCriticalSection( &queue_csection );
847
if(queue[queue_head].sz) {
853
LeaveCriticalSection( &queue_csection );
859
* Packet reception threads
862
VOID CALLBACK packet_read_completion(
864
DWORD dwNumberOfBytesTransfered,
865
LPOVERLAPPED lpOverlapped
868
EnterCriticalSection( &fetch_csection );
870
LPPACKET lpPacket = CONTAINING_RECORD(lpOverlapped,PACKET,OverLapped);
872
D(bug("packet_read_completion bytes=%d, error code=%d\n",dwNumberOfBytesTransfered,dwErrorCode));
874
if(thread_active && !dwErrorCode) {
875
int count = min(dwNumberOfBytesTransfered,1514);
878
for(int i=MAX_ECHO; i; i--) {
880
if(j < 0) j = MAX_ECHO-1;
881
if(count == pending_packet_sz[j] &&
882
memcmp(pending_packet[j],lpPacket->Buffer,count) == 0)
884
D(bug("packet_read_completion discarding own packet.\r\n"));
885
dwNumberOfBytesTransfered = 0;
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"));
895
if(dwNumberOfBytesTransfered) {
896
if(!m_router_enabled || !router_read_packet((uint8 *)lpPacket->Buffer, dwNumberOfBytesTransfered)) {
897
enqueue_packet( (LPBYTE)lpPacket->Buffer, dwNumberOfBytesTransfered );
903
// actually an auto-reset event.
904
if(lpPacket->OverLapped.hEvent) ResetEvent(lpPacket->OverLapped.hEvent);
906
lpPacket->free = TRUE;
907
lpPacket->bIoComplete = TRUE;
910
wait_request2 = false;
911
ReleaseSemaphore(int_sig2,1,NULL);
914
LeaveCriticalSection( &fetch_csection );
917
static BOOL has_no_completed_io(void)
921
EnterCriticalSection( &fetch_csection );
923
for( int i=0; i<PACKET_POOL_COUNT; i++ ) {
924
if(packets[i]->bIoComplete) {
929
if(result) wait_request2 = true;
931
LeaveCriticalSection( &fetch_csection );
935
static bool allocate_read_packets(void)
937
for( int i=0; i<PACKET_POOL_COUNT; i++ ) {
938
packets[i] = PacketAllocatePacket(fd,1514);
940
D(bug("allocate_read_packets: out of memory\r\n"));
947
static void free_read_packets(void)
949
for( int i=0; i<PACKET_POOL_COUNT; i++ ) {
950
PacketFreePacket(packets[i]);
954
static unsigned int ether_thread_get_packets_nt(void *arg)
956
static uint8 packet[1514];
957
int i, packet_sz = 0;
959
thread_active_2 = true;
961
D(bug("ether_thread_get_packets_nt start\r\n"));
963
// Wait for packets to arrive.
964
// Obey the golden rules; keep the reads pending.
965
while(thread_active) {
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(
977
packets[i]->BytesReceived,
978
&packets[i]->OverLapped
982
packets[i]->free = TRUE;
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);
995
D(bug("ether_thread_get_packets_nt exit\r\n"));
997
thread_active_2 = false;
1002
static unsigned int ether_thread_feed_int(void *arg)
1006
thread_active_3 = true;
1008
D(bug("ether_thread_feed_int start\r\n"));
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"));
1016
while(thread_active && looping) {
1018
// Wait for interrupt acknowledge by EtherInterrupt()
1019
WaitForSingleObject(int_ack,INFINITE);
1020
if(thread_active) looping = set_wait_request();
1022
D(bug("Queue empty.\r\n"));
1025
D(bug("ether_thread_feed_int exit\r\n"));
1027
thread_active_3 = false;
1034
* Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers
1037
void EtherInterrupt(void)
1040
EthernetPacket ether_packet;
1041
uint32 packet = ether_packet.addr();
1043
D(bug("EtherIRQ\r\n"));
1045
// Call protocol handler for received packets
1046
while( (length = dequeue_packet(Mac2HostAddr(packet))) > 0 ) {
1052
bug("Receiving Ethernet packet (%d bytes):\n",(int)length);
1053
dump_packet( Mac2HostAddr(packet), length );
1057
uint16 type = ReadMacInt16(packet + 12);
1059
// Look for protocol
1060
NetProtocol *prot = find_protocol(type);
1065
// No default handler
1066
if (prot->handler == 0)
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)));
1074
// Call protocol handler
1076
r.d[0] = type; // Packet type
1077
r.d[1] = length - 14; // Remaining packet length (without header, for ReadPacket)
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);
1086
// Acknowledge interrupt to reception thread
1087
D(bug(" EtherIRQ done\r\n"));
1088
ReleaseSemaphore(int_ack,1,NULL);
1092
#pragma optimize("",on)
2
* ether_windows.cpp - Ethernet device driver
4
* Basilisk II (C) 1997-2005 Christian Bauer
6
* Windows platform specific code copyright (C) Lauri Pesonen
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.
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.
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
30
#include "cpu_emulation.h"
32
#include "macos_util.h"
34
#include "user_strings.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"
44
// Define to let the slirp library determine the right timeout for select()
45
#define USE_SLIRP_TIMEOUT 1
52
#pragma optimize("",off)
58
// Ethernet device types
67
// TAP-Win32 constants
68
#define TAP_VERSION_MIN_MAJOR 7
69
#define TAP_VERSION_MIN_MINOR 1
71
#define TAP_CONTROL_CODE(request, method) \
72
CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
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)
84
#define OLD_TAP_CONTROL_CODE(request, method) \
85
CTL_CODE (FILE_DEVICE_PHYSICAL_NETCARD | 8000, request, method, FILE_ANY_ACCESS)
87
#define OLD_TAP_IOCTL_GET_VERSION OLD_TAP_CONTROL_CODE (3, METHOD_BUFFERED)
90
bool ether_use_permanent = true;
91
static int16 ether_multi_mode = ETHER_MULTICAST_MAC;
95
unsigned int ether_tid;
98
static int net_if_type = -1; // Ethernet device type
100
static bool net_open = false; // Flag: initialization succeeded, network device open
101
uint8 ether_addr[6]; // Our Ethernet address
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 {
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;
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;
128
// Write thread packet queue
129
static CRITICAL_SECTION send_csection;
130
static LPPACKET send_queue = 0;
133
// Write thread free packet pool
134
static CRITICAL_SECTION wpool_csection;
135
static LPPACKET write_packet_pool = 0;
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];
150
// List of attached protocols
157
static NetProtocol *prot_list = NULL;
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;
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);
194
* Find protocol in list
197
static NetProtocol *find_protocol(uint16 type)
199
// All 802.2 types are the same
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;
219
bool ether_init(void)
223
// Do nothing if no Ethernet device specified
224
const char *name = PrefsFindString("ether");
228
ether_multi_mode = PrefsFindInt32("ethermulticastmode");
229
ether_use_permanent = PrefsFindBool("etherpermanentaddress");
231
// Determine Ethernet device type
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;
240
net_if_type = NET_IF_B2ETHER;
242
// Initialize NAT-Router
243
if (net_if_type == NET_IF_ROUTER) {
245
net_if_type = NET_IF_FAKE;
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));
257
// Open ethernet device
258
const char *dev_name;
259
switch (net_if_type) {
261
dev_name = PrefsFindString("etherguid");
262
if (dev_name == NULL || strcmp(name, "b2ether") != 0)
266
dev_name = PrefsFindString("etherguid");
269
if (net_if_type == NET_IF_B2ETHER) {
270
if (dev_name == NULL) {
271
WarningAlert("No ethernet device GUID specified. Ethernet is not available.");
275
fd = PacketOpenAdapter( dev_name, ether_multi_mode );
277
sprintf(str, "Could not open ethernet adapter %s.", dev_name);
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);
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]));
290
const char *ether_fake_address;
291
ether_fake_address = PrefsFindString("etherfakeaddress");
292
if(ether_fake_address && strlen(ether_fake_address) == 12) {
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);
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]));
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.");
309
fd = tap_open_adapter(dev_name);
311
sprintf(str, "Could not open ethernet adapter %s.", dev_name);
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);
322
if (!tap_set_status(fd, true)) {
323
sprintf(str, "Could not set media status to connected.");
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);
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]));
335
const char *ether_fake_address;
336
ether_fake_address = PrefsFindString("etherfakeaddress");
337
if (ether_fake_address && strlen(ether_fake_address) == 12) {
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);
348
If we bridge the underlying ethernet connection and the TAP
349
device altogether, we have to use a fake address.
352
ether_addr[0] = 0x52;
353
ether_addr[1] = 0x54;
354
ether_addr[2] = 0x00;
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]));
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]));
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]));
373
// Start packet reception thread
374
int_ack = CreateSemaphore( 0, 0, 1, NULL);
376
WarningAlert("WARNING: Cannot create int_ack semaphore");
381
int_sig = CreateSemaphore( 0, 0, 1, NULL);
383
WarningAlert("WARNING: Cannot create int_sig semaphore");
387
int_sig2 = CreateSemaphore( 0, 0, 1, NULL);
389
WarningAlert("WARNING: Cannot create int_sig2 semaphore");
393
int_send_now = CreateSemaphore( 0, 0, 1, NULL);
395
WarningAlert("WARNING: Cannot create int_send_now semaphore");
401
if(!allocate_read_packets()) goto open_error;
403
// No need to enter wait state if we can avoid it.
404
// These all terminate fast.
406
if(pfnInitializeCriticalSectionAndSpinCount) {
407
pfnInitializeCriticalSectionAndSpinCount( &fetch_csection, 5000 );
409
InitializeCriticalSection( &fetch_csection );
411
if(pfnInitializeCriticalSectionAndSpinCount) {
412
pfnInitializeCriticalSectionAndSpinCount( &queue_csection, 5000 );
414
InitializeCriticalSection( &queue_csection );
416
if(pfnInitializeCriticalSectionAndSpinCount) {
417
pfnInitializeCriticalSectionAndSpinCount( &send_csection, 5000 );
419
InitializeCriticalSection( &send_csection );
421
if(pfnInitializeCriticalSectionAndSpinCount) {
422
pfnInitializeCriticalSectionAndSpinCount( &wpool_csection, 5000 );
424
InitializeCriticalSection( &wpool_csection );
427
ether_th = (HANDLE)_beginthreadex( 0, 0, ether_thread_feed_int, 0, 0, ðer_tid );
429
D(bug("Failed to create ethernet thread\n"));
432
thread_active = true;
435
unsigned int (WINAPI *receive_func)(void *);
436
switch (net_if_type) {
438
receive_func = slirp_receive_func;
441
receive_func = ether_thread_get_packets_nt;
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 );
452
TerminateThread(ether_th,0);
455
CloseHandle(int_ack);
458
CloseHandle(int_sig);
461
CloseHandle(int_sig2);
464
CloseHandle(int_send_now);
466
thread_active = false;
469
switch (net_if_type) {
471
PacketCloseAdapter(fd);
474
tap_close_adapter(fd);
487
void ether_exit(void)
489
D(bug("EtherExit\n"));
491
// Stop reception thread
492
thread_active = false;
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);
499
D(bug("CancelIO if needed\n"));
500
if (fd && fd->hFile && pfnCancelIo)
501
pfnCancelIo(fd->hFile);
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;
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;
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;
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;
530
D(bug("Closing semaphores\n"));
532
CloseHandle(int_ack);
536
CloseHandle(int_sig);
540
CloseHandle(int_sig2);
544
CloseHandle(int_send_now);
548
// Close ethernet device
550
switch (net_if_type) {
552
PacketCloseAdapter(fd);
555
tap_close_adapter(fd);
561
// Remove all protocols
562
D(bug("Removing protocols\n"));
563
NetProtocol *p = prot_list;
565
NetProtocol *next = p->next;
571
D(bug("Deleting sections\n"));
572
DeleteCriticalSection( &fetch_csection );
573
DeleteCriticalSection( &queue_csection );
574
DeleteCriticalSection( &send_csection );
575
DeleteCriticalSection( &wpool_csection );
577
D(bug("Freeing read packets\n"));
580
D(bug("Freeing write packets\n"));
581
free_write_packets();
583
D(bug("Finalizing queue\n"));
586
if (net_if_type == NET_IF_ROUTER) {
587
D(bug("Stopping router\n"));
591
D(bug("EtherExit done\n"));
596
* Glue around low-level implementation
608
// Initialize ethernet
613
// Do nothing if the user disabled the network
614
if (PrefsFindBool("nonet"))
617
net_open = ether_init();
627
// Get ethernet hardware address
628
void AO_get_ethernet_address(uint32 arg)
630
uint8 *addr = Mac2HostAddr(arg);
632
OTCopy48BitAddress(ether_addr, addr);
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]));
644
// Add multicast address
645
void AO_enable_multicast(uint32 addr)
648
ether_do_add_multicast(Mac2HostAddr(addr));
651
// Disable multicast address
652
void AO_disable_multicast(uint32 addr)
655
ether_do_del_multicast(Mac2HostAddr(addr));
658
// Transmit one packet
659
void AO_transmit_packet(uint32 mp)
662
switch (ether_do_write(mp)) {
667
num_tx_buffer_full++;
673
// Copy packet data from message block to linear buffer
674
static inline int ether_arg_to_buffer(uint32 mp, uint8 *p)
676
return ether_msgb_to_buffer(mp, p);
679
// Ethernet interrupt
682
D(bug("EtherIRQ\n"));
686
ether_do_interrupt();
689
// Acknowledge interrupt to reception thread
690
D(bug(" EtherIRQ done\n"));
691
ReleaseSemaphore(int_ack,1,NULL);
694
// Add multicast address
695
int16 ether_add_multicast(uint32 pb)
697
return ether_do_add_multicast(Mac2HostAddr(pb + eMultiAddr));
700
// Disable multicast address
701
int16 ether_del_multicast(uint32 pb)
703
return ether_do_del_multicast(Mac2HostAddr(pb + eMultiAddr));
706
// Transmit one packet
707
int16 ether_write(uint32 wds)
709
return ether_do_write(wds);
712
// Copy packet data from WDS to linear buffer
713
static inline int ether_arg_to_buffer(uint32 wds, uint8 *p)
715
return ether_wds_to_buffer(wds, p);
718
// Dispatch packet to protocol handler
719
static void ether_dispatch_packet(uint32 packet, uint32 length)
722
uint16 type = ReadMacInt16(packet + 12);
725
NetProtocol *prot = find_protocol(type);
729
// No default handler
730
if (prot->handler == 0)
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)));
737
// Call protocol handler
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);
748
// Ethernet interrupt
749
void EtherInterrupt(void)
751
D(bug("EtherIRQ\n"));
752
ether_do_interrupt();
754
// Acknowledge interrupt to reception thread
755
D(bug(" EtherIRQ done\n"));
756
ReleaseSemaphore(int_ack,1,NULL);
765
void ether_reset(void)
767
D(bug("EtherReset\n"));
769
// Remove all protocols
770
NetProtocol *p = prot_list;
772
NetProtocol *next = p->next;
781
* Add multicast address
784
static int16 ether_do_add_multicast(uint8 *addr)
786
D(bug("ether_add_multicast\n"));
788
// We wouldn't need to do this
789
// if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr;
791
switch (net_if_type) {
793
if (!PacketAddMulticast( fd, addr)) {
794
D(bug("WARNING: couldn't enable multicast address\n"));
798
D(bug("ether_add_multicast: noErr\n"));
805
* Delete multicast address
808
int16 ether_do_del_multicast(uint8 *addr)
810
D(bug("ether_del_multicast\n"));
812
// We wouldn't need to do this
813
// if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr;
815
switch (net_if_type) {
817
if (!PacketDelMulticast( fd, addr)) {
818
D(bug("WARNING: couldn't disable multicast address\n"));
828
* Attach protocol handler
831
int16 ether_attach_ph(uint16 type, uint32 handler)
833
D(bug("ether_attach_ph type=0x%x, handler=0x%x\n",(int)type,handler));
836
NetProtocol *p = find_protocol(type);
838
D(bug("ether_attach_ph: lapProtErr\n"));
841
// No, create and attach
845
p->handler = handler;
847
D(bug("ether_attach_ph: noErr\n"));
854
* Detach protocol handler
857
int16 ether_detach_ph(uint16 type)
859
D(bug("ether_detach_ph type=%08lx\n",(int)type));
861
NetProtocol *p = find_protocol(type);
863
NetProtocol *previous = 0;
864
NetProtocol *q = prot_list;
868
previous->next = q->next;
883
static void dump_packet( uint8 *packet, int length )
885
char buf[1000], sm[10];
889
if(length > 256) length = 256;
891
for (int i=0; i<length; i++) {
892
sprintf(sm," %02x", (int)packet[i]);
902
* Transmit raw ethernet packet
905
static void insert_send_queue( LPPACKET Packet )
907
EnterCriticalSection( &send_csection );
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;
917
LeaveCriticalSection( &send_csection );
920
static LPPACKET get_send_head( void )
924
EnterCriticalSection( &send_csection );
927
send_queue = send_queue->next;
929
LeaveCriticalSection( &send_csection );
934
static int get_write_packet_pool_sz( void )
936
LPPACKET t = write_packet_pool;
946
static void free_write_packets( void )
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;
958
void recycle_write_packet( LPPACKET Packet )
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 );
967
static LPPACKET get_write_packet( UINT len )
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;
982
// actually an auto-reset event.
983
if(Packet->OverLapped.hEvent) ResetEvent(Packet->OverLapped.hEvent);
985
Packet = PacketAllocatePacket(fd,len);
988
D(bug("Pool size after get wr packet = %ld\n",get_write_packet_pool_sz()));
990
LeaveCriticalSection( &wpool_csection );
995
static unsigned int ether_thread_write_packets(void *arg)
999
thread_active_1 = true;
1001
D(bug("ether_thread_write_packets start\n"));
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) {
1009
if(router_write_packet((uint8 *)Packet->Buffer, Packet->Length)) {
1010
Packet->bIoComplete = TRUE;
1011
recycle_write_packet(Packet);
1015
Packet->bIoComplete = TRUE;
1016
recycle_write_packet(Packet);
1018
case NET_IF_B2ETHER:
1019
if(!PacketSendPacket( fd, Packet, FALSE, TRUE )) {
1020
// already recycled if async
1024
if (!tap_send_packet(fd, Packet, FALSE, TRUE)) {
1025
// already recycled if async
1029
slirp_input((uint8 *)Packet->Buffer, Packet->Length);
1030
Packet->bIoComplete = TRUE;
1031
recycle_write_packet(Packet);
1037
D(bug("ether_thread_write_packets exit\n"));
1039
thread_active_1 = false;
1044
static BOOL write_packet( uint8 *packet, int len )
1048
D(bug("write_packet\n"));
1050
Packet = get_write_packet(len);
1052
memcpy( Packet->Buffer, packet, len );
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 );
1060
insert_send_queue( Packet );
1062
ReleaseSemaphore(int_send_now,1,NULL);
1069
static int16 ether_do_write(uint32 arg)
1071
D(bug("ether_write\n"));
1073
// Copy packet to buffer
1074
uint8 packet[1514], *p = packet;
1075
int len = ether_arg_to_buffer(arg, p);
1078
D(bug("illegal packet length: %d\n",len));
1082
bug("Sending Ethernet packet (%d bytes):\n",(int)len);
1083
dump_packet( packet, len );
1088
if (!write_packet(packet, len)) {
1089
D(bug("WARNING: couldn't transmit packet\n"));
1090
return excessCollsns;
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.
1101
static void init_queue(void)
1106
for( int i=0; i<MAX_QUEUE_ITEMS; i++ ) {
1107
queue[i].buf = (uint8 *)malloc( 1514 );
1112
static void final_queue(void)
1114
for( int i=0; i<MAX_QUEUE_ITEMS; i++ ) {
1115
if(queue[i].buf) free(queue[i].buf);
1119
void enqueue_packet( const uint8 *buf, int sz )
1121
EnterCriticalSection( &queue_csection );
1122
if(queue[queue_inx].sz > 0) {
1123
D(bug("ethernet queue full, packet dropped\n"));
1125
if(sz > 1514) sz = 1514;
1126
queue[queue_inx].sz = sz;
1127
memcpy( queue[queue_inx].buf, buf, sz );
1129
if(queue_inx >= MAX_QUEUE_ITEMS) queue_inx = 0;
1131
wait_request = false;
1132
ReleaseSemaphore(int_sig,1,NULL);
1135
LeaveCriticalSection( &queue_csection );
1138
static int dequeue_packet( uint8 *buf )
1142
if(!thread_active) return(0);
1144
EnterCriticalSection( &queue_csection );
1145
sz = queue[queue_head].sz;
1147
memcpy( buf, queue[queue_head].buf, sz );
1148
queue[queue_head].sz = 0;
1150
if(queue_head >= MAX_QUEUE_ITEMS) queue_head = 0;
1152
LeaveCriticalSection( &queue_csection );
1156
static void trigger_queue(void)
1158
EnterCriticalSection( &queue_csection );
1159
if( queue[queue_head].sz > 0 ) {
1160
D(bug(" packet received, triggering Ethernet interrupt\n"));
1161
SetInterruptFlag(INTFLAG_ETHER);
1163
// of course can't wait here.
1165
LeaveCriticalSection( &queue_csection );
1168
static bool set_wait_request(void)
1171
EnterCriticalSection( &queue_csection );
1172
if(queue[queue_head].sz) {
1176
wait_request = true;
1178
LeaveCriticalSection( &queue_csection );
1187
static LPADAPTER tap_open_adapter(const char *dev_name)
1189
fd = (LPADAPTER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(*fd));
1193
char dev_path[MAX_PATH];
1194
snprintf(dev_path, sizeof(dev_path),
1195
"\\\\.\\Global\\%s.tap", dev_name);
1197
HANDLE handle = CreateFile(
1199
GENERIC_READ | GENERIC_WRITE,
1203
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
1205
if (handle == NULL || handle == INVALID_HANDLE_VALUE)
1212
static void tap_close_adapter(LPADAPTER fd)
1216
tap_set_status(fd, false);
1217
CloseHandle(fd->hFile);
1223
static bool tap_check_version(LPADAPTER fd)
1226
ULONG info[3] = { 0, };
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))
1236
if (info[0] > TAP_VERSION_MIN_MAJOR)
1238
if (info[0] == TAP_VERSION_MIN_MAJOR && info[1] >= TAP_VERSION_MIN_MINOR)
1244
static bool tap_set_status(LPADAPTER fd, ULONG status)
1247
return DeviceIoControl(fd->hFile, TAP_IOCTL_SET_MEDIA_STATUS,
1248
&status, sizeof (status),
1249
&status, sizeof (status), &len, NULL);
1252
static bool tap_get_mac(LPADAPTER fd, LPBYTE addr)
1255
return DeviceIoControl(fd->hFile, TAP_IOCTL_GET_MAC,
1257
addr, 6, &len, NULL);
1261
static VOID CALLBACK tap_write_completion(
1263
DWORD dwNumberOfBytesTransfered,
1264
LPOVERLAPPED lpOverLapped
1267
LPPACKET lpPacket = CONTAINING_RECORD(lpOverLapped, PACKET, OverLapped);
1269
lpPacket->bIoComplete = TRUE;
1270
recycle_write_packet(lpPacket);
1273
static bool tap_send_packet(
1277
BOOLEAN RecyclingAllowed)
1281
lpPacket->OverLapped.Offset = 0;
1282
lpPacket->OverLapped.OffsetHigh = 0;
1283
lpPacket->bIoComplete = FALSE;
1286
Result = WriteFile(fd->hFile,
1289
&lpPacket->BytesReceived,
1290
&lpPacket->OverLapped);
1292
GetOverlappedResult(fd->hFile,
1293
&lpPacket->OverLapped,
1294
&lpPacket->BytesReceived,
1297
lpPacket->bIoComplete = TRUE;
1298
if (RecyclingAllowed)
1299
PacketFreePacket(lpPacket);
1302
Result = WriteFileEx(fd->hFile,
1305
&lpPacket->OverLapped,
1306
tap_write_completion);
1308
if (!Result && RecyclingAllowed)
1309
recycle_write_packet(lpPacket);
1315
static bool tap_receive_packet(LPADAPTER fd, LPPACKET lpPacket, BOOLEAN Sync)
1319
lpPacket->OverLapped.Offset = 0;
1320
lpPacket->OverLapped.OffsetHigh = 0;
1321
lpPacket->bIoComplete = FALSE;
1324
Result = ReadFile(fd->hFile,
1327
&lpPacket->BytesReceived,
1328
&lpPacket->OverLapped);
1330
Result = GetOverlappedResult(fd->hFile,
1331
&lpPacket->OverLapped,
1332
&lpPacket->BytesReceived,
1335
lpPacket->bIoComplete = TRUE;
1337
lpPacket->free = TRUE;
1341
Result = ReadFileEx(fd->hFile,
1344
&lpPacket->OverLapped,
1345
packet_read_completion);
1348
lpPacket->BytesReceived = 0;
1356
* SLIRP output buffer glue
1359
int slirp_can_output(void)
1364
void slirp_output(const uint8 *packet, int len)
1366
enqueue_packet(packet, len);
1369
static unsigned int slirp_receive_func(void *arg)
1371
D(bug("slirp_receive_func\n"));
1372
thread_active_2 = true;
1374
while (thread_active) {
1375
// Wait for packets to arrive
1376
fd_set rfds, wfds, xfds;
1377
int nfds, ret, timeout;
1379
// ... in the output queue
1384
timeout = slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
1385
#if ! USE_SLIRP_TIMEOUT
1389
/* Windows does not honour the timeout if there is not
1390
descriptor to wait for */
1391
Delay_usec(timeout);
1397
tv.tv_usec = timeout;
1398
ret = select(0, &rfds, &wfds, &xfds, &tv);
1401
slirp_select_poll(&rfds, &wfds, &xfds);
1404
D(bug("slirp_receive_func exit\n"));
1405
thread_active_2 = false;
1411
* Packet reception threads
1414
VOID CALLBACK packet_read_completion(
1416
DWORD dwNumberOfBytesTransfered,
1417
LPOVERLAPPED lpOverlapped
1420
EnterCriticalSection( &fetch_csection );
1422
LPPACKET lpPacket = CONTAINING_RECORD(lpOverlapped,PACKET,OverLapped);
1424
D(bug("packet_read_completion bytes=%d, error code=%d\n",dwNumberOfBytesTransfered,dwErrorCode));
1426
if(thread_active && !dwErrorCode) {
1427
int count = min(dwNumberOfBytesTransfered,1514);
1430
for(int i=MAX_ECHO; i; i--) {
1432
if(j < 0) j = MAX_ECHO-1;
1433
if(count == pending_packet_sz[j] &&
1434
memcmp(pending_packet[j],lpPacket->Buffer,count) == 0)
1436
D(bug("packet_read_completion discarding own packet.\n"));
1437
dwNumberOfBytesTransfered = 0;
1439
j = (j+1) & (~(MAX_ECHO-1));
1440
if(j != echo_count) {
1441
D(bug("Wow, this fix made some good after all...\n"));
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;
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 );
1460
// actually an auto-reset event.
1461
if(lpPacket->OverLapped.hEvent) ResetEvent(lpPacket->OverLapped.hEvent);
1463
lpPacket->free = TRUE;
1464
lpPacket->bIoComplete = TRUE;
1467
wait_request2 = false;
1468
ReleaseSemaphore(int_sig2,1,NULL);
1471
LeaveCriticalSection( &fetch_csection );
1474
static BOOL has_no_completed_io(void)
1478
EnterCriticalSection( &fetch_csection );
1480
for( int i=0; i<PACKET_POOL_COUNT; i++ ) {
1481
if(packets[i]->bIoComplete) {
1486
if(result) wait_request2 = true;
1488
LeaveCriticalSection( &fetch_csection );
1492
static bool allocate_read_packets(void)
1494
for( int i=0; i<PACKET_POOL_COUNT; i++ ) {
1495
packets[i] = PacketAllocatePacket(fd,1514);
1497
D(bug("allocate_read_packets: out of memory\n"));
1504
static void free_read_packets(void)
1506
for( int i=0; i<PACKET_POOL_COUNT; i++ ) {
1507
PacketFreePacket(packets[i]);
1511
static unsigned int ether_thread_get_packets_nt(void *arg)
1513
static uint8 packet[1514];
1514
int i, packet_sz = 0;
1516
thread_active_2 = true;
1518
D(bug("ether_thread_get_packets_nt start\n"));
1520
// Wait for packets to arrive.
1521
// Obey the golden rules; keep the reads pending.
1522
while(thread_active) {
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;
1530
switch (net_if_type) {
1531
case NET_IF_B2ETHER:
1532
Result = PacketReceivePacket(fd, packets[i], FALSE);
1535
Result = tap_receive_packet(fd, packets[i], FALSE);
1539
if(packets[i]->bIoComplete) {
1540
D(bug("Early io completion...\n"));
1541
packet_read_completion(
1543
packets[i]->BytesReceived,
1544
&packets[i]->OverLapped
1548
packets[i]->free = TRUE;
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);
1561
D(bug("ether_thread_get_packets_nt exit\n"));
1563
thread_active_2 = false;
1568
static unsigned int ether_thread_feed_int(void *arg)
1572
thread_active_3 = true;
1574
D(bug("ether_thread_feed_int start\n"));
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"));
1582
while(thread_active && looping) {
1584
// Wait for interrupt acknowledge by EtherInterrupt()
1585
WaitForSingleObject(int_ack,INFINITE);
1586
if(thread_active) looping = set_wait_request();
1588
D(bug("Queue empty.\n"));
1591
D(bug("ether_thread_feed_int exit\n"));
1593
thread_active_3 = false;
1600
* Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers
1603
static void ether_do_interrupt(void)
1605
// Call protocol handler for received packets
1606
EthernetPacket ether_packet;
1607
uint32 packet = ether_packet.addr();
1611
// Read packet from Ethernet device
1612
length = dequeue_packet(Mac2HostAddr(packet));
1617
bug("Receiving Ethernet packet (%d bytes):\n",(int)length);
1618
dump_packet( Mac2HostAddr(packet), length );
1622
ether_dispatch_packet(packet, length);
1627
#pragma optimize("",on)