--- BasiliskII/src/Windows/ether_windows.cpp 2004/12/06 23:31:03 1.1 +++ BasiliskII/src/Windows/ether_windows.cpp 2006/04/23 15:36:51 1.5 @@ -1,7 +1,7 @@ /* * ether_windows.cpp - Ethernet device driver * - * Basilisk II (C) 1997-2004 Christian Bauer + * Basilisk II (C) 1997-2005 Christian Bauer * * Windows platform specific code copyright (C) Lauri Pesonen * @@ -49,6 +49,13 @@ #include "debug.h" +// Ethernet device types +enum { + NET_IF_B2ETHER, + NET_IF_ROUTER, + NET_IF_FAKE, +}; + // Options bool ether_use_permanent = true; static int16 ether_multi_mode = ETHER_MULTICAST_MAC; @@ -58,20 +65,21 @@ HANDLE ether_th; unsigned int ether_tid; HANDLE ether_th1; HANDLE ether_th2; - - -// Need to fake a NIC if there is none but the router module is activated. -bool ether_fake = false; +static int net_if_type = -1; // Ethernet device type +#ifdef SHEEPSHAVER +static bool net_open = false; // Flag: initialization succeeded, network device open +uint8 ether_addr[6]; // Our Ethernet address +#endif // These are protected by queue_csection // Controls transfer for read thread to feed thread static CRITICAL_SECTION queue_csection; -typedef struct _queue_t { +typedef struct _win_queue_t { uint8 *buf; int sz; -} queue_t; +} win_queue_t; #define MAX_QUEUE_ITEMS 1024 -static queue_t queue[MAX_QUEUE_ITEMS]; +static win_queue_t queue[MAX_QUEUE_ITEMS]; static int queue_head = 0; static int queue_inx = 0; static bool wait_request = true; @@ -129,9 +137,6 @@ static HANDLE int_sig = 0; static HANDLE int_sig2 = 0; static HANDLE int_send_now = 0; -static char edevice[512]; - - // Prototypes static WINAPI unsigned int ether_thread_feed_int(void *arg); static WINAPI unsigned int ether_thread_get_packets_nt(void *arg); @@ -141,6 +146,10 @@ static void final_queue(void); static bool allocate_read_packets(void); static void free_read_packets(void); static void free_write_packets(void); +static int16 ether_do_add_multicast(uint8 *addr); +static int16 ether_do_del_multicast(uint8 *addr); +static int16 ether_do_write(uint32 arg); +static void ether_do_interrupt(void); /* @@ -173,47 +182,54 @@ bool ether_init(void) { char str[256]; - // Initialize NAT-Router - router_init(); - // Do nothing if no Ethernet device specified const char *name = PrefsFindString("ether"); - if (name) - strcpy(edevice, name); + if (name == NULL) + return false; - bool there_is_a_router = PrefsFindBool("routerenabled"); + ether_multi_mode = PrefsFindInt32("ethermulticastmode"); + ether_use_permanent = PrefsFindBool("etherpermanentaddress"); - if (!name || !*name) { - if( there_is_a_router ) { - strcpy( edevice, "None" ); - ether_fake = true; - } else { - return false; - } - } + // Determine Ethernet device type + net_if_type = -1; + if (strcmp(name, "router") == 0) + net_if_type = NET_IF_ROUTER; + else + net_if_type = NET_IF_B2ETHER; - ether_use_permanent = PrefsFindBool("etherpermanentaddress"); - ether_multi_mode = PrefsFindInt32("ethermulticastmode"); + // Initialize NAT-Router + if (net_if_type == NET_IF_ROUTER) { + if (!router_init()) + net_if_type = NET_IF_FAKE; + } // Open ethernet device - if(ether_fake) { - memcpy( ether_addr, router_mac_addr, 6 ); - D(bug("Fake ethernet address (same as router) %02x %02x %02x %02x %02x %02x\r\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); - } else { - fd = PacketOpenAdapter( name, ether_multi_mode ); + const char *dev_name; + switch (net_if_type) { + case NET_IF_B2ETHER: + dev_name = PrefsFindString("etherguid"); + break; + } + if (net_if_type == NET_IF_B2ETHER) { + if (dev_name == NULL) { + WarningAlert("No ethernet device GUID specified. Ethernet is not available."); + goto open_error; + } + + fd = PacketOpenAdapter( dev_name, ether_multi_mode ); if (!fd) { - sprintf(str, "Could not open ethernet adapter %s.", name); + sprintf(str, "Could not open ethernet adapter %s.", dev_name); WarningAlert(str); goto open_error; } // Get Ethernet address if(!PacketGetMAC(fd,ether_addr,ether_use_permanent)) { - sprintf(str, "Could not get hardware address of device %s. Ethernet is not available.", name); + sprintf(str, "Could not get hardware address of device %s. Ethernet is not available.", dev_name); WarningAlert(str); goto open_error; } - D(bug("Real ethernet address %02x %02x %02x %02x %02x %02x\r\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); + D(bug("Real ethernet address %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); const char *ether_fake_address; ether_fake_address = PrefsFindString("etherfakeaddress"); @@ -225,9 +241,13 @@ bool ether_init(void) sm[3] = ether_fake_address[i*2+1]; ether_addr[i] = (uint8)strtoul(sm,0,0); } - D(bug("Fake ethernet address %02x %02x %02x %02x %02x %02x\r\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); + D(bug("Fake ethernet address %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); } } + else { + memcpy( ether_addr, router_mac_addr, 6 ); + D(bug("Fake ethernet address (same as router) %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); + } // Start packet reception thread int_ack = CreateSemaphore( 0, 0, 1, NULL); @@ -285,27 +305,14 @@ bool ether_init(void) ether_th = (HANDLE)_beginthreadex( 0, 0, ether_thread_feed_int, 0, 0, ðer_tid ); if (!ether_th) { - D(bug("Failed to create ethernet thread\r\n")); + D(bug("Failed to create ethernet thread\n")); goto open_error; } thread_active = true; -#if 0 - SetThreadPriority( ether_th, threads[THREAD_ETHER].priority_running ); - SetThreadAffinityMask( ether_th, threads[THREAD_ETHER].affinity_mask ); -#endif unsigned int dummy; ether_th2 = (HANDLE)_beginthreadex( 0, 0, ether_thread_get_packets_nt, 0, 0, &dummy ); -#if 0 - SetThreadPriority( ether_th2, threads[THREAD_ETHER].priority_running ); - SetThreadAffinityMask( ether_th2, threads[THREAD_ETHER].affinity_mask ); -#endif - ether_th1 = (HANDLE)_beginthreadex( 0, 0, ether_thread_write_packets, 0, 0, &dummy ); -#if 0 - SetThreadPriority( ether_th1, threads[THREAD_ETHER].priority_running ); - SetThreadAffinityMask( ether_th1, threads[THREAD_ETHER].affinity_mask ); -#endif // Everything OK return true; @@ -328,7 +335,7 @@ bool ether_init(void) int_send_now = 0; thread_active = false; } - if(!ether_fake) { + if(net_if_type == NET_IF_B2ETHER) { PacketCloseAdapter(fd); } fd = 0; @@ -342,45 +349,39 @@ bool ether_init(void) void ether_exit(void) { - D(bug("EtherExit\r\n")); + D(bug("EtherExit\n")); - // Take them down in a controlled way. + // Stop reception thread thread_active = false; - // _asm int 3 - - D(bug("Closing ethernet device %s\r\n",edevice)); - - if(!*edevice) return; - if(int_ack) ReleaseSemaphore(int_ack,1,NULL); if(int_sig) ReleaseSemaphore(int_sig,1,NULL); if(int_sig2) ReleaseSemaphore(int_sig2,1,NULL); if(int_send_now) ReleaseSemaphore(int_send_now,1,NULL); - D(bug("CancelIO if needed\r\n")); + D(bug("CancelIO if needed\n")); if (fd && fd->hFile && pfnCancelIo) pfnCancelIo(fd->hFile); // Wait max 2 secs to shut down pending io. After that, kill them. - D(bug("Wait delay\r\n")); + D(bug("Wait delay\n")); for( int i=0; i<10; i++ ) { if(!thread_active_1 && !thread_active_2 && !thread_active_3) break; Sleep(200); } if(thread_active_1) { - D(bug("Ether killing ether_th1\r\n")); + D(bug("Ether killing ether_th1\n")); if(ether_th1) TerminateThread(ether_th1,0); thread_active_1 = false; } if(thread_active_2) { - D(bug("Ether killing ether_th2\r\n")); + D(bug("Ether killing ether_th2\n")); if(ether_th2) TerminateThread(ether_th2,0); thread_active_2 = false; } if(thread_active_3) { - D(bug("Ether killing thread\r\n")); + D(bug("Ether killing thread\n")); if(ether_th) TerminateThread(ether_th,0); thread_active_3 = false; } @@ -389,7 +390,7 @@ void ether_exit(void) ether_th2 = 0; ether_th = 0; - D(bug("Closing semaphores\r\n")); + D(bug("Closing semaphores\n")); if(int_ack) { CloseHandle(int_ack); int_ack = 0; @@ -414,7 +415,7 @@ void ether_exit(void) } // Remove all protocols - D(bug("Removing protocols\r\n")); + D(bug("Removing protocols\n")); NetProtocol *p = prot_list; while (p) { NetProtocol *next = p->next; @@ -423,35 +424,203 @@ void ether_exit(void) } prot_list = 0; - D(bug("Deleting sections\r\n")); + D(bug("Deleting sections\n")); DeleteCriticalSection( &fetch_csection ); DeleteCriticalSection( &queue_csection ); DeleteCriticalSection( &send_csection ); DeleteCriticalSection( &wpool_csection ); - D(bug("Freeing read packets\r\n")); + D(bug("Freeing read packets\n")); free_read_packets(); - D(bug("Freeing write packets\r\n")); + D(bug("Freeing write packets\n")); free_write_packets(); - D(bug("Finalizing queue\r\n")); + D(bug("Finalizing queue\n")); final_queue(); - D(bug("Stopping router\r\n")); - router_final(); + if (net_if_type == NET_IF_ROUTER) { + D(bug("Stopping router\n")); + router_final(); + } - D(bug("EtherExit done\r\n")); + D(bug("EtherExit done\n")); } /* + * Glue around low-level implementation + */ + +#ifdef SHEEPSHAVER +// Error codes +enum { + eMultiErr = -91, + eLenErr = -92, + lapProtErr = -94, + excessCollsns = -95 +}; + +// Initialize ethernet +void EtherInit(void) +{ + net_open = false; + + // Do nothing if the user disabled the network + if (PrefsFindBool("nonet")) + return; + + net_open = ether_init(); +} + +// Exit ethernet +void EtherExit(void) +{ + ether_exit(); + net_open = false; +} + +// Get ethernet hardware address +void AO_get_ethernet_address(uint32 arg) +{ + uint8 *addr = Mac2HostAddr(arg); + if (net_open) + OTCopy48BitAddress(ether_addr, addr); + else { + addr[0] = 0x12; + addr[1] = 0x34; + addr[2] = 0x56; + addr[3] = 0x78; + addr[4] = 0x9a; + addr[5] = 0xbc; + } + 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])); +} + +// Add multicast address +void AO_enable_multicast(uint32 addr) +{ + if (net_open) + ether_do_add_multicast(Mac2HostAddr(addr)); +} + +// Disable multicast address +void AO_disable_multicast(uint32 addr) +{ + if (net_open) + ether_do_del_multicast(Mac2HostAddr(addr)); +} + +// Transmit one packet +void AO_transmit_packet(uint32 mp) +{ + if (net_open) { + switch (ether_do_write(mp)) { + case noErr: + num_tx_packets++; + break; + case excessCollsns: + num_tx_buffer_full++; + break; + } + } +} + +// Copy packet data from message block to linear buffer +static inline int ether_arg_to_buffer(uint32 mp, uint8 *p) +{ + return ether_msgb_to_buffer(mp, p); +} + +// Ethernet interrupt +void EtherIRQ(void) +{ + D(bug("EtherIRQ\n")); + num_ether_irq++; + + OTEnterInterrupt(); + ether_do_interrupt(); + OTLeaveInterrupt(); + + // Acknowledge interrupt to reception thread + D(bug(" EtherIRQ done\n")); + ReleaseSemaphore(int_ack,1,NULL); +} +#else +// Add multicast address +int16 ether_add_multicast(uint32 pb) +{ + return ether_do_add_multicast(Mac2HostAddr(pb + eMultiAddr)); +} + +// Disable multicast address +int16 ether_del_multicast(uint32 pb) +{ + return ether_do_del_multicast(Mac2HostAddr(pb + eMultiAddr)); +} + +// Transmit one packet +int16 ether_write(uint32 wds) +{ + return ether_do_write(wds); +} + +// Copy packet data from WDS to linear buffer +static inline int ether_arg_to_buffer(uint32 wds, uint8 *p) +{ + return ether_wds_to_buffer(wds, p); +} + +// Dispatch packet to protocol handler +static void ether_dispatch_packet(uint32 packet, uint32 length) +{ + // Get packet type + uint16 type = ReadMacInt16(packet + 12); + + // Look for protocol + NetProtocol *prot = find_protocol(type); + if (prot == NULL) + return; + + // No default handler + if (prot->handler == 0) + return; + + // Copy header to RHA + 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] = length - 14; // Remaining packet length (without header, 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])); + Execute68k(prot->handler, &r); +} + +// Ethernet interrupt +void EtherInterrupt(void) +{ + D(bug("EtherIRQ\n")); + ether_do_interrupt(); + + // Acknowledge interrupt to reception thread + D(bug(" EtherIRQ done\n")); + ReleaseSemaphore(int_ack,1,NULL); +} +#endif + + +/* * Reset */ void ether_reset(void) { - D(bug("EtherReset\r\n")); + D(bug("EtherReset\n")); // Remove all protocols NetProtocol *p = prot_list; @@ -468,18 +637,21 @@ void ether_reset(void) * Add multicast address */ -int16 ether_add_multicast(uint32 pb) +static int16 ether_do_add_multicast(uint8 *addr) { - D(bug("ether_add_multicast\r\n")); + D(bug("ether_add_multicast\n")); // We wouldn't need to do this // if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr; - if (!ether_fake && !PacketAddMulticast( fd, Mac2HostAddr(pb + eMultiAddr))) { - D(bug("WARNING: couldn't enable multicast address\r\n")); - return eMultiErr; - } else { - D(bug("ether_add_multicast: noErr\r\n")); + switch (net_if_type) { + case NET_IF_B2ETHER: + if (!PacketAddMulticast( fd, addr)) { + D(bug("WARNING: couldn't enable multicast address\n")); + return eMultiErr; + } + default: + D(bug("ether_add_multicast: noErr\n")); return noErr; } } @@ -489,18 +661,22 @@ int16 ether_add_multicast(uint32 pb) * Delete multicast address */ -int16 ether_del_multicast(uint32 pb) +int16 ether_do_del_multicast(uint8 *addr) { - D(bug("ether_del_multicast\r\n")); + D(bug("ether_del_multicast\n")); // We wouldn't need to do this // if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr; - if (!ether_fake && !PacketDelMulticast( fd, Mac2HostAddr(pb + eMultiAddr))) { - D(bug("WARNING: couldn't disable multicast address\r\n")); - return eMultiErr; - } else + switch (net_if_type) { + case NET_IF_B2ETHER: + if (!PacketDelMulticast( fd, addr)) { + D(bug("WARNING: couldn't disable multicast address\n")); + return eMultiErr; + } + default: return noErr; + } } @@ -510,12 +686,12 @@ int16 ether_del_multicast(uint32 pb) int16 ether_attach_ph(uint16 type, uint32 handler) { - D(bug("ether_attach_ph type=0x%x, handler=0x%x\r\n",(int)type,handler)); + D(bug("ether_attach_ph type=0x%x, handler=0x%x\n",(int)type,handler)); // Already attached? NetProtocol *p = find_protocol(type); if (p != NULL) { - D(bug("ether_attach_ph: lapProtErr\r\n")); + D(bug("ether_attach_ph: lapProtErr\n")); return lapProtErr; } else { // No, create and attach @@ -524,7 +700,7 @@ int16 ether_attach_ph(uint16 type, uint3 p->type = type; p->handler = handler; prot_list = p; - D(bug("ether_attach_ph: noErr\r\n")); + D(bug("ether_attach_ph: noErr\n")); return noErr; } } @@ -536,7 +712,7 @@ int16 ether_attach_ph(uint16 type, uint3 int16 ether_detach_ph(uint16 type) { - D(bug("ether_detach_ph type=%08lx\r\n",(int)type)); + D(bug("ether_detach_ph type=%08lx\n",(int)type)); NetProtocol *p = find_protocol(type); if (p != NULL) { @@ -569,10 +745,10 @@ static void dump_packet( uint8 *packet, if(length > 256) length = 256; for (int i=0; inext; - D(bug("Freeing write packet %ld\r\n",++i)); + D(bug("Freeing write packet %ld\n",++i)); PacketFreePacket(write_packet_pool); write_packet_pool = next; } @@ -640,7 +816,7 @@ void recycle_write_packet( LPPACKET Pack EnterCriticalSection( &wpool_csection ); Packet->next = write_packet_pool; write_packet_pool = Packet; - D(bug("Pool size after recycling = %ld\r\n",get_write_packet_pool_sz())); + D(bug("Pool size after recycling = %ld\n",get_write_packet_pool_sz())); LeaveCriticalSection( &wpool_csection ); } @@ -665,7 +841,7 @@ static LPPACKET get_write_packet( UINT l Packet = PacketAllocatePacket(fd,len); } - D(bug("Pool size after get wr packet = %ld\r\n",get_write_packet_pool_sz())); + D(bug("Pool size after get wr packet = %ld\n",get_write_packet_pool_sz())); LeaveCriticalSection( &wpool_csection ); @@ -678,25 +854,33 @@ static unsigned int ether_thread_write_p thread_active_1 = true; - D(bug("ether_thread_write_packets start\r\n")); + D(bug("ether_thread_write_packets start\n")); while(thread_active) { // must be alertable, otherwise write completion is never called WaitForSingleObjectEx(int_send_now,INFINITE,TRUE); while( thread_active && (Packet = get_send_head()) != 0 ) { - if(m_router_enabled && router_write_packet((uint8 *)Packet->Buffer, Packet->Length)) { - Packet->bIoComplete = TRUE; - recycle_write_packet(Packet); - } else if(ether_fake) { + switch (net_if_type) { + case NET_IF_ROUTER: + if(router_write_packet((uint8 *)Packet->Buffer, Packet->Length)) { + Packet->bIoComplete = TRUE; + recycle_write_packet(Packet); + } + break; + case NET_IF_FAKE: Packet->bIoComplete = TRUE; recycle_write_packet(Packet); - } else if(!PacketSendPacket( fd, Packet, FALSE, TRUE )) { - // already recycled if async + break; + case NET_IF_B2ETHER: + if(!PacketSendPacket( fd, Packet, FALSE, TRUE )) { + // already recycled if async + } + break; } } } - D(bug("ether_thread_write_packets exit\r\n")); + D(bug("ether_thread_write_packets exit\n")); thread_active_1 = false; @@ -707,7 +891,7 @@ static BOOL write_packet( uint8 *packet, { LPPACKET Packet; - D(bug("write_packet\r\n")); + D(bug("write_packet\n")); Packet = get_write_packet(len); if(Packet) { @@ -728,29 +912,16 @@ static BOOL write_packet( uint8 *packet, } } -int16 ether_write(uint32 wds) +static int16 ether_do_write(uint32 arg) { - D(bug("ether_write\r\n")); - - // Set source address - uint32 hdr = ReadMacInt32(wds + 2); - memcpy(Mac2HostAddr(hdr + 6), ether_addr, 6); + D(bug("ether_write\n")); // Copy packet to buffer uint8 packet[1514], *p = packet; - int len = 0; - for (;;) { - uint16 w = (uint16)ReadMacInt16(wds); - if (w == 0) - break; - memcpy(p, Mac2HostAddr(ReadMacInt32(wds + 2)), w); - len += w; - p += w; - wds += 6; - } + int len = ether_arg_to_buffer(arg, p); if(len > 1514) { - D(bug("illegal packet length: %d\r\n",len)); + D(bug("illegal packet length: %d\n",len)); return eLenErr; } else { #if MONITOR @@ -761,7 +932,7 @@ int16 ether_write(uint32 wds) // Transmit packet if (!write_packet(packet, len)) { - D(bug("WARNING: couldn't transmit packet\r\n")); + D(bug("WARNING: couldn't transmit packet\n")); return excessCollsns; } else { // It's up to the protocol drivers to do the error checking. Even if the @@ -795,7 +966,7 @@ void enqueue_packet( uint8 *buf, int sz { EnterCriticalSection( &queue_csection ); if(queue[queue_inx].sz > 0) { - D(bug("ethernet queue full, packet dropped\r\n")); + D(bug("ethernet queue full, packet dropped\n")); } else { if(sz > 1514) sz = 1514; queue[queue_inx].sz = sz; @@ -832,7 +1003,7 @@ static void trigger_queue(void) { EnterCriticalSection( &queue_csection ); if( queue[queue_head].sz > 0 ) { - D(bug(" packet received, triggering Ethernet interrupt\r\n")); + D(bug(" packet received, triggering Ethernet interrupt\n")); SetInterruptFlag(INTFLAG_ETHER); TriggerInterrupt(); // of course can't wait here. @@ -881,19 +1052,19 @@ VOID CALLBACK packet_read_completion( if(count == pending_packet_sz[j] && memcmp(pending_packet[j],lpPacket->Buffer,count) == 0) { - D(bug("packet_read_completion discarding own packet.\r\n")); + D(bug("packet_read_completion discarding own packet.\n")); dwNumberOfBytesTransfered = 0; j = (j+1) & (~(MAX_ECHO-1)); if(j != echo_count) { - D(bug("Wow, this fix made some good after all...\r\n")); + D(bug("Wow, this fix made some good after all...\n")); } break; } } if(dwNumberOfBytesTransfered) { - if(!m_router_enabled || !router_read_packet((uint8 *)lpPacket->Buffer, dwNumberOfBytesTransfered)) { + if(net_if_type != NET_IF_ROUTER || !router_read_packet((uint8 *)lpPacket->Buffer, dwNumberOfBytesTransfered)) { enqueue_packet( (LPBYTE)lpPacket->Buffer, dwNumberOfBytesTransfered ); } } @@ -937,7 +1108,7 @@ static bool allocate_read_packets(void) for( int i=0; ifree) { packets[i]->free = FALSE; if(PacketReceivePacket(fd,packets[i],FALSE)) { if(packets[i]->bIoComplete) { - D(bug("Early io completion...\r\n")); + D(bug("Early io completion...\n")); packet_read_completion( ERROR_SUCCESS, packets[i]->BytesReceived, @@ -986,13 +1157,13 @@ static unsigned int ether_thread_get_pac } if(thread_active && has_no_completed_io()) { - D(bug("Waiting for int_sig2\r\n")); + D(bug("Waiting for int_sig2\n")); // "problem": awakens twice in a row. Fix if you increase the pool size. WaitForSingleObjectEx(int_sig2,INFINITE,TRUE); } } - D(bug("ether_thread_get_packets_nt exit\r\n")); + D(bug("ether_thread_get_packets_nt exit\n")); thread_active_2 = false; @@ -1005,13 +1176,13 @@ static unsigned int ether_thread_feed_in thread_active_3 = true; - D(bug("ether_thread_feed_int start\r\n")); + D(bug("ether_thread_feed_int start\n")); while(thread_active) { - D(bug("Waiting for int_sig\r\n")); + D(bug("Waiting for int_sig\n")); WaitForSingleObject(int_sig,INFINITE); // Looping this way to avoid a race condition. - D(bug("Triggering\r\n")); + D(bug("Triggering\n")); looping = true; while(thread_active && looping) { trigger_queue(); @@ -1019,10 +1190,10 @@ static unsigned int ether_thread_feed_in WaitForSingleObject(int_ack,INFINITE); if(thread_active) looping = set_wait_request(); } - D(bug("Queue empty.\r\n")); + D(bug("Queue empty.\n")); } - D(bug("ether_thread_feed_int exit\r\n")); + D(bug("ether_thread_feed_int exit\n")); thread_active_3 = false; @@ -1034,57 +1205,27 @@ static unsigned int ether_thread_feed_in * Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers */ -void EtherInterrupt(void) +static void ether_do_interrupt(void) { - int length; - static uint8 packet[1514]; - - D(bug("EtherIRQ\r\n")); - // Call protocol handler for received packets - while( (length = dequeue_packet(packet)) > 0 ) { + EthernetPacket ether_packet; + uint32 packet = ether_packet.addr(); + ssize_t length; + for (;;) { + // Read packet from Ethernet device + length = dequeue_packet(Mac2HostAddr(packet)); if (length < 14) - continue; + break; #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)); - - // Look for protocol - NetProtocol *prot = find_protocol(type); - if (prot == NULL) - continue; - // break; - - // No default handler - if (prot->handler == 0) - continue; - // break; - - // Copy header to RHA - memcpy(Mac2HostAddr(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 - 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[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])); - Execute68k(prot->handler, &r); + // Dispatch packet + ether_dispatch_packet(packet, length); } - - // Acknowledge interrupt to reception thread - D(bug(" EtherIRQ done\r\n")); - ReleaseSemaphore(int_ack,1,NULL); } #if DEBUG