mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-11-26 10:49:21 +00:00
Make ethernet really work on 64-bit platforms, especially x86-64
This commit is contained in:
parent
9383e5bd50
commit
143b18c752
@ -461,17 +461,18 @@ void ether_stop_udp_thread(void)
|
||||
void EtherInterrupt(void)
|
||||
{
|
||||
D(bug("EtherIRQ\n"));
|
||||
EthernetPacket ether_packet;
|
||||
uint32 packet = ether_packet.addr();
|
||||
|
||||
if (udp_tunnel) {
|
||||
|
||||
uint8 packet[1514];
|
||||
ssize_t length;
|
||||
|
||||
// Read packets from socket and hand to ether_udp_read() for processing
|
||||
while (true) {
|
||||
struct sockaddr_in from;
|
||||
socklen_t from_len = sizeof(from);
|
||||
length = recvfrom(fd, packet, 1514, 0, (struct sockaddr *)&from, &from_len);
|
||||
length = recvfrom(fd, Mac2HostAddr(packet), 1514, 0, (struct sockaddr *)&from, &from_len);
|
||||
if (length < 14)
|
||||
break;
|
||||
ether_udp_read(packet, length, &from);
|
||||
@ -483,15 +484,16 @@ void EtherInterrupt(void)
|
||||
net_packet *p = &net_buffer_ptr->read[rd_pos];
|
||||
while (p->cmd & IN_USE) {
|
||||
if ((p->cmd >> 8) == SHEEP_PACKET) {
|
||||
Host2Mac_memcpy(packet, p->data, p->length);
|
||||
#if MONITOR
|
||||
bug("Receiving Ethernet packet:\n");
|
||||
for (int i=0; i<p->length; i++) {
|
||||
bug("%02x ", p->data[i]);
|
||||
bug("%02x ", ReadMacInt8(packet + i));
|
||||
}
|
||||
bug("\n");
|
||||
#endif
|
||||
// Get packet type
|
||||
uint16 type = ntohs(*(uint16 *)(p->data + 12));
|
||||
uint16 type = ReadMacInt16(packet + 12);
|
||||
|
||||
// Look for protocol
|
||||
NetProtocol *prot = find_protocol(type);
|
||||
@ -503,14 +505,14 @@ void EtherInterrupt(void)
|
||||
goto next;
|
||||
|
||||
// Copy header to RHA
|
||||
Host2Mac_memcpy(ether_data + ed_RHA, p->data, 14);
|
||||
Mac2Mac_memcpy(ether_data + ed_RHA, packet, 14);
|
||||
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)));
|
||||
|
||||
// Call protocol handler
|
||||
M68kRegisters r;
|
||||
r.d[0] = type; // Packet type
|
||||
r.d[1] = p->length - 14; // Remaining packet length (without header, for ReadPacket)
|
||||
r.a[0] = (uint32)p->data + 14; // Pointer to packet (host address, for ReadPacket)
|
||||
r.a[0] = packet + 14; // Pointer to packet (Mac address, for ReadPacket)
|
||||
r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA
|
||||
r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines
|
||||
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]));
|
||||
|
@ -466,8 +466,8 @@ void EtherInterrupt(void)
|
||||
D(bug("EtherIRQ\n"));
|
||||
|
||||
// Call protocol handler for received packets
|
||||
// NOTE: "static" so that packet[] has a 32-bit address (.data section, not stack)
|
||||
static uint8 packet[1516];
|
||||
EthernetPacket ether_packet;
|
||||
uint32 packet = ether_packet.addr();
|
||||
ssize_t length;
|
||||
for (;;) {
|
||||
|
||||
@ -476,7 +476,7 @@ void EtherInterrupt(void)
|
||||
// Read packet from socket
|
||||
struct sockaddr_in from;
|
||||
socklen_t from_len = sizeof(from);
|
||||
length = recvfrom(fd, packet, 1514, 0, (struct sockaddr *)&from, &from_len);
|
||||
length = recvfrom(fd, Mac2HostAddr(packet), 1514, 0, (struct sockaddr *)&from, &from_len);
|
||||
if (length < 14)
|
||||
break;
|
||||
ether_udp_read(packet, length, &from);
|
||||
@ -485,9 +485,9 @@ void EtherInterrupt(void)
|
||||
|
||||
// Read packet from sheep_net device
|
||||
#if defined(__linux__)
|
||||
length = read(fd, packet, net_if_type == NET_IF_ETHERTAP ? 1516 : 1514);
|
||||
length = read(fd, Mac2HostAddr(packet), net_if_type == NET_IF_ETHERTAP ? 1516 : 1514);
|
||||
#else
|
||||
length = read(fd, packet, 1514);
|
||||
length = read(fd, Mac2HostAddr(packet), 1514);
|
||||
#endif
|
||||
if (length < 14)
|
||||
break;
|
||||
@ -495,13 +495,13 @@ void EtherInterrupt(void)
|
||||
#if MONITOR
|
||||
bug("Receiving Ethernet packet:\n");
|
||||
for (int i=0; i<length; i++) {
|
||||
bug("%02x ", packet[i]);
|
||||
bug("%02x ", ReadMacInt8(packet + i));
|
||||
}
|
||||
bug("\n");
|
||||
#endif
|
||||
|
||||
// Pointer to packet data (Ethernet header)
|
||||
uint8 *p = packet;
|
||||
uint32 p = packet;
|
||||
#if defined(__linux__)
|
||||
if (net_if_type == NET_IF_ETHERTAP) {
|
||||
p += 2; // Linux ethertap has two random bytes before the packet
|
||||
@ -510,7 +510,7 @@ void EtherInterrupt(void)
|
||||
#endif
|
||||
|
||||
// Get packet type
|
||||
uint16 type = (p[12] << 8) | p[13];
|
||||
uint16 type = ReadMacInt16(p + 12);
|
||||
|
||||
// Look for protocol
|
||||
uint16 search_type = (type <= 1500 ? 0 : type);
|
||||
@ -523,14 +523,14 @@ void EtherInterrupt(void)
|
||||
continue;
|
||||
|
||||
// Copy header to RHA
|
||||
Host2Mac_memcpy(ether_data + ed_RHA, p, 14);
|
||||
Mac2Mac_memcpy(ether_data + ed_RHA, p, 14);
|
||||
D(bug(" header %08x%04x %08x%04x %04x\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)));
|
||||
|
||||
// Call protocol handler
|
||||
M68kRegisters r;
|
||||
r.d[0] = type; // Packet type
|
||||
r.d[1] = length - 14; // Remaining packet length (without header, for ReadPacket)
|
||||
r.a[0] = (uint32)p + 14; // Pointer to packet (host address, for ReadPacket)
|
||||
r.a[0] = p + 14; // Pointer to packet (Mac address, for ReadPacket)
|
||||
r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA
|
||||
r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines
|
||||
D(bug(" calling protocol handler %08x, type %08x, length %08x, data %08x, rha %08x, read_packet %08x\n", handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4]));
|
||||
|
@ -1037,23 +1037,24 @@ static unsigned int ether_thread_feed_int(void *arg)
|
||||
void EtherInterrupt(void)
|
||||
{
|
||||
int length;
|
||||
static uint8 packet[1514];
|
||||
EthernetPacket ether_packet;
|
||||
uint32 packet = ether_packet.addr();
|
||||
|
||||
D(bug("EtherIRQ\r\n"));
|
||||
|
||||
// Call protocol handler for received packets
|
||||
while( (length = dequeue_packet(packet)) > 0 ) {
|
||||
while( (length = dequeue_packet(Mac2HostAddr(packet))) > 0 ) {
|
||||
|
||||
if (length < 14)
|
||||
continue;
|
||||
|
||||
#if MONITOR
|
||||
bug("Receiving Ethernet packet (%d bytes):\n",(int)length);
|
||||
dump_packet( packet, length );
|
||||
dump_packet( Mac2HostAddr(packet), length );
|
||||
#endif
|
||||
|
||||
// Get packet type
|
||||
uint16 type = ntohs(*(uint16 *)(packet + 12));
|
||||
uint16 type = ReadMacInt16(packet + 12);
|
||||
|
||||
// Look for protocol
|
||||
NetProtocol *prot = find_protocol(type);
|
||||
@ -1067,7 +1068,7 @@ void EtherInterrupt(void)
|
||||
// break;
|
||||
|
||||
// Copy header to RHA
|
||||
memcpy(Mac2HostAddr(ether_data + ed_RHA), packet, 14);
|
||||
Mac2Mac_memcpy(ether_data + ed_RHA, packet, 14);
|
||||
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)));
|
||||
|
||||
// Call protocol handler
|
||||
@ -1075,7 +1076,7 @@ void EtherInterrupt(void)
|
||||
r.d[0] = type; // Packet type
|
||||
r.d[1] = length - 14; // Remaining packet length (without header, for ReadPacket)
|
||||
|
||||
r.a[0] = (uint32)packet + 14; // Pointer to packet (host address, for ReadPacket)
|
||||
r.a[0] = packet + 14; // Pointer to packet (Mac address, for ReadPacket)
|
||||
r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA
|
||||
r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines
|
||||
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]));
|
||||
|
@ -353,7 +353,7 @@ void EmulOp(uint16 opcode, M68kRegisters *r)
|
||||
break;
|
||||
|
||||
case M68K_EMUL_OP_ETHER_READ_PACKET:
|
||||
EtherReadPacket((uint8 **)&r->a[0], r->a[3], r->d[3], r->d[1]);
|
||||
EtherReadPacket(r->a[0], r->a[3], r->d[3], r->d[1]);
|
||||
break;
|
||||
|
||||
case M68K_EMUL_OP_SOUNDIN_OPEN: // Sound input driver functions
|
||||
|
@ -390,12 +390,12 @@ int16 EtherControl(uint32 pb, uint32 dce)
|
||||
* Ethernet ReadPacket routine
|
||||
*/
|
||||
|
||||
void EtherReadPacket(uint8 **src, uint32 &dest, uint32 &len, uint32 &remaining)
|
||||
void EtherReadPacket(uint32 &src, uint32 &dest, uint32 &len, uint32 &remaining)
|
||||
{
|
||||
D(bug("EtherReadPacket src %p, dest %08x, len %08x, remaining %08x\n", *src, dest, len, remaining));
|
||||
D(bug("EtherReadPacket src %08x, dest %08x, len %08x, remaining %08x\n", src, dest, len, remaining));
|
||||
uint32 todo = len > remaining ? remaining : len;
|
||||
Host2Mac_memcpy(dest, *src, todo);
|
||||
*src += todo;
|
||||
Mac2Mac_memcpy(dest, src, todo);
|
||||
src += todo;
|
||||
dest += todo;
|
||||
len -= todo;
|
||||
remaining -= todo;
|
||||
@ -407,22 +407,22 @@ void EtherReadPacket(uint8 **src, uint32 &dest, uint32 &len, uint32 &remaining)
|
||||
* Read packet from UDP socket
|
||||
*/
|
||||
|
||||
void ether_udp_read(uint8 *packet, int length, struct sockaddr_in *from)
|
||||
void ether_udp_read(uint32 packet, int length, struct sockaddr_in *from)
|
||||
{
|
||||
// Drop packets sent by us
|
||||
if (memcmp(packet + 6, ether_addr, 6) == 0)
|
||||
if (memcmp(Mac2HostAddr(packet) + 6, ether_addr, 6) == 0)
|
||||
return;
|
||||
|
||||
#if MONITOR
|
||||
bug("Receiving Ethernet packet:\n");
|
||||
for (int i=0; i<length; i++) {
|
||||
bug("%02x ", packet[i]);
|
||||
bug("%02x ", ReadMacInt8(packet + i));
|
||||
}
|
||||
bug("\n");
|
||||
#endif
|
||||
|
||||
// Get packet type
|
||||
uint16 type = (packet[12] << 8) | packet[13];
|
||||
uint16 type = ReadMacInt16(packet + 12);
|
||||
|
||||
// Look for protocol
|
||||
uint16 search_type = (type <= 1500 ? 0 : type);
|
||||
@ -433,17 +433,56 @@ void ether_udp_read(uint8 *packet, int length, struct sockaddr_in *from)
|
||||
return;
|
||||
|
||||
// Copy header to RHA
|
||||
Host2Mac_memcpy(ether_data + ed_RHA, packet, 14);
|
||||
Mac2Mac_memcpy(ether_data + ed_RHA, packet, 14);
|
||||
D(bug(" header %08x%04x %08x%04x %04x\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)));
|
||||
|
||||
// Call protocol handler
|
||||
M68kRegisters r;
|
||||
r.d[0] = type; // Packet type
|
||||
r.d[1] = length - 14; // Remaining packet length (without header, for ReadPacket)
|
||||
r.a[0] = (uint32)packet + 14; // Pointer to packet (host address, for ReadPacket)
|
||||
r.a[0] = packet + 14; // Pointer to packet (Mac address, for ReadPacket)
|
||||
r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA
|
||||
r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines
|
||||
D(bug(" calling protocol handler %08x, type %08x, length %08x, data %08x, rha %08x, read_packet %08x\n", handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4]));
|
||||
Execute68k(handler, &r);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* 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 {
|
||||
M68kRegisters r;
|
||||
r.d[0] = 1516;
|
||||
Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
|
||||
assert(r.a[0] != 0);
|
||||
packet = r.a[0];
|
||||
if (ether_packet == 0)
|
||||
ether_packet = packet;
|
||||
}
|
||||
}
|
||||
|
||||
EthernetPacket::~EthernetPacket()
|
||||
{
|
||||
--n_ether_packets;
|
||||
if (packet != ether_packet) {
|
||||
M68kRegisters r;
|
||||
r.a[0] = packet;
|
||||
Execute68kTrap(0xa01f, &r); // DisposePtr
|
||||
}
|
||||
if (n_ether_packets > 0) {
|
||||
bug("WARNING: Nested allocation of ethernet packets!\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -28,7 +28,7 @@ extern void EtherExit(void);
|
||||
|
||||
extern int16 EtherOpen(uint32 pb, uint32 dce);
|
||||
extern int16 EtherControl(uint32 pb, uint32 dce);
|
||||
extern void EtherReadPacket(uint8 **src, uint32 &dest, uint32 &len, uint32 &remaining);
|
||||
extern void EtherReadPacket(uint32 &src, uint32 &dest, uint32 &len, uint32 &remaining);
|
||||
|
||||
// System specific and internal functions/data
|
||||
extern void EtherReset(void);
|
||||
@ -44,7 +44,7 @@ extern int16 ether_detach_ph(uint16 type);
|
||||
extern int16 ether_write(uint32 wds);
|
||||
extern bool ether_start_udp_thread(int socket_fd);
|
||||
extern void ether_stop_udp_thread(void);
|
||||
extern void ether_udp_read(uint8 *packet, int length, struct sockaddr_in *from);
|
||||
extern void ether_udp_read(uint32 packet, int length, struct sockaddr_in *from);
|
||||
|
||||
extern uint8 ether_addr[6]; // Ethernet address (set by ether_init())
|
||||
|
||||
@ -61,6 +61,21 @@ enum {
|
||||
|
||||
extern uint32 ether_data; // Mac address of driver data in MacOS RAM
|
||||
|
||||
// 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 WDS to linear buffer (must hold at least 1514 bytes),
|
||||
// returns packet length
|
||||
static inline int ether_wds_to_buffer(uint32 wds, uint8 *p)
|
||||
|
Loading…
Reference in New Issue
Block a user