1 |
|
/* |
2 |
|
* ether_windows.cpp - Ethernet device driver |
3 |
|
* |
4 |
< |
* Basilisk II (C) 1997-2004 Christian Bauer |
4 |
> |
* Basilisk II (C) 1997-2005 Christian Bauer |
5 |
|
* |
6 |
|
* Windows platform specific code copyright (C) Lauri Pesonen |
7 |
|
* |
49 |
|
#include "debug.h" |
50 |
|
|
51 |
|
|
52 |
+ |
// Ethernet device types |
53 |
+ |
enum { |
54 |
+ |
NET_IF_B2ETHER, |
55 |
+ |
NET_IF_ROUTER, |
56 |
+ |
NET_IF_FAKE, |
57 |
+ |
}; |
58 |
+ |
|
59 |
|
// Options |
60 |
|
bool ether_use_permanent = true; |
61 |
|
static int16 ether_multi_mode = ETHER_MULTICAST_MAC; |
65 |
|
unsigned int ether_tid; |
66 |
|
HANDLE ether_th1; |
67 |
|
HANDLE ether_th2; |
68 |
< |
|
69 |
< |
|
70 |
< |
// Need to fake a NIC if there is none but the router module is activated. |
71 |
< |
bool ether_fake = false; |
68 |
> |
static int net_if_type = -1; // Ethernet device type |
69 |
> |
#ifdef SHEEPSHAVER |
70 |
> |
static bool net_open = false; // Flag: initialization succeeded, network device open |
71 |
> |
uint8 ether_addr[6]; // Our Ethernet address |
72 |
> |
#endif |
73 |
|
|
74 |
|
// These are protected by queue_csection |
75 |
|
// Controls transfer for read thread to feed thread |
76 |
|
static CRITICAL_SECTION queue_csection; |
77 |
< |
typedef struct _queue_t { |
77 |
> |
typedef struct _win_queue_t { |
78 |
|
uint8 *buf; |
79 |
|
int sz; |
80 |
< |
} queue_t; |
80 |
> |
} win_queue_t; |
81 |
|
#define MAX_QUEUE_ITEMS 1024 |
82 |
< |
static queue_t queue[MAX_QUEUE_ITEMS]; |
82 |
> |
static win_queue_t queue[MAX_QUEUE_ITEMS]; |
83 |
|
static int queue_head = 0; |
84 |
|
static int queue_inx = 0; |
85 |
|
static bool wait_request = true; |
137 |
|
static HANDLE int_sig2 = 0; |
138 |
|
static HANDLE int_send_now = 0; |
139 |
|
|
132 |
– |
static char edevice[512]; |
133 |
– |
|
134 |
– |
|
140 |
|
// Prototypes |
141 |
|
static WINAPI unsigned int ether_thread_feed_int(void *arg); |
142 |
|
static WINAPI unsigned int ether_thread_get_packets_nt(void *arg); |
146 |
|
static bool allocate_read_packets(void); |
147 |
|
static void free_read_packets(void); |
148 |
|
static void free_write_packets(void); |
149 |
+ |
static int16 ether_do_add_multicast(uint8 *addr); |
150 |
+ |
static int16 ether_do_del_multicast(uint8 *addr); |
151 |
+ |
static int16 ether_do_write(uint32 arg); |
152 |
+ |
static void ether_do_interrupt(void); |
153 |
|
|
154 |
|
|
155 |
|
/* |
182 |
|
{ |
183 |
|
char str[256]; |
184 |
|
|
176 |
– |
// Initialize NAT-Router |
177 |
– |
router_init(); |
178 |
– |
|
185 |
|
// Do nothing if no Ethernet device specified |
186 |
|
const char *name = PrefsFindString("ether"); |
187 |
< |
if (name) |
188 |
< |
strcpy(edevice, name); |
187 |
> |
if (name == NULL) |
188 |
> |
return false; |
189 |
|
|
190 |
< |
bool there_is_a_router = PrefsFindBool("routerenabled"); |
190 |
> |
ether_multi_mode = PrefsFindInt32("ethermulticastmode"); |
191 |
> |
ether_use_permanent = PrefsFindBool("etherpermanentaddress"); |
192 |
|
|
193 |
< |
if (!name || !*name) { |
194 |
< |
if( there_is_a_router ) { |
195 |
< |
strcpy( edevice, "None" ); |
196 |
< |
ether_fake = true; |
197 |
< |
} else { |
198 |
< |
return false; |
192 |
< |
} |
193 |
< |
} |
193 |
> |
// Determine Ethernet device type |
194 |
> |
net_if_type = -1; |
195 |
> |
if (strcmp(name, "router") == 0) |
196 |
> |
net_if_type = NET_IF_ROUTER; |
197 |
> |
else |
198 |
> |
net_if_type = NET_IF_B2ETHER; |
199 |
|
|
200 |
< |
ether_use_permanent = PrefsFindBool("etherpermanentaddress"); |
201 |
< |
ether_multi_mode = PrefsFindInt32("ethermulticastmode"); |
200 |
> |
// Initialize NAT-Router |
201 |
> |
if (net_if_type == NET_IF_ROUTER) { |
202 |
> |
if (!router_init()) |
203 |
> |
net_if_type = NET_IF_FAKE; |
204 |
> |
} |
205 |
|
|
206 |
|
// Open ethernet device |
207 |
< |
if(ether_fake) { |
208 |
< |
memcpy( ether_addr, router_mac_addr, 6 ); |
209 |
< |
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])); |
210 |
< |
} else { |
211 |
< |
fd = PacketOpenAdapter( name, ether_multi_mode ); |
207 |
> |
const char *dev_name; |
208 |
> |
switch (net_if_type) { |
209 |
> |
case NET_IF_B2ETHER: |
210 |
> |
dev_name = PrefsFindString("etherguid"); |
211 |
> |
break; |
212 |
> |
} |
213 |
> |
if (net_if_type == NET_IF_B2ETHER) { |
214 |
> |
if (dev_name == NULL) { |
215 |
> |
WarningAlert("No ethernet device GUID specified. Ethernet is not available."); |
216 |
> |
goto open_error; |
217 |
> |
} |
218 |
> |
|
219 |
> |
fd = PacketOpenAdapter( dev_name, ether_multi_mode ); |
220 |
|
if (!fd) { |
221 |
< |
sprintf(str, "Could not open ethernet adapter %s.", name); |
221 |
> |
sprintf(str, "Could not open ethernet adapter %s.", dev_name); |
222 |
|
WarningAlert(str); |
223 |
|
goto open_error; |
224 |
|
} |
225 |
|
|
226 |
|
// Get Ethernet address |
227 |
|
if(!PacketGetMAC(fd,ether_addr,ether_use_permanent)) { |
228 |
< |
sprintf(str, "Could not get hardware address of device %s. Ethernet is not available.", name); |
228 |
> |
sprintf(str, "Could not get hardware address of device %s. Ethernet is not available.", dev_name); |
229 |
|
WarningAlert(str); |
230 |
|
goto open_error; |
231 |
|
} |
232 |
< |
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])); |
232 |
> |
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])); |
233 |
|
|
234 |
|
const char *ether_fake_address; |
235 |
|
ether_fake_address = PrefsFindString("etherfakeaddress"); |
241 |
|
sm[3] = ether_fake_address[i*2+1]; |
242 |
|
ether_addr[i] = (uint8)strtoul(sm,0,0); |
243 |
|
} |
244 |
< |
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])); |
244 |
> |
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])); |
245 |
|
} |
246 |
|
} |
247 |
+ |
else { |
248 |
+ |
memcpy( ether_addr, router_mac_addr, 6 ); |
249 |
+ |
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])); |
250 |
+ |
} |
251 |
|
|
252 |
|
// Start packet reception thread |
253 |
|
int_ack = CreateSemaphore( 0, 0, 1, NULL); |
305 |
|
|
306 |
|
ether_th = (HANDLE)_beginthreadex( 0, 0, ether_thread_feed_int, 0, 0, ðer_tid ); |
307 |
|
if (!ether_th) { |
308 |
< |
D(bug("Failed to create ethernet thread\r\n")); |
308 |
> |
D(bug("Failed to create ethernet thread\n")); |
309 |
|
goto open_error; |
310 |
|
} |
311 |
|
thread_active = true; |
292 |
– |
#if 0 |
293 |
– |
SetThreadPriority( ether_th, threads[THREAD_ETHER].priority_running ); |
294 |
– |
SetThreadAffinityMask( ether_th, threads[THREAD_ETHER].affinity_mask ); |
295 |
– |
#endif |
312 |
|
|
313 |
|
unsigned int dummy; |
314 |
|
ether_th2 = (HANDLE)_beginthreadex( 0, 0, ether_thread_get_packets_nt, 0, 0, &dummy ); |
299 |
– |
#if 0 |
300 |
– |
SetThreadPriority( ether_th2, threads[THREAD_ETHER].priority_running ); |
301 |
– |
SetThreadAffinityMask( ether_th2, threads[THREAD_ETHER].affinity_mask ); |
302 |
– |
#endif |
303 |
– |
|
315 |
|
ether_th1 = (HANDLE)_beginthreadex( 0, 0, ether_thread_write_packets, 0, 0, &dummy ); |
305 |
– |
#if 0 |
306 |
– |
SetThreadPriority( ether_th1, threads[THREAD_ETHER].priority_running ); |
307 |
– |
SetThreadAffinityMask( ether_th1, threads[THREAD_ETHER].affinity_mask ); |
308 |
– |
#endif |
316 |
|
|
317 |
|
// Everything OK |
318 |
|
return true; |
335 |
|
int_send_now = 0; |
336 |
|
thread_active = false; |
337 |
|
} |
338 |
< |
if(!ether_fake) { |
338 |
> |
if(net_if_type == NET_IF_B2ETHER) { |
339 |
|
PacketCloseAdapter(fd); |
340 |
|
} |
341 |
|
fd = 0; |
349 |
|
|
350 |
|
void ether_exit(void) |
351 |
|
{ |
352 |
< |
D(bug("EtherExit\r\n")); |
352 |
> |
D(bug("EtherExit\n")); |
353 |
|
|
354 |
< |
// Take them down in a controlled way. |
354 |
> |
// Stop reception thread |
355 |
|
thread_active = false; |
356 |
|
|
350 |
– |
// _asm int 3 |
351 |
– |
|
352 |
– |
D(bug("Closing ethernet device %s\r\n",edevice)); |
353 |
– |
|
354 |
– |
if(!*edevice) return; |
355 |
– |
|
357 |
|
if(int_ack) ReleaseSemaphore(int_ack,1,NULL); |
358 |
|
if(int_sig) ReleaseSemaphore(int_sig,1,NULL); |
359 |
|
if(int_sig2) ReleaseSemaphore(int_sig2,1,NULL); |
360 |
|
if(int_send_now) ReleaseSemaphore(int_send_now,1,NULL); |
361 |
|
|
362 |
< |
D(bug("CancelIO if needed\r\n")); |
362 |
> |
D(bug("CancelIO if needed\n")); |
363 |
|
if (fd && fd->hFile && pfnCancelIo) |
364 |
|
pfnCancelIo(fd->hFile); |
365 |
|
|
366 |
|
// Wait max 2 secs to shut down pending io. After that, kill them. |
367 |
< |
D(bug("Wait delay\r\n")); |
367 |
> |
D(bug("Wait delay\n")); |
368 |
|
for( int i=0; i<10; i++ ) { |
369 |
|
if(!thread_active_1 && !thread_active_2 && !thread_active_3) break; |
370 |
|
Sleep(200); |
371 |
|
} |
372 |
|
|
373 |
|
if(thread_active_1) { |
374 |
< |
D(bug("Ether killing ether_th1\r\n")); |
374 |
> |
D(bug("Ether killing ether_th1\n")); |
375 |
|
if(ether_th1) TerminateThread(ether_th1,0); |
376 |
|
thread_active_1 = false; |
377 |
|
} |
378 |
|
if(thread_active_2) { |
379 |
< |
D(bug("Ether killing ether_th2\r\n")); |
379 |
> |
D(bug("Ether killing ether_th2\n")); |
380 |
|
if(ether_th2) TerminateThread(ether_th2,0); |
381 |
|
thread_active_2 = false; |
382 |
|
} |
383 |
|
if(thread_active_3) { |
384 |
< |
D(bug("Ether killing thread\r\n")); |
384 |
> |
D(bug("Ether killing thread\n")); |
385 |
|
if(ether_th) TerminateThread(ether_th,0); |
386 |
|
thread_active_3 = false; |
387 |
|
} |
390 |
|
ether_th2 = 0; |
391 |
|
ether_th = 0; |
392 |
|
|
393 |
< |
D(bug("Closing semaphores\r\n")); |
393 |
> |
D(bug("Closing semaphores\n")); |
394 |
|
if(int_ack) { |
395 |
|
CloseHandle(int_ack); |
396 |
|
int_ack = 0; |
415 |
|
} |
416 |
|
|
417 |
|
// Remove all protocols |
418 |
< |
D(bug("Removing protocols\r\n")); |
418 |
> |
D(bug("Removing protocols\n")); |
419 |
|
NetProtocol *p = prot_list; |
420 |
|
while (p) { |
421 |
|
NetProtocol *next = p->next; |
424 |
|
} |
425 |
|
prot_list = 0; |
426 |
|
|
427 |
< |
D(bug("Deleting sections\r\n")); |
427 |
> |
D(bug("Deleting sections\n")); |
428 |
|
DeleteCriticalSection( &fetch_csection ); |
429 |
|
DeleteCriticalSection( &queue_csection ); |
430 |
|
DeleteCriticalSection( &send_csection ); |
431 |
|
DeleteCriticalSection( &wpool_csection ); |
432 |
|
|
433 |
< |
D(bug("Freeing read packets\r\n")); |
433 |
> |
D(bug("Freeing read packets\n")); |
434 |
|
free_read_packets(); |
435 |
|
|
436 |
< |
D(bug("Freeing write packets\r\n")); |
436 |
> |
D(bug("Freeing write packets\n")); |
437 |
|
free_write_packets(); |
438 |
|
|
439 |
< |
D(bug("Finalizing queue\r\n")); |
439 |
> |
D(bug("Finalizing queue\n")); |
440 |
|
final_queue(); |
441 |
|
|
442 |
< |
D(bug("Stopping router\r\n")); |
443 |
< |
router_final(); |
442 |
> |
if (net_if_type == NET_IF_ROUTER) { |
443 |
> |
D(bug("Stopping router\n")); |
444 |
> |
router_final(); |
445 |
> |
} |
446 |
|
|
447 |
< |
D(bug("EtherExit done\r\n")); |
447 |
> |
D(bug("EtherExit done\n")); |
448 |
|
} |
449 |
|
|
450 |
|
|
451 |
|
/* |
452 |
+ |
* Glue around low-level implementation |
453 |
+ |
*/ |
454 |
+ |
|
455 |
+ |
#ifdef SHEEPSHAVER |
456 |
+ |
// Error codes |
457 |
+ |
enum { |
458 |
+ |
eMultiErr = -91, |
459 |
+ |
eLenErr = -92, |
460 |
+ |
lapProtErr = -94, |
461 |
+ |
excessCollsns = -95 |
462 |
+ |
}; |
463 |
+ |
|
464 |
+ |
// Initialize ethernet |
465 |
+ |
void EtherInit(void) |
466 |
+ |
{ |
467 |
+ |
net_open = false; |
468 |
+ |
|
469 |
+ |
// Do nothing if the user disabled the network |
470 |
+ |
if (PrefsFindBool("nonet")) |
471 |
+ |
return; |
472 |
+ |
|
473 |
+ |
net_open = ether_init(); |
474 |
+ |
} |
475 |
+ |
|
476 |
+ |
// Exit ethernet |
477 |
+ |
void EtherExit(void) |
478 |
+ |
{ |
479 |
+ |
ether_exit(); |
480 |
+ |
net_open = false; |
481 |
+ |
} |
482 |
+ |
|
483 |
+ |
// Get ethernet hardware address |
484 |
+ |
void AO_get_ethernet_address(uint32 arg) |
485 |
+ |
{ |
486 |
+ |
uint8 *addr = Mac2HostAddr(arg); |
487 |
+ |
if (net_open) |
488 |
+ |
OTCopy48BitAddress(ether_addr, addr); |
489 |
+ |
else { |
490 |
+ |
addr[0] = 0x12; |
491 |
+ |
addr[1] = 0x34; |
492 |
+ |
addr[2] = 0x56; |
493 |
+ |
addr[3] = 0x78; |
494 |
+ |
addr[4] = 0x9a; |
495 |
+ |
addr[5] = 0xbc; |
496 |
+ |
} |
497 |
+ |
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])); |
498 |
+ |
} |
499 |
+ |
|
500 |
+ |
// Add multicast address |
501 |
+ |
void AO_enable_multicast(uint32 addr) |
502 |
+ |
{ |
503 |
+ |
if (net_open) |
504 |
+ |
ether_do_add_multicast(Mac2HostAddr(addr)); |
505 |
+ |
} |
506 |
+ |
|
507 |
+ |
// Disable multicast address |
508 |
+ |
void AO_disable_multicast(uint32 addr) |
509 |
+ |
{ |
510 |
+ |
if (net_open) |
511 |
+ |
ether_do_del_multicast(Mac2HostAddr(addr)); |
512 |
+ |
} |
513 |
+ |
|
514 |
+ |
// Transmit one packet |
515 |
+ |
void AO_transmit_packet(uint32 mp) |
516 |
+ |
{ |
517 |
+ |
if (net_open) { |
518 |
+ |
switch (ether_do_write(mp)) { |
519 |
+ |
case noErr: |
520 |
+ |
num_tx_packets++; |
521 |
+ |
break; |
522 |
+ |
case excessCollsns: |
523 |
+ |
num_tx_buffer_full++; |
524 |
+ |
break; |
525 |
+ |
} |
526 |
+ |
} |
527 |
+ |
} |
528 |
+ |
|
529 |
+ |
// Copy packet data from message block to linear buffer |
530 |
+ |
static inline int ether_arg_to_buffer(uint32 mp, uint8 *p) |
531 |
+ |
{ |
532 |
+ |
return ether_msgb_to_buffer(mp, p); |
533 |
+ |
} |
534 |
+ |
|
535 |
+ |
// Ethernet interrupt |
536 |
+ |
void EtherIRQ(void) |
537 |
+ |
{ |
538 |
+ |
D(bug("EtherIRQ\n")); |
539 |
+ |
num_ether_irq++; |
540 |
+ |
|
541 |
+ |
OTEnterInterrupt(); |
542 |
+ |
ether_do_interrupt(); |
543 |
+ |
OTLeaveInterrupt(); |
544 |
+ |
|
545 |
+ |
// Acknowledge interrupt to reception thread |
546 |
+ |
D(bug(" EtherIRQ done\n")); |
547 |
+ |
ReleaseSemaphore(int_ack,1,NULL); |
548 |
+ |
} |
549 |
+ |
#else |
550 |
+ |
// Add multicast address |
551 |
+ |
int16 ether_add_multicast(uint32 pb) |
552 |
+ |
{ |
553 |
+ |
return ether_do_add_multicast(Mac2HostAddr(pb + eMultiAddr)); |
554 |
+ |
} |
555 |
+ |
|
556 |
+ |
// Disable multicast address |
557 |
+ |
int16 ether_del_multicast(uint32 pb) |
558 |
+ |
{ |
559 |
+ |
return ether_do_del_multicast(Mac2HostAddr(pb + eMultiAddr)); |
560 |
+ |
} |
561 |
+ |
|
562 |
+ |
// Transmit one packet |
563 |
+ |
int16 ether_write(uint32 wds) |
564 |
+ |
{ |
565 |
+ |
return ether_do_write(wds); |
566 |
+ |
} |
567 |
+ |
|
568 |
+ |
// Copy packet data from WDS to linear buffer |
569 |
+ |
static inline int ether_arg_to_buffer(uint32 wds, uint8 *p) |
570 |
+ |
{ |
571 |
+ |
return ether_wds_to_buffer(wds, p); |
572 |
+ |
} |
573 |
+ |
|
574 |
+ |
// Dispatch packet to protocol handler |
575 |
+ |
static void ether_dispatch_packet(uint32 packet, uint32 length) |
576 |
+ |
{ |
577 |
+ |
// Get packet type |
578 |
+ |
uint16 type = ReadMacInt16(packet + 12); |
579 |
+ |
|
580 |
+ |
// Look for protocol |
581 |
+ |
NetProtocol *prot = find_protocol(type); |
582 |
+ |
if (prot == NULL) |
583 |
+ |
return; |
584 |
+ |
|
585 |
+ |
// No default handler |
586 |
+ |
if (prot->handler == 0) |
587 |
+ |
return; |
588 |
+ |
|
589 |
+ |
// Copy header to RHA |
590 |
+ |
Mac2Mac_memcpy(ether_data + ed_RHA, packet, 14); |
591 |
+ |
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))); |
592 |
+ |
|
593 |
+ |
// Call protocol handler |
594 |
+ |
M68kRegisters r; |
595 |
+ |
r.d[0] = type; // Packet type |
596 |
+ |
r.d[1] = length - 14; // Remaining packet length (without header, for ReadPacket) |
597 |
+ |
r.a[0] = packet + 14; // Pointer to packet (Mac address, for ReadPacket) |
598 |
+ |
r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA |
599 |
+ |
r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines |
600 |
+ |
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])); |
601 |
+ |
Execute68k(prot->handler, &r); |
602 |
+ |
} |
603 |
+ |
|
604 |
+ |
// Ethernet interrupt |
605 |
+ |
void EtherInterrupt(void) |
606 |
+ |
{ |
607 |
+ |
D(bug("EtherIRQ\n")); |
608 |
+ |
ether_do_interrupt(); |
609 |
+ |
|
610 |
+ |
// Acknowledge interrupt to reception thread |
611 |
+ |
D(bug(" EtherIRQ done\n")); |
612 |
+ |
ReleaseSemaphore(int_ack,1,NULL); |
613 |
+ |
} |
614 |
+ |
#endif |
615 |
+ |
|
616 |
+ |
|
617 |
+ |
/* |
618 |
|
* Reset |
619 |
|
*/ |
620 |
|
|
621 |
|
void ether_reset(void) |
622 |
|
{ |
623 |
< |
D(bug("EtherReset\r\n")); |
623 |
> |
D(bug("EtherReset\n")); |
624 |
|
|
625 |
|
// Remove all protocols |
626 |
|
NetProtocol *p = prot_list; |
637 |
|
* Add multicast address |
638 |
|
*/ |
639 |
|
|
640 |
< |
int16 ether_add_multicast(uint32 pb) |
640 |
> |
static int16 ether_do_add_multicast(uint8 *addr) |
641 |
|
{ |
642 |
< |
D(bug("ether_add_multicast\r\n")); |
642 |
> |
D(bug("ether_add_multicast\n")); |
643 |
|
|
644 |
|
// We wouldn't need to do this |
645 |
|
// if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr; |
646 |
|
|
647 |
< |
if (!ether_fake && !PacketAddMulticast( fd, Mac2HostAddr(pb + eMultiAddr))) { |
648 |
< |
D(bug("WARNING: couldn't enable multicast address\r\n")); |
649 |
< |
return eMultiErr; |
650 |
< |
} else { |
651 |
< |
D(bug("ether_add_multicast: noErr\r\n")); |
647 |
> |
switch (net_if_type) { |
648 |
> |
case NET_IF_B2ETHER: |
649 |
> |
if (!PacketAddMulticast( fd, addr)) { |
650 |
> |
D(bug("WARNING: couldn't enable multicast address\n")); |
651 |
> |
return eMultiErr; |
652 |
> |
} |
653 |
> |
default: |
654 |
> |
D(bug("ether_add_multicast: noErr\n")); |
655 |
|
return noErr; |
656 |
|
} |
657 |
|
} |
661 |
|
* Delete multicast address |
662 |
|
*/ |
663 |
|
|
664 |
< |
int16 ether_del_multicast(uint32 pb) |
664 |
> |
int16 ether_do_del_multicast(uint8 *addr) |
665 |
|
{ |
666 |
< |
D(bug("ether_del_multicast\r\n")); |
666 |
> |
D(bug("ether_del_multicast\n")); |
667 |
|
|
668 |
|
// We wouldn't need to do this |
669 |
|
// if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr; |
670 |
|
|
671 |
< |
if (!ether_fake && !PacketDelMulticast( fd, Mac2HostAddr(pb + eMultiAddr))) { |
672 |
< |
D(bug("WARNING: couldn't disable multicast address\r\n")); |
673 |
< |
return eMultiErr; |
674 |
< |
} else |
671 |
> |
switch (net_if_type) { |
672 |
> |
case NET_IF_B2ETHER: |
673 |
> |
if (!PacketDelMulticast( fd, addr)) { |
674 |
> |
D(bug("WARNING: couldn't disable multicast address\n")); |
675 |
> |
return eMultiErr; |
676 |
> |
} |
677 |
> |
default: |
678 |
|
return noErr; |
679 |
+ |
} |
680 |
|
} |
681 |
|
|
682 |
|
|
686 |
|
|
687 |
|
int16 ether_attach_ph(uint16 type, uint32 handler) |
688 |
|
{ |
689 |
< |
D(bug("ether_attach_ph type=0x%x, handler=0x%x\r\n",(int)type,handler)); |
689 |
> |
D(bug("ether_attach_ph type=0x%x, handler=0x%x\n",(int)type,handler)); |
690 |
|
|
691 |
|
// Already attached? |
692 |
|
NetProtocol *p = find_protocol(type); |
693 |
|
if (p != NULL) { |
694 |
< |
D(bug("ether_attach_ph: lapProtErr\r\n")); |
694 |
> |
D(bug("ether_attach_ph: lapProtErr\n")); |
695 |
|
return lapProtErr; |
696 |
|
} else { |
697 |
|
// No, create and attach |
700 |
|
p->type = type; |
701 |
|
p->handler = handler; |
702 |
|
prot_list = p; |
703 |
< |
D(bug("ether_attach_ph: noErr\r\n")); |
703 |
> |
D(bug("ether_attach_ph: noErr\n")); |
704 |
|
return noErr; |
705 |
|
} |
706 |
|
} |
712 |
|
|
713 |
|
int16 ether_detach_ph(uint16 type) |
714 |
|
{ |
715 |
< |
D(bug("ether_detach_ph type=%08lx\r\n",(int)type)); |
715 |
> |
D(bug("ether_detach_ph type=%08lx\n",(int)type)); |
716 |
|
|
717 |
|
NetProtocol *p = find_protocol(type); |
718 |
|
if (p != NULL) { |
745 |
|
if(length > 256) length = 256; |
746 |
|
|
747 |
|
for (int i=0; i<length; i++) { |
748 |
< |
sprintf(sm,"%02x", (int)packet[i]); |
748 |
> |
sprintf(sm," %02x", (int)packet[i]); |
749 |
|
strcat( buf, sm ); |
750 |
|
} |
751 |
< |
strcat( buf, "\r\n" ); |
751 |
> |
strcat( buf, "\n" ); |
752 |
|
bug(buf); |
753 |
|
} |
754 |
|
#endif |
805 |
|
int i = 0; |
806 |
|
while(write_packet_pool) { |
807 |
|
next = write_packet_pool->next; |
808 |
< |
D(bug("Freeing write packet %ld\r\n",++i)); |
808 |
> |
D(bug("Freeing write packet %ld\n",++i)); |
809 |
|
PacketFreePacket(write_packet_pool); |
810 |
|
write_packet_pool = next; |
811 |
|
} |
816 |
|
EnterCriticalSection( &wpool_csection ); |
817 |
|
Packet->next = write_packet_pool; |
818 |
|
write_packet_pool = Packet; |
819 |
< |
D(bug("Pool size after recycling = %ld\r\n",get_write_packet_pool_sz())); |
819 |
> |
D(bug("Pool size after recycling = %ld\n",get_write_packet_pool_sz())); |
820 |
|
LeaveCriticalSection( &wpool_csection ); |
821 |
|
} |
822 |
|
|
841 |
|
Packet = PacketAllocatePacket(fd,len); |
842 |
|
} |
843 |
|
|
844 |
< |
D(bug("Pool size after get wr packet = %ld\r\n",get_write_packet_pool_sz())); |
844 |
> |
D(bug("Pool size after get wr packet = %ld\n",get_write_packet_pool_sz())); |
845 |
|
|
846 |
|
LeaveCriticalSection( &wpool_csection ); |
847 |
|
|
854 |
|
|
855 |
|
thread_active_1 = true; |
856 |
|
|
857 |
< |
D(bug("ether_thread_write_packets start\r\n")); |
857 |
> |
D(bug("ether_thread_write_packets start\n")); |
858 |
|
|
859 |
|
while(thread_active) { |
860 |
|
// must be alertable, otherwise write completion is never called |
861 |
|
WaitForSingleObjectEx(int_send_now,INFINITE,TRUE); |
862 |
|
while( thread_active && (Packet = get_send_head()) != 0 ) { |
863 |
< |
if(m_router_enabled && router_write_packet((uint8 *)Packet->Buffer, Packet->Length)) { |
864 |
< |
Packet->bIoComplete = TRUE; |
865 |
< |
recycle_write_packet(Packet); |
866 |
< |
} else if(ether_fake) { |
863 |
> |
switch (net_if_type) { |
864 |
> |
case NET_IF_ROUTER: |
865 |
> |
if(router_write_packet((uint8 *)Packet->Buffer, Packet->Length)) { |
866 |
> |
Packet->bIoComplete = TRUE; |
867 |
> |
recycle_write_packet(Packet); |
868 |
> |
} |
869 |
> |
break; |
870 |
> |
case NET_IF_FAKE: |
871 |
|
Packet->bIoComplete = TRUE; |
872 |
|
recycle_write_packet(Packet); |
873 |
< |
} else if(!PacketSendPacket( fd, Packet, FALSE, TRUE )) { |
874 |
< |
// already recycled if async |
873 |
> |
break; |
874 |
> |
case NET_IF_B2ETHER: |
875 |
> |
if(!PacketSendPacket( fd, Packet, FALSE, TRUE )) { |
876 |
> |
// already recycled if async |
877 |
> |
} |
878 |
> |
break; |
879 |
|
} |
880 |
|
} |
881 |
|
} |
882 |
|
|
883 |
< |
D(bug("ether_thread_write_packets exit\r\n")); |
883 |
> |
D(bug("ether_thread_write_packets exit\n")); |
884 |
|
|
885 |
|
thread_active_1 = false; |
886 |
|
|
891 |
|
{ |
892 |
|
LPPACKET Packet; |
893 |
|
|
894 |
< |
D(bug("write_packet\r\n")); |
894 |
> |
D(bug("write_packet\n")); |
895 |
|
|
896 |
|
Packet = get_write_packet(len); |
897 |
|
if(Packet) { |
912 |
|
} |
913 |
|
} |
914 |
|
|
915 |
< |
int16 ether_write(uint32 wds) |
915 |
> |
static int16 ether_do_write(uint32 arg) |
916 |
|
{ |
917 |
< |
D(bug("ether_write\r\n")); |
734 |
< |
|
735 |
< |
// Set source address |
736 |
< |
uint32 hdr = ReadMacInt32(wds + 2); |
737 |
< |
memcpy(Mac2HostAddr(hdr + 6), ether_addr, 6); |
917 |
> |
D(bug("ether_write\n")); |
918 |
|
|
919 |
|
// Copy packet to buffer |
920 |
|
uint8 packet[1514], *p = packet; |
921 |
< |
int len = 0; |
742 |
< |
for (;;) { |
743 |
< |
uint16 w = (uint16)ReadMacInt16(wds); |
744 |
< |
if (w == 0) |
745 |
< |
break; |
746 |
< |
memcpy(p, Mac2HostAddr(ReadMacInt32(wds + 2)), w); |
747 |
< |
len += w; |
748 |
< |
p += w; |
749 |
< |
wds += 6; |
750 |
< |
} |
921 |
> |
int len = ether_arg_to_buffer(arg, p); |
922 |
|
|
923 |
|
if(len > 1514) { |
924 |
< |
D(bug("illegal packet length: %d\r\n",len)); |
924 |
> |
D(bug("illegal packet length: %d\n",len)); |
925 |
|
return eLenErr; |
926 |
|
} else { |
927 |
|
#if MONITOR |
932 |
|
|
933 |
|
// Transmit packet |
934 |
|
if (!write_packet(packet, len)) { |
935 |
< |
D(bug("WARNING: couldn't transmit packet\r\n")); |
935 |
> |
D(bug("WARNING: couldn't transmit packet\n")); |
936 |
|
return excessCollsns; |
937 |
|
} else { |
938 |
|
// It's up to the protocol drivers to do the error checking. Even if the |
966 |
|
{ |
967 |
|
EnterCriticalSection( &queue_csection ); |
968 |
|
if(queue[queue_inx].sz > 0) { |
969 |
< |
D(bug("ethernet queue full, packet dropped\r\n")); |
969 |
> |
D(bug("ethernet queue full, packet dropped\n")); |
970 |
|
} else { |
971 |
|
if(sz > 1514) sz = 1514; |
972 |
|
queue[queue_inx].sz = sz; |
1003 |
|
{ |
1004 |
|
EnterCriticalSection( &queue_csection ); |
1005 |
|
if( queue[queue_head].sz > 0 ) { |
1006 |
< |
D(bug(" packet received, triggering Ethernet interrupt\r\n")); |
1006 |
> |
D(bug(" packet received, triggering Ethernet interrupt\n")); |
1007 |
|
SetInterruptFlag(INTFLAG_ETHER); |
1008 |
|
TriggerInterrupt(); |
1009 |
|
// of course can't wait here. |
1052 |
|
if(count == pending_packet_sz[j] && |
1053 |
|
memcmp(pending_packet[j],lpPacket->Buffer,count) == 0) |
1054 |
|
{ |
1055 |
< |
D(bug("packet_read_completion discarding own packet.\r\n")); |
1055 |
> |
D(bug("packet_read_completion discarding own packet.\n")); |
1056 |
|
dwNumberOfBytesTransfered = 0; |
1057 |
|
|
1058 |
|
j = (j+1) & (~(MAX_ECHO-1)); |
1059 |
|
if(j != echo_count) { |
1060 |
< |
D(bug("Wow, this fix made some good after all...\r\n")); |
1060 |
> |
D(bug("Wow, this fix made some good after all...\n")); |
1061 |
|
} |
1062 |
|
|
1063 |
|
break; |
1064 |
|
} |
1065 |
|
} |
1066 |
|
if(dwNumberOfBytesTransfered) { |
1067 |
< |
if(!m_router_enabled || !router_read_packet((uint8 *)lpPacket->Buffer, dwNumberOfBytesTransfered)) { |
1067 |
> |
if(net_if_type != NET_IF_ROUTER || !router_read_packet((uint8 *)lpPacket->Buffer, dwNumberOfBytesTransfered)) { |
1068 |
|
enqueue_packet( (LPBYTE)lpPacket->Buffer, dwNumberOfBytesTransfered ); |
1069 |
|
} |
1070 |
|
} |
1108 |
|
for( int i=0; i<PACKET_POOL_COUNT; i++ ) { |
1109 |
|
packets[i] = PacketAllocatePacket(fd,1514); |
1110 |
|
if(!packets[i]) { |
1111 |
< |
D(bug("allocate_read_packets: out of memory\r\n")); |
1111 |
> |
D(bug("allocate_read_packets: out of memory\n")); |
1112 |
|
return(false); |
1113 |
|
} |
1114 |
|
} |
1129 |
|
|
1130 |
|
thread_active_2 = true; |
1131 |
|
|
1132 |
< |
D(bug("ether_thread_get_packets_nt start\r\n")); |
1132 |
> |
D(bug("ether_thread_get_packets_nt start\n")); |
1133 |
|
|
1134 |
|
// Wait for packets to arrive. |
1135 |
|
// Obey the golden rules; keep the reads pending. |
1136 |
|
while(thread_active) { |
1137 |
|
|
1138 |
< |
if(!ether_fake) { |
1139 |
< |
D(bug("Pending reads\r\n")); |
1138 |
> |
if(net_if_type == NET_IF_B2ETHER) { |
1139 |
> |
D(bug("Pending reads\n")); |
1140 |
|
for( i=0; thread_active && i<PACKET_POOL_COUNT; i++ ) { |
1141 |
|
if(packets[i]->free) { |
1142 |
|
packets[i]->free = FALSE; |
1143 |
|
if(PacketReceivePacket(fd,packets[i],FALSE)) { |
1144 |
|
if(packets[i]->bIoComplete) { |
1145 |
< |
D(bug("Early io completion...\r\n")); |
1145 |
> |
D(bug("Early io completion...\n")); |
1146 |
|
packet_read_completion( |
1147 |
|
ERROR_SUCCESS, |
1148 |
|
packets[i]->BytesReceived, |
1157 |
|
} |
1158 |
|
|
1159 |
|
if(thread_active && has_no_completed_io()) { |
1160 |
< |
D(bug("Waiting for int_sig2\r\n")); |
1160 |
> |
D(bug("Waiting for int_sig2\n")); |
1161 |
|
// "problem": awakens twice in a row. Fix if you increase the pool size. |
1162 |
|
WaitForSingleObjectEx(int_sig2,INFINITE,TRUE); |
1163 |
|
} |
1164 |
|
} |
1165 |
|
|
1166 |
< |
D(bug("ether_thread_get_packets_nt exit\r\n")); |
1166 |
> |
D(bug("ether_thread_get_packets_nt exit\n")); |
1167 |
|
|
1168 |
|
thread_active_2 = false; |
1169 |
|
|
1176 |
|
|
1177 |
|
thread_active_3 = true; |
1178 |
|
|
1179 |
< |
D(bug("ether_thread_feed_int start\r\n")); |
1179 |
> |
D(bug("ether_thread_feed_int start\n")); |
1180 |
|
|
1181 |
|
while(thread_active) { |
1182 |
< |
D(bug("Waiting for int_sig\r\n")); |
1182 |
> |
D(bug("Waiting for int_sig\n")); |
1183 |
|
WaitForSingleObject(int_sig,INFINITE); |
1184 |
|
// Looping this way to avoid a race condition. |
1185 |
< |
D(bug("Triggering\r\n")); |
1185 |
> |
D(bug("Triggering\n")); |
1186 |
|
looping = true; |
1187 |
|
while(thread_active && looping) { |
1188 |
|
trigger_queue(); |
1190 |
|
WaitForSingleObject(int_ack,INFINITE); |
1191 |
|
if(thread_active) looping = set_wait_request(); |
1192 |
|
} |
1193 |
< |
D(bug("Queue empty.\r\n")); |
1193 |
> |
D(bug("Queue empty.\n")); |
1194 |
|
} |
1195 |
|
|
1196 |
< |
D(bug("ether_thread_feed_int exit\r\n")); |
1196 |
> |
D(bug("ether_thread_feed_int exit\n")); |
1197 |
|
|
1198 |
|
thread_active_3 = false; |
1199 |
|
|
1205 |
|
* Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers |
1206 |
|
*/ |
1207 |
|
|
1208 |
< |
void EtherInterrupt(void) |
1208 |
> |
static void ether_do_interrupt(void) |
1209 |
|
{ |
1039 |
– |
int length; |
1040 |
– |
static uint8 packet[1514]; |
1041 |
– |
|
1042 |
– |
D(bug("EtherIRQ\r\n")); |
1043 |
– |
|
1210 |
|
// Call protocol handler for received packets |
1211 |
< |
while( (length = dequeue_packet(packet)) > 0 ) { |
1211 |
> |
EthernetPacket ether_packet; |
1212 |
> |
uint32 packet = ether_packet.addr(); |
1213 |
> |
ssize_t length; |
1214 |
> |
for (;;) { |
1215 |
|
|
1216 |
+ |
// Read packet from Ethernet device |
1217 |
+ |
length = dequeue_packet(Mac2HostAddr(packet)); |
1218 |
|
if (length < 14) |
1219 |
< |
continue; |
1219 |
> |
break; |
1220 |
|
|
1221 |
|
#if MONITOR |
1222 |
|
bug("Receiving Ethernet packet (%d bytes):\n",(int)length); |
1223 |
< |
dump_packet( packet, length ); |
1223 |
> |
dump_packet( Mac2HostAddr(packet), length ); |
1224 |
|
#endif |
1225 |
|
|
1226 |
< |
// Get packet type |
1227 |
< |
uint16 type = ntohs(*(uint16 *)(packet + 12)); |
1057 |
< |
|
1058 |
< |
// Look for protocol |
1059 |
< |
NetProtocol *prot = find_protocol(type); |
1060 |
< |
if (prot == NULL) |
1061 |
< |
continue; |
1062 |
< |
// break; |
1063 |
< |
|
1064 |
< |
// No default handler |
1065 |
< |
if (prot->handler == 0) |
1066 |
< |
continue; |
1067 |
< |
// break; |
1068 |
< |
|
1069 |
< |
// Copy header to RHA |
1070 |
< |
memcpy(Mac2HostAddr(ether_data + ed_RHA), packet, 14); |
1071 |
< |
D(bug(" header %08lx%04lx %08lx%04lx %04lx\r\n", ReadMacInt32(ether_data + ed_RHA), ReadMacInt16(ether_data + ed_RHA + 4), ReadMacInt32(ether_data + ed_RHA + 6), ReadMacInt16(ether_data + ed_RHA + 10), ReadMacInt16(ether_data + ed_RHA + 12))); |
1072 |
< |
|
1073 |
< |
// Call protocol handler |
1074 |
< |
M68kRegisters r; |
1075 |
< |
r.d[0] = type; // Packet type |
1076 |
< |
r.d[1] = length - 14; // Remaining packet length (without header, for ReadPacket) |
1077 |
< |
|
1078 |
< |
r.a[0] = (uint32)packet + 14; // Pointer to packet (host address, for ReadPacket) |
1079 |
< |
r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA |
1080 |
< |
r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines |
1081 |
< |
D(bug(" calling protocol handler %08lx, type %08lx, length %08lx, data %08lx, rha %08lx, read_packet %08lx\r\n", prot->handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4])); |
1082 |
< |
Execute68k(prot->handler, &r); |
1226 |
> |
// Dispatch packet |
1227 |
> |
ether_dispatch_packet(packet, length); |
1228 |
|
} |
1084 |
– |
|
1085 |
– |
// Acknowledge interrupt to reception thread |
1086 |
– |
D(bug(" EtherIRQ done\r\n")); |
1087 |
– |
ReleaseSemaphore(int_ack,1,NULL); |
1229 |
|
} |
1230 |
|
|
1231 |
|
#if DEBUG |