Make ethernet really work on 64-bit platforms, especially x86-64

This commit is contained in:
gbeauche 2005-03-19 17:43:03 +00:00
parent 9383e5bd50
commit 143b18c752
6 changed files with 92 additions and 35 deletions

View File

@ -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]));

View File

@ -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]));

View File

@ -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]));

View File

@ -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

View File

@ -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

View File

@ -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)