diff --git a/SheepShaver/src/BeOS/ether_beos.cpp b/SheepShaver/src/BeOS/ether_beos.cpp index a326e1fd..35a9a5ed 100644 --- a/SheepShaver/src/BeOS/ether_beos.cpp +++ b/SheepShaver/src/BeOS/ether_beos.cpp @@ -226,8 +226,9 @@ void EtherExit(void) * Ask add-on for ethernet hardware address */ -void AO_get_ethernet_address(uint8 *addr) +void AO_get_ethernet_address(uint32 arg) { + uint8 *addr = Mac2HostAddr(arg); if (net_open) { OTCopy48BitAddress(net_buffer_ptr->ether_addr, addr); } else { @@ -246,7 +247,7 @@ void AO_get_ethernet_address(uint8 *addr) * Tell add-on to enable multicast address */ -void AO_enable_multicast(uint8 *addr) +void AO_enable_multicast(uint32 addr) { D(bug("AO_enable_multicast\n")); if (net_open) { @@ -254,7 +255,7 @@ void AO_enable_multicast(uint8 *addr) if (p->cmd & IN_USE) { D(bug("WARNING: couldn't enable multicast address\n")); } else { - memcpy(p->data, addr, 6); + Mac2host_memcpy(p->data, addr, 6); p->length = 6; p->cmd = IN_USE | (ADD_MULTICAST << 8); wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT; @@ -268,7 +269,7 @@ void AO_enable_multicast(uint8 *addr) * Tell add-on to disable multicast address */ -void AO_disable_multicast(uint8 *addr) +void AO_disable_multicast(uint32 addr) { D(bug("AO_disable_multicast\n")); if (net_open) { @@ -276,7 +277,7 @@ void AO_disable_multicast(uint8 *addr) if (p->cmd & IN_USE) { D(bug("WARNING: couldn't enable multicast address\n")); } else { - memcpy(p->data, addr, 6); + Mac2host_memcpy(p->data, addr, 6); p->length = 6; p->cmd = IN_USE | (REMOVE_MULTICAST << 8); wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT; @@ -291,7 +292,7 @@ void AO_disable_multicast(uint8 *addr) * Tell add-on to transmit one packet */ -void AO_transmit_packet(mblk_t *mp) +void AO_transmit_packet(uint32 mp_arg) { D(bug("AO_transmit_packet\n")); if (net_open) { @@ -306,6 +307,7 @@ void AO_transmit_packet(mblk_t *mp) // Copy packet to buffer uint8 *start; uint8 *bp = start = p->data; + mblk_t *mp = Mac2HostAddr(mp_arg); while (mp) { uint32 size = mp->b_wptr - mp->b_rptr; memcpy(bp, mp->b_rptr, size); diff --git a/SheepShaver/src/ether.cpp b/SheepShaver/src/ether.cpp index 629cbed3..8998161f 100644 --- a/SheepShaver/src/ether.cpp +++ b/SheepShaver/src/ether.cpp @@ -27,10 +27,10 @@ #include #include "sysdeps.h" +#include "cpu_emulation.h" #include "ether.h" #include "ether_defs.h" #include "macos_util.h" -#include "cpu_emulation.h" #include "emul_op.h" #include "main.h" @@ -398,7 +398,7 @@ uint8 InitStreamModule(void *theID) dlpi_stream_list = NULL; // Ask add-on for ethernet hardware address - AO_get_ethernet_address(hardware_address); + AO_get_ethernet_address(Host2MacAddr(hardware_address)); // Yes, we're open ether_driver_opened = true; @@ -479,7 +479,7 @@ int ether_close(queue_t *rdq, int flag, void *creds) // Disable all registered multicast addresses while (the_stream->multicast_list) { - AO_disable_multicast(the_stream->multicast_list->addr); + AO_disable_multicast(Host2MacAddr(the_stream->multicast_list->addr)); the_stream->RemoveMulticast(the_stream->multicast_list->addr); } the_stream->multicast_list = NULL; @@ -929,7 +929,7 @@ static void transmit_packet(mblk_t *mp) OTCopy48BitAddress(hardware_address, enetHeader->fSourceAddr); // Tell add-on to transmit packet - AO_transmit_packet(mp); + AO_transmit_packet(Host2MacAddr((uint8 *)mp)); freemsg(mp); } @@ -1101,6 +1101,22 @@ type_found: } } +void ether_dispatch_packet(uint32 p, uint32 size) +{ + // Wrap packet in message block + num_rx_packets++; + mblk_t *mp; + if ((mp = allocb(size, 0)) != NULL) { + D(bug(" packet data at %p\n", (void *)mp->b_rptr)); + Mac2Host_memcpy(mp->b_rptr, p, size); + mp->b_wptr += size; + ether_packet_received(mp); + } else { + D(bug("WARNING: Cannot allocate mblk for received packet\n")); + num_rx_no_mem++; + } +} + /* * Build and send an error acknowledge @@ -1542,7 +1558,7 @@ static void DLPI_enable_multi(DLPIStream *the_stream, queue_t *q, mblk_t *mp) } // Tell add-on to enable multicast address - AO_enable_multicast(reqaddr); + AO_enable_multicast(Host2MacAddr((uint8 *)reqaddr)); // Add new address to multicast list uint8 *addr = Mac2HostAddr(Mac_sysalloc(kEnetPhysicalAddressLength)); @@ -1586,7 +1602,7 @@ static void DLPI_disable_multi(DLPIStream *the_stream, queue_t *q, mblk_t *mp) Mac_sysfree(Host2MacAddr(addr)); // Tell add-on to disable multicast address - AO_disable_multicast(reqaddr); + AO_disable_multicast(Host2MacAddr((uint8 *)reqaddr)); // No longer check multicast packets if no multicast addresses are registered if (the_stream->multicast_list == NULL) @@ -1639,3 +1655,37 @@ static void DLPI_unit_data(DLPIStream *the_stream, queue_t *q, mblk_t *mp) if ((mp = build_tx_packet_header(the_stream, mp, false)) != NULL) transmit_packet(mp); } + + +/* + * Ethernet packet allocator + */ + +#if SIZEOF_VOID_P != 4 || REAL_ADDRESSING == 0 +static uint32 ether_packet = 0; // Ethernet packet (cached allocation) +static uint32 n_ether_packets = 0; // Number of ethernet packets allocated so far (should be at most 1) + +EthernetPacket::EthernetPacket() +{ + ++n_ether_packets; + if (ether_packet && n_ether_packets == 1) + packet = ether_packet; + else { + packet = Mac_sysalloc(1516); + assert(packet != 0); + Mac_memset(packet, 0, 1516); + if (ether_packet == 0) + ether_packet = packet; + } +} + +EthernetPacket::~EthernetPacket() +{ + --n_ether_packets; + if (packet != ether_packet) + Mac_sysfree(packet); + if (n_ether_packets > 0) { + bug("WARNING: Nested allocation of ethernet packets!\n"); + } +} +#endif diff --git a/SheepShaver/src/include/ether.h b/SheepShaver/src/include/ether.h index 2a8769c7..04ef2b9e 100644 --- a/SheepShaver/src/include/ether.h +++ b/SheepShaver/src/include/ether.h @@ -39,19 +39,50 @@ extern void EtherExit(void); extern void EtherIRQ(void); -extern void AO_get_ethernet_address(uint8 *addr); -extern void AO_enable_multicast(uint8 *addr); -extern void AO_disable_multicast(uint8 *addr); -extern void AO_transmit_packet(mblk_t *mp); +extern void AO_get_ethernet_address(uint32 addr); +extern void AO_enable_multicast(uint32 addr); +extern void AO_disable_multicast(uint32 addr); +extern void AO_transmit_packet(uint32 mp); extern mblk_t *allocb(size_t size, int pri); extern void OTEnterInterrupt(void); extern void OTLeaveInterrupt(void); +extern void ether_dispatch_packet(uint32 p, uint32 length); extern void ether_packet_received(mblk_t *mp); extern bool ether_driver_opened; +// Ethernet packet allocator (optimized for 32-bit platforms in real addressing mode) +class EthernetPacket { +#if SIZEOF_VOID_P == 4 && REAL_ADDRESSING + uint8 packet[1516]; + public: + uint32 addr(void) const { return (uint32)packet; } +#else + uint32 packet; + public: + EthernetPacket(); + ~EthernetPacket(); + uint32 addr(void) const { return packet; } +#endif +}; + +// Copy packet data from message block to linear buffer (must hold at +// least 1514 bytes), returns packet length +static inline int ether_msgb_to_buffer(uint32 mp, uint8 *p) +{ + int len = 0; + while (mp) { + uint32 size = ReadMacInt32(mp + 16) - ReadMacInt32(mp + 12); + Mac2Host_memcpy(p, ReadMacInt32(mp + 12), size); + len += size; + p += size; + mp = ReadMacInt32(mp + 8); + } + return len; +} + extern int32 num_wput; extern int32 num_error_acks; extern int32 num_tx_packets;