Index: peripherals/spectranet.c =================================================================== --- peripherals/spectranet.c (revision 4510) +++ peripherals/spectranet.c (working copy) @@ -410,6 +410,22 @@ return 0; } +libspectrum_error +spectranet_end( void ) +{ + if( w5100 ) { + nic_w5100_free( w5100 ); + w5100 = NULL; + } + + if( flash_rom ) { + flash_am29f010_free( flash_rom ); + flash_rom = NULL; + } + + return LIBSPECTRUM_ERROR_NONE; +} + static libspectrum_word get_w5100_register( memory_page *page, libspectrum_word address ) { Index: peripherals/spectranet.h =================================================================== --- peripherals/spectranet.h (revision 4510) +++ peripherals/spectranet.h (working copy) @@ -27,6 +27,7 @@ #define FUSE_SPECTRANET_H int spectranet_init( void ); +libspectrum_error spectranet_end( void ); void spectranet_page( int via_io ); void spectranet_unpage( void ); Index: peripherals/nic/w5100_internals.h =================================================================== --- peripherals/nic/w5100_internals.h (revision 4510) +++ peripherals/nic/w5100_internals.h (working copy) @@ -29,6 +29,26 @@ #ifndef FUSE_W5100_INTERNALS_H #define FUSE_W5100_INTERNALS_H +#ifdef WIN32 +#include +#endif /* #ifdef WIN32 */ + +#ifdef WIN32 + +#define close_socket( x ) closesocket( x ) +#define socket_error WSAGetLastError() +#define POLLING_INTERVAL 100000 +typedef SOCKET socket_t; + +#else + +#define INVALID_SOCKET -1 +#define close_socket( x ) close( x ) +#define socket_error errno +typedef int socket_t; + +#endif /* #ifdef WIN32 */ + typedef enum w5100_socket_mode { W5100_SOCKET_MODE_CLOSED = 0x00, W5100_SOCKET_MODE_TCP, @@ -106,7 +126,7 @@ /* Host properties */ - int fd; /* Socket file descriptor */ + socket_t fd; /* Socket file descriptor */ int socket_bound; /* True once we've bound the socket to a port */ int write_pending; /* True if we're waiting to write data on this socket */ Index: peripherals/nic/w5100_socket.c =================================================================== --- peripherals/nic/w5100_socket.c (revision 4510) +++ peripherals/nic/w5100_socket.c (working copy) @@ -28,15 +28,20 @@ #include "config.h" -#include #include -#include #include #include -#include #include #include +#ifdef WIN32 +#include +#else +#include +#include +#include +#endif /* #ifdef WIN32 */ + #include "fuse.h" #include "ui/ui.h" #include "w5100.h" @@ -55,7 +60,7 @@ nic_w5100_socket_init( nic_w5100_socket_t *socket, int which ) { socket->id = which; - socket->fd = -1; + socket->fd = INVALID_SOCKET; socket->socket_bound = 0; socket->ok_for_io = 0; pthread_mutex_init( &socket->lock, NULL ); @@ -113,10 +118,10 @@ void nic_w5100_socket_free( nic_w5100_socket_t *socket ) { - if( socket->fd != -1 ) { + if( socket->fd != INVALID_SOCKET ) { w5100_socket_acquire_lock( socket ); - close( socket->fd ); - socket->fd = -1; + close_socket( socket->fd ); + socket->fd = INVALID_SOCKET; socket->socket_bound = 0; socket->ok_for_io = 0; socket->write_pending = 0; @@ -171,8 +176,8 @@ w5100_socket_acquire_lock( socket_obj ); socket_obj->fd = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); - if( socket_obj->fd == -1 ) { - printf("w5100: failed to open UDP socket for socket %d; errno = %d : %s\n", socket_obj->id, errno, strerror(errno)); + if( socket_obj->fd == INVALID_SOCKET ) { + printf("w5100: failed to open UDP socket for socket %d; errno = %d : %s\n", socket_obj->id, socket_error, strerror(socket_error)); w5100_socket_release_lock( socket_obj ); return; } @@ -187,8 +192,8 @@ w5100_socket_acquire_lock( socket_obj ); socket_obj->fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); - if( socket_obj->fd == -1 ) { - printf("w5100: failed to open TCP socket for socket %d; errno = %d : %s\n", socket_obj->id, errno, strerror(errno)); + if( socket_obj->fd == INVALID_SOCKET ) { + printf("w5100: failed to open TCP socket for socket %d; errno = %d : %s\n", socket_obj->id, socket_error, strerror(socket_error)); w5100_socket_release_lock( socket_obj ); return; } @@ -211,8 +216,7 @@ printf("w5100: attempting to bind socket IP %s\n", inet_ntoa(sa.sin_addr)); if( bind( socket->fd, (struct sockaddr*)&sa, sizeof(sa) ) == -1 ) { - printf("w5100: failed to bind socket %d; errno = %d : %s\n", socket->id, errno, strerror(errno)); - w5100_socket_release_lock( socket ); + printf("w5100: failed to bind socket %d; errno = %d : %s\n", socket->id, socket_error, strerror(socket_error)); return; } @@ -236,7 +240,7 @@ memcpy( &sa.sin_addr.s_addr, socket->dip, 4 ); if( connect( socket->fd, (struct sockaddr*)&sa, sizeof(sa) ) == -1 ) { - printf("w5100: failed to connect socket %d to 0x%08x:0x%04x; errno = %d : %s\n", socket->id, ntohl(sa.sin_addr.s_addr), ntohs(sa.sin_port), errno, strerror(errno)); + printf("w5100: failed to connect socket %d to 0x%08x:0x%04x; errno = %d : %s\n", socket->id, ntohl(sa.sin_addr.s_addr), ntohs(sa.sin_port), socket_error, strerror(socket_error)); socket->ir |= 1 << 3; socket->state = W5100_SOCKET_STATE_CLOSED; w5100_socket_release_lock( socket ); @@ -268,9 +272,9 @@ w5100_socket_close( nic_w5100_t *self, nic_w5100_socket_t *socket ) { w5100_socket_acquire_lock( socket ); - if( socket->fd != -1 ) { - close( socket->fd ); - socket->fd = -1; + if( socket->fd != INVALID_SOCKET ) { + close_socket( socket->fd ); + socket->fd = INVALID_SOCKET; socket->socket_bound = 0; socket->ok_for_io = 0; socket->state = W5100_SOCKET_STATE_CLOSED; @@ -403,6 +407,7 @@ printf("w5100: reading 0x%02x from unsupported register 0x%03x\n", b, reg ); break; } + return b; } @@ -481,7 +486,7 @@ { w5100_socket_acquire_lock( socket ); - if( socket->fd != -1 ) { + if( socket->fd != INVALID_SOCKET ) { /* We can process a UDP read if we're in a UDP state and there are at least 9 bytes free in our buffer (8 byte UDP header and 1 byte of actual data). */ @@ -528,11 +533,11 @@ sa.sin_family = AF_INET; memcpy( &sa.sin_port, socket->port, 2 ); sa.sin_addr.s_addr = htonl(INADDR_ANY); - bytes_read = recvfrom( socket->fd, buffer + 8, bytes_free - 8, 0, (struct sockaddr*)&sa, &sa_length ); + bytes_read = recvfrom( socket->fd, (char *)buffer + 8, bytes_free - 8, 0, (struct sockaddr*)&sa, &sa_length ); printf("w5100: read 0x%03x bytes from UDP socket %d\n", (int)bytes_read, socket->id); } else { - bytes_read = recv( socket->fd, buffer, bytes_free, 0 ); + bytes_read = recv( socket->fd, (char *)buffer, bytes_free, 0 ); printf("w5100: read 0x%03x bytes from TCP socket %d\n", (int)bytes_read, socket->id); } @@ -562,7 +567,7 @@ } } else { - printf("w5100: error %d reading from socket %d : %s\n", errno, socket->id, strerror(errno)); + printf("w5100: error %d reading from socket %d : %s\n", socket_error, socket->id, strerror(socket_error)); } } @@ -592,7 +597,7 @@ memcpy( &sa.sin_port, socket->dport, 2 ); memcpy( &sa.sin_addr.s_addr, socket->dip, 4 ); - bytes_sent = sendto( socket->fd, data, length, 0, (struct sockaddr*)&sa, sizeof(sa) ); + bytes_sent = sendto( socket->fd, (const char *)data, length, 0, (struct sockaddr*)&sa, sizeof(sa) ); printf("w5100: sent 0x%03x bytes of 0x%03x to UDP socket %d\n", (int)bytes_sent, length, socket->id); if( bytes_sent == length ) { @@ -609,7 +614,7 @@ else if( bytes_sent != -1 ) printf("w5100: didn't manage to send full datagram to UDP socket %d?\n", socket->id); else - printf("w5100: error %d writing to UDP socket %d : %s\n", errno, socket->id, strerror(errno)); + printf("w5100: error %d writing to UDP socket %d : %s\n", socket_error, socket->id, strerror(socket_error)); } static void @@ -626,7 +631,7 @@ if( offset + length > 0x800 ) length = 0x800 - offset; - bytes_sent = send( socket->fd, data, length, 0 ); + bytes_sent = send( socket->fd, (const char*)data, length, 0 ); printf("w5100: sent 0x%03x bytes of 0x%03x to TCP socket %d\n", (int)bytes_sent, length, socket->id); if( bytes_sent != -1 ) { @@ -637,7 +642,7 @@ } } else - printf("w5100: error %d writing to TCP socket %d : %s\n", errno, socket->id, strerror(errno)); + printf("w5100: error %d writing to TCP socket %d : %s\n", socket_error, socket->id, strerror(socket_error)); } void @@ -648,7 +653,7 @@ /* Process only if we're an open socket, and we haven't been closed and re-opened since the select() started */ - if( socket->fd != -1 && socket->ok_for_io ) { + if( socket->fd != INVALID_SOCKET && socket->ok_for_io ) { if( FD_ISSET( socket->fd, &readfds ) ) w5100_socket_process_read( socket ); Index: peripherals/nic/w5100.c =================================================================== --- peripherals/nic/w5100.c (revision 4510) +++ peripherals/nic/w5100.c (working copy) @@ -29,12 +29,21 @@ #include "config.h" #include -#include #include -#include #include #include +#ifdef WIN32 + +#include + +#else + +#include +#include + +#endif /* #ifdef WIN32 */ + #include "fuse.h" #include "ui/ui.h" #include "w5100.h" @@ -92,20 +101,29 @@ { nic_w5100_t *self = arg; int i; + fd_set readfds, writefds; + int max_fd; +#ifdef WIN32 + struct timeval tv; + fd_set *readfds_p, *writefds_p; +#endif /* ifdef WIN32 */ + while( !self->stop_io_thread ) { - fd_set readfds, writefds; - int max_fd = self->pipe_read; + max_fd = -1; + FD_ZERO( &readfds ); + FD_ZERO( &writefds ); - FD_ZERO( &readfds ); +#ifndef WIN32 + max_fd = self->pipe_read; FD_SET( self->pipe_read, &readfds ); +#endif /* ifndef WIN32 */ - FD_ZERO( &writefds ); - for( i = 0; i < 4; i++ ) nic_w5100_socket_add_to_sets( &self->socket[i], &readfds, &writefds, &max_fd ); +#ifndef WIN32 printf("w5100: io thread select\n"); select( max_fd + 1, &readfds, &writefds, NULL, NULL ); @@ -117,7 +135,31 @@ printf("w5100: discarding pipe data\n"); read( self->pipe_read, &bitbucket, 1 ); } +#else + /* Set max wait time upto 0.1 sec if not IO is completed */ + tv.tv_sec = 0; + tv.tv_usec = POLLING_INTERVAL; + readfds_p = ( readfds.fd_count )? &readfds : NULL; + writefds_p = ( writefds.fd_count )? &writefds : NULL; + + /* Call select() only if there are pending sockets */ + if( readfds_p || writefds_p ) + { + printf("w5100: io thread select\n"); + + if( select( max_fd + 1, readfds_p, writefds_p, NULL, &tv ) < 0 ) { + printf( "w5100: io thread wake from select with error %d\n", + socket_error ); + } + } + else { + usleep( tv.tv_usec ); + } + + printf("w5100: io thread wake\n"); +#endif /* ifndef WIN32 */ + for( i = 0; i < 4; i++ ) nic_w5100_socket_process_io( &self->socket[i], readfds, writefds ); } @@ -128,17 +170,38 @@ void nic_w5100_wake_io_thread( nic_w5100_t *self ) { +#ifndef WIN32 const char dummy = 0; write( self->pipe_write, &dummy, 1 ); +#endif /* ifndef WIN32 */ } nic_w5100_t* nic_w5100_alloc( void ) { int error; - int pipefd[2]; int i; +#ifndef WIN32 + int pipefd[2]; +#else + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD( 2, 2 ); + error = WSAStartup( wVersionRequested, &wsaData ); + if( error ) { + ui_error( UI_ERROR_ERROR, "WSAStartup failed with error: %d", error ); + fuse_abort(); + } + printf("WSAStartup\n"); + if( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { + WSACleanup(); + ui_error( UI_ERROR_ERROR, "FUSE could not find an usable Winsock DLL" ); + fuse_abort(); + } +#endif /* ifndef WIN32 */ + nic_w5100_t *self = malloc( sizeof( *self ) ); if( !self ) { ui_error( UI_ERROR_ERROR, "%s:%d out of memory", __FILE__, __LINE__ ); @@ -150,6 +213,7 @@ w5100_reset( self ); +#ifndef WIN32 error = pipe( pipefd ); if( error ) { ui_error( UI_ERROR_ERROR, "w5100: error %d creating pipe", error ); @@ -158,6 +222,7 @@ self->pipe_read = pipefd[0]; self->pipe_write = pipefd[1]; +#endif /* ifndef WIN32 */ self->stop_io_thread = 0; @@ -178,11 +243,22 @@ self->stop_io_thread = 1; nic_w5100_wake_io_thread( self ); +#ifdef WIN32 + /* wait IO thread wake up */ + usleep( 2 * POLLING_INTERVAL ); +#endif /* ifdef WIN32 */ + pthread_join( self->thread, NULL ); for( i = 0; i < 4; i++ ) nic_w5100_socket_free( &self->socket[i] ); - + +#ifdef WIN32 + printf("WSACleanup\n"); + if( WSACleanup() ) + printf( "Error in WSACleanup: %d\n", socket_error ); +#endif /* ifdef WIN32 */ + free( self ); } Index: fuse.c =================================================================== --- fuse.c (revision 4510) +++ fuse.c (working copy) @@ -831,6 +831,7 @@ opus_end(); plusd_end(); disciple_end(); + spectranet_end(); machine_end(); Index: configure.in =================================================================== --- configure.in (revision 4510) +++ configure.in (working copy) @@ -110,7 +110,7 @@ AC_MSG_RESULT($win32) if test "$win32" = yes; then AC_CHECK_HEADER(windows.h, - LIBS="$LIBS -mwindows -lcomctl32 -lwinmm"; + LIBS="$LIBS -mwindows -lcomctl32 -lwinmm -lpthread"; AC_DEFINE([UI_WIN32], 1, [Defined if Win32 UI in use]) AC_DEFINE([WINVER], 0x0400, [Minimal supported version of Windows is 95 or NT4]) AC_DEFINE([_WIN32_IE], 0x400, [Internet Explorer is 4.0 or higher is required])