--- SheepShaver/src/ether.cpp 2004/12/19 09:01:04 1.6 +++ SheepShaver/src/ether.cpp 2008/01/01 09:47:38 1.10 @@ -1,7 +1,7 @@ /* * ether.cpp - SheepShaver Ethernet Device Driver (DLPI) * - * SheepShaver (C) 1997-2004 Marc Hellwig and Christian Bauer + * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,20 +27,14 @@ #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" #define DEBUG 0 #include "debug.h" -#if DIRECT_ADDRESSING -#warning "This code is not direct addressing clean" -#endif - // Packet types enum { kPktDIX = 0, @@ -183,7 +177,7 @@ typedef mblk_t *(*allocb_ptr)(size_t siz static uint32 allocb_tvect = 0; mblk_t *allocb(size_t arg1, int arg2) { - return (mblk_t *)Mac2HostAddr(CallMacOS2(allocb_ptr, allocb_tvect, arg1, arg2)); + return (mblk_t *)Mac2HostAddr((uint32)CallMacOS2(allocb_ptr, allocb_tvect, arg1, arg2)); } typedef void (*freeb_ptr)(mblk_t *); static uint32 freeb_tvect = 0; @@ -201,19 +195,19 @@ typedef mblk_t *(*copyb_ptr)(mblk_t *); static uint32 copyb_tvect = 0; static inline mblk_t *copyb(mblk_t *arg1) { - return (mblk_t *)Mac2HostAddr(CallMacOS1(copyb_ptr, copyb_tvect, arg1)); + return (mblk_t *)Mac2HostAddr((uint32)CallMacOS1(copyb_ptr, copyb_tvect, arg1)); } typedef mblk_t *(*dupmsg_ptr)(mblk_t *); static uint32 dupmsg_tvect = 0; static inline mblk_t *dupmsg(mblk_t *arg1) { - return (mblk_t *)Mac2HostAddr(CallMacOS1(dupmsg_ptr, dupmsg_tvect, arg1)); + return (mblk_t *)Mac2HostAddr((uint32)CallMacOS1(dupmsg_ptr, dupmsg_tvect, arg1)); } typedef mblk_t *(*getq_ptr)(queue_t *); static uint32 getq_tvect = 0; static inline mblk_t *getq(queue_t *arg1) { - return (mblk_t *)Mac2HostAddr(CallMacOS1(getq_ptr, getq_tvect, arg1)); + return (mblk_t *)Mac2HostAddr((uint32)CallMacOS1(getq_ptr, getq_tvect, arg1)); } typedef int (*putq_ptr)(queue_t *, mblk_t *); static uint32 putq_tvect = 0; @@ -285,9 +279,12 @@ typedef DLPIStream *(*mi_next_ptr_ptr)(D static uint32 mi_next_ptr_tvect = 0; static inline DLPIStream *mi_next_ptr(DLPIStream *arg1) { - return (DLPIStream *)Mac2HostAddr(CallMacOS1(mi_next_ptr_ptr, mi_next_ptr_tvect, arg1)); + return (DLPIStream *)Mac2HostAddr((uint32)CallMacOS1(mi_next_ptr_ptr, mi_next_ptr_tvect, arg1)); } - +#ifdef USE_ETHER_FULL_DRIVER +typedef void (*ether_dispatch_packet_ptr)(uint32 p, uint32 size); +static uint32 ether_dispatch_packet_tvect = 0; +#endif // Prototypes static void ether_ioctl(DLPIStream *the_stream, queue_t* q, mblk_t* mp); @@ -311,7 +308,7 @@ static void DLPI_unit_data(DLPIStream *t * Initialize ethernet stream module */ -uint8 InitStreamModule(void *theID) +static uint8 InitStreamModuleImpl(void *theID) { D(bug("InitStreamModule\n")); @@ -394,34 +391,73 @@ uint8 InitStreamModule(void *theID) if (mi_next_ptr_tvect == 0) return false; +#ifndef USE_ETHER_FULL_DRIVER // Initialize stream list (which might be leftover) dlpi_stream_list = NULL; // Ask add-on for ethernet hardware address - AO_get_ethernet_address(hardware_address); + AO_get_ethernet_address(Host2MacAddr(hardware_address)); +#endif // Yes, we're open ether_driver_opened = true; return true; } +uint8 InitStreamModule(void *theID) +{ + // Common initialization code + bool net_open = InitStreamModuleImpl(theID); + + // Call InitStreamModule() in native side +#ifdef BUILD_ETHER_FULL_DRIVER + extern bool NativeInitStreamModule(void *); + if (!NativeInitStreamModule((void *)ether_dispatch_packet)) + net_open = false; +#endif + + // Import functions from the Ethernet driver +#ifdef USE_ETHER_FULL_DRIVER + ether_dispatch_packet_tvect = (uintptr)theID; + D(bug("ether_dispatch_packet TVECT at %08lx\n", ether_dispatch_packet_tvect)); + if (ether_dispatch_packet_tvect == 0) + net_open = false; +#endif + + return net_open; +} + /* * Terminate ethernet stream module */ -void TerminateStreamModule(void) +static void TerminateStreamModuleImpl(void) { D(bug("TerminateStreamModule\n")); +#ifndef USE_ETHER_FULL_DRIVER // This happens sometimes. I don't know why. if (dlpi_stream_list != NULL) printf("FATAL: TerminateStreamModule() called, but streams still open\n"); +#endif // Sorry, we're closed ether_driver_opened = false; } +void TerminateStreamModule(void) +{ + // Common termination code + TerminateStreamModuleImpl(); + + // Call TerminateStreamModule() in native side +#ifdef BUILD_ETHER_FULL_DRIVER + extern void NativeTerminateStreamModule(void); + NativeTerminateStreamModule(); +#endif +} + /* * Open new stream @@ -479,7 +515,7 @@ int ether_close(queue_t *rdq, int flag, // 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 +965,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 +1137,29 @@ type_found: } } +void ether_dispatch_packet(uint32 p, uint32 size) +{ +#ifdef USE_ETHER_FULL_DRIVER + // Call handler from the Ethernet driver + D(bug("ether_dispatch_packet\n")); + D(bug(" packet data at %p, %d bytes\n", p, size)); + CallMacOS2(ether_dispatch_packet_ptr, ether_dispatch_packet_tvect, p, size); +#else + // 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++; + } +#endif +} + /* * Build and send an error acknowledge @@ -1542,7 +1601,7 @@ static void DLPI_enable_multi(DLPIStream } // 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 +1645,7 @@ static void DLPI_disable_multi(DLPIStrea 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 +1698,37 @@ static void DLPI_unit_data(DLPIStream *t 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