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 |
|
* |
58 |
|
unsigned int ether_tid; |
59 |
|
HANDLE ether_th1; |
60 |
|
HANDLE ether_th2; |
61 |
+ |
#ifdef SHEEPSHAVER |
62 |
+ |
static bool net_open = false; // Flag: initialization succeeded, network device open |
63 |
+ |
uint8 ether_addr[6]; // Our Ethernet address |
64 |
+ |
#endif |
65 |
|
|
66 |
|
|
67 |
|
// Need to fake a NIC if there is none but the router module is activated. |
70 |
|
// These are protected by queue_csection |
71 |
|
// Controls transfer for read thread to feed thread |
72 |
|
static CRITICAL_SECTION queue_csection; |
73 |
< |
typedef struct _queue_t { |
73 |
> |
typedef struct _win_queue_t { |
74 |
|
uint8 *buf; |
75 |
|
int sz; |
76 |
< |
} queue_t; |
76 |
> |
} win_queue_t; |
77 |
|
#define MAX_QUEUE_ITEMS 1024 |
78 |
< |
static queue_t queue[MAX_QUEUE_ITEMS]; |
78 |
> |
static win_queue_t queue[MAX_QUEUE_ITEMS]; |
79 |
|
static int queue_head = 0; |
80 |
|
static int queue_inx = 0; |
81 |
|
static bool wait_request = true; |
145 |
|
static bool allocate_read_packets(void); |
146 |
|
static void free_read_packets(void); |
147 |
|
static void free_write_packets(void); |
148 |
+ |
static int16 ether_do_add_multicast(uint8 *addr); |
149 |
+ |
static int16 ether_do_del_multicast(uint8 *addr); |
150 |
+ |
static int16 ether_do_write(uint32 arg); |
151 |
+ |
static void ether_do_interrupt(void); |
152 |
|
|
153 |
|
|
154 |
|
/* |
454 |
|
|
455 |
|
|
456 |
|
/* |
457 |
+ |
* Glue around low-level implementation |
458 |
+ |
*/ |
459 |
+ |
|
460 |
+ |
#ifdef SHEEPSHAVER |
461 |
+ |
// Error codes |
462 |
+ |
enum { |
463 |
+ |
eMultiErr = -91, |
464 |
+ |
eLenErr = -92, |
465 |
+ |
lapProtErr = -94, |
466 |
+ |
excessCollsns = -95 |
467 |
+ |
}; |
468 |
+ |
|
469 |
+ |
// Initialize ethernet |
470 |
+ |
void EtherInit(void) |
471 |
+ |
{ |
472 |
+ |
net_open = false; |
473 |
+ |
|
474 |
+ |
// Do nothing if the user disabled the network |
475 |
+ |
if (PrefsFindBool("nonet")) |
476 |
+ |
return; |
477 |
+ |
|
478 |
+ |
net_open = ether_init(); |
479 |
+ |
} |
480 |
+ |
|
481 |
+ |
// Exit ethernet |
482 |
+ |
void EtherExit(void) |
483 |
+ |
{ |
484 |
+ |
ether_exit(); |
485 |
+ |
net_open = false; |
486 |
+ |
} |
487 |
+ |
|
488 |
+ |
// Get ethernet hardware address |
489 |
+ |
void AO_get_ethernet_address(uint32 arg) |
490 |
+ |
{ |
491 |
+ |
uint8 *addr = Mac2HostAddr(arg); |
492 |
+ |
if (net_open) |
493 |
+ |
OTCopy48BitAddress(ether_addr, addr); |
494 |
+ |
else { |
495 |
+ |
addr[0] = 0x12; |
496 |
+ |
addr[1] = 0x34; |
497 |
+ |
addr[2] = 0x56; |
498 |
+ |
addr[3] = 0x78; |
499 |
+ |
addr[4] = 0x9a; |
500 |
+ |
addr[5] = 0xbc; |
501 |
+ |
} |
502 |
+ |
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])); |
503 |
+ |
} |
504 |
+ |
|
505 |
+ |
// Add multicast address |
506 |
+ |
void AO_enable_multicast(uint32 addr) |
507 |
+ |
{ |
508 |
+ |
if (net_open) |
509 |
+ |
ether_do_add_multicast(Mac2HostAddr(addr)); |
510 |
+ |
} |
511 |
+ |
|
512 |
+ |
// Disable multicast address |
513 |
+ |
void AO_disable_multicast(uint32 addr) |
514 |
+ |
{ |
515 |
+ |
if (net_open) |
516 |
+ |
ether_do_del_multicast(Mac2HostAddr(addr)); |
517 |
+ |
} |
518 |
+ |
|
519 |
+ |
// Transmit one packet |
520 |
+ |
void AO_transmit_packet(uint32 mp) |
521 |
+ |
{ |
522 |
+ |
if (net_open) { |
523 |
+ |
switch (ether_do_write(mp)) { |
524 |
+ |
case noErr: |
525 |
+ |
num_tx_packets++; |
526 |
+ |
break; |
527 |
+ |
case excessCollsns: |
528 |
+ |
num_tx_buffer_full++; |
529 |
+ |
break; |
530 |
+ |
} |
531 |
+ |
} |
532 |
+ |
} |
533 |
+ |
|
534 |
+ |
// Copy packet data from message block to linear buffer |
535 |
+ |
static inline int ether_arg_to_buffer(uint32 mp, uint8 *p) |
536 |
+ |
{ |
537 |
+ |
return ether_msgb_to_buffer(mp, p); |
538 |
+ |
} |
539 |
+ |
|
540 |
+ |
// Ethernet interrupt |
541 |
+ |
void EtherIRQ(void) |
542 |
+ |
{ |
543 |
+ |
D(bug("EtherIRQ\n")); |
544 |
+ |
num_ether_irq++; |
545 |
+ |
|
546 |
+ |
OTEnterInterrupt(); |
547 |
+ |
ether_do_interrupt(); |
548 |
+ |
OTLeaveInterrupt(); |
549 |
+ |
|
550 |
+ |
// Acknowledge interrupt to reception thread |
551 |
+ |
D(bug(" EtherIRQ done\r\n")); |
552 |
+ |
ReleaseSemaphore(int_ack,1,NULL); |
553 |
+ |
} |
554 |
+ |
#else |
555 |
+ |
// Add multicast address |
556 |
+ |
int16 ether_add_multicast(uint32 pb) |
557 |
+ |
{ |
558 |
+ |
return ether_do_add_multicast(Mac2HostAddr(pb + eMultiAddr)); |
559 |
+ |
} |
560 |
+ |
|
561 |
+ |
// Disable multicast address |
562 |
+ |
int16 ether_del_multicast(uint32 pb) |
563 |
+ |
{ |
564 |
+ |
return ether_do_del_multicast(Mac2HostAddr(pb + eMultiAddr)); |
565 |
+ |
} |
566 |
+ |
|
567 |
+ |
// Transmit one packet |
568 |
+ |
int16 ether_write(uint32 wds) |
569 |
+ |
{ |
570 |
+ |
return ether_do_write(wds); |
571 |
+ |
} |
572 |
+ |
|
573 |
+ |
// Copy packet data from WDS to linear buffer |
574 |
+ |
static inline int ether_arg_to_buffer(uint32 wds, uint8 *p) |
575 |
+ |
{ |
576 |
+ |
return ether_wds_to_buffer(wds, p); |
577 |
+ |
} |
578 |
+ |
|
579 |
+ |
// Dispatch packet to protocol handler |
580 |
+ |
static void ether_dispatch_packet(uint32 packet, uint32 length) |
581 |
+ |
{ |
582 |
+ |
// Get packet type |
583 |
+ |
uint16 type = ReadMacInt16(packet + 12); |
584 |
+ |
|
585 |
+ |
// Look for protocol |
586 |
+ |
NetProtocol *prot = find_protocol(type); |
587 |
+ |
if (prot == NULL) |
588 |
+ |
return; |
589 |
+ |
|
590 |
+ |
// No default handler |
591 |
+ |
if (prot->handler == 0) |
592 |
+ |
return; |
593 |
+ |
|
594 |
+ |
// Copy header to RHA |
595 |
+ |
Mac2Mac_memcpy(ether_data + ed_RHA, packet, 14); |
596 |
+ |
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))); |
597 |
+ |
|
598 |
+ |
// Call protocol handler |
599 |
+ |
M68kRegisters r; |
600 |
+ |
r.d[0] = type; // Packet type |
601 |
+ |
r.d[1] = length - 14; // Remaining packet length (without header, for ReadPacket) |
602 |
+ |
r.a[0] = packet + 14; // Pointer to packet (Mac address, for ReadPacket) |
603 |
+ |
r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA |
604 |
+ |
r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines |
605 |
+ |
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])); |
606 |
+ |
Execute68k(prot->handler, &r); |
607 |
+ |
} |
608 |
+ |
|
609 |
+ |
// Ethernet interrupt |
610 |
+ |
void EtherInterrupt(void) |
611 |
+ |
{ |
612 |
+ |
D(bug("EtherIRQ\n")); |
613 |
+ |
ether_do_interrupt(); |
614 |
+ |
|
615 |
+ |
// Acknowledge interrupt to reception thread |
616 |
+ |
D(bug(" EtherIRQ done\r\n")); |
617 |
+ |
ReleaseSemaphore(int_ack,1,NULL); |
618 |
+ |
} |
619 |
+ |
#endif |
620 |
+ |
|
621 |
+ |
|
622 |
+ |
/* |
623 |
|
* Reset |
624 |
|
*/ |
625 |
|
|
642 |
|
* Add multicast address |
643 |
|
*/ |
644 |
|
|
645 |
< |
int16 ether_add_multicast(uint32 pb) |
645 |
> |
static int16 ether_do_add_multicast(uint8 *addr) |
646 |
|
{ |
647 |
|
D(bug("ether_add_multicast\r\n")); |
648 |
|
|
649 |
|
// We wouldn't need to do this |
650 |
|
// if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr; |
651 |
|
|
652 |
< |
if (!ether_fake && !PacketAddMulticast( fd, Mac2HostAddr(pb + eMultiAddr))) { |
652 |
> |
if (!ether_fake && !PacketAddMulticast( fd, addr)) { |
653 |
|
D(bug("WARNING: couldn't enable multicast address\r\n")); |
654 |
|
return eMultiErr; |
655 |
|
} else { |
663 |
|
* Delete multicast address |
664 |
|
*/ |
665 |
|
|
666 |
< |
int16 ether_del_multicast(uint32 pb) |
666 |
> |
int16 ether_do_del_multicast(uint8 *addr) |
667 |
|
{ |
668 |
|
D(bug("ether_del_multicast\r\n")); |
669 |
|
|
670 |
|
// We wouldn't need to do this |
671 |
|
// if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr; |
672 |
|
|
673 |
< |
if (!ether_fake && !PacketDelMulticast( fd, Mac2HostAddr(pb + eMultiAddr))) { |
673 |
> |
if (!ether_fake && !PacketDelMulticast( fd, addr)) { |
674 |
|
D(bug("WARNING: couldn't disable multicast address\r\n")); |
675 |
|
return eMultiErr; |
676 |
|
} else |
743 |
|
if(length > 256) length = 256; |
744 |
|
|
745 |
|
for (int i=0; i<length; i++) { |
746 |
< |
sprintf(sm,"%02x", (int)packet[i]); |
746 |
> |
sprintf(sm," %02x", (int)packet[i]); |
747 |
|
strcat( buf, sm ); |
748 |
|
} |
749 |
|
strcat( buf, "\r\n" ); |
902 |
|
} |
903 |
|
} |
904 |
|
|
905 |
< |
int16 ether_write(uint32 wds) |
905 |
> |
static int16 ether_do_write(uint32 arg) |
906 |
|
{ |
907 |
|
D(bug("ether_write\r\n")); |
908 |
|
|
735 |
– |
// Set source address |
736 |
– |
uint32 hdr = ReadMacInt32(wds + 2); |
737 |
– |
memcpy(Mac2HostAddr(hdr + 6), ether_addr, 6); |
738 |
– |
|
909 |
|
// Copy packet to buffer |
910 |
|
uint8 packet[1514], *p = packet; |
911 |
< |
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 |
< |
} |
911 |
> |
int len = ether_arg_to_buffer(arg, p); |
912 |
|
|
913 |
|
if(len > 1514) { |
914 |
|
D(bug("illegal packet length: %d\r\n",len)); |
1195 |
|
* Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers |
1196 |
|
*/ |
1197 |
|
|
1198 |
< |
void EtherInterrupt(void) |
1198 |
> |
static void ether_do_interrupt(void) |
1199 |
|
{ |
1039 |
– |
int length; |
1040 |
– |
static uint8 packet[1514]; |
1041 |
– |
|
1042 |
– |
D(bug("EtherIRQ\r\n")); |
1043 |
– |
|
1200 |
|
// Call protocol handler for received packets |
1201 |
< |
while( (length = dequeue_packet(packet)) > 0 ) { |
1201 |
> |
EthernetPacket ether_packet; |
1202 |
> |
uint32 packet = ether_packet.addr(); |
1203 |
> |
ssize_t length; |
1204 |
> |
for (;;) { |
1205 |
|
|
1206 |
+ |
// Read packet from Ethernet device |
1207 |
+ |
length = dequeue_packet(Mac2HostAddr(packet)); |
1208 |
|
if (length < 14) |
1209 |
< |
continue; |
1209 |
> |
break; |
1210 |
|
|
1211 |
|
#if MONITOR |
1212 |
|
bug("Receiving Ethernet packet (%d bytes):\n",(int)length); |
1213 |
< |
dump_packet( packet, length ); |
1213 |
> |
dump_packet( Mac2HostAddr(packet), length ); |
1214 |
|
#endif |
1215 |
|
|
1216 |
< |
// Get packet type |
1217 |
< |
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); |
1216 |
> |
// Dispatch packet |
1217 |
> |
ether_dispatch_packet(packet, length); |
1218 |
|
} |
1084 |
– |
|
1085 |
– |
// Acknowledge interrupt to reception thread |
1086 |
– |
D(bug(" EtherIRQ done\r\n")); |
1087 |
– |
ReleaseSemaphore(int_ack,1,NULL); |
1219 |
|
} |
1220 |
|
|
1221 |
|
#if DEBUG |