1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
/* w5100.c: Wiznet W5100 emulation - internal routines
Emulates a minimal subset of the Wiznet W5100 TCP/IP controller.
Copyright (c) 2011 Philip Kendall
$Id: w5100_internals.h 4912 2013-03-24 19:34:06Z sbaldovi $
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Author contact information:
E-mail: philip-fuse@shadowmagic.org.uk
*/
#ifndef FUSE_W5100_INTERNALS_H
#define FUSE_W5100_INTERNALS_H
#include <signal.h>
typedef enum w5100_socket_mode {
W5100_SOCKET_MODE_CLOSED = 0x00,
W5100_SOCKET_MODE_TCP,
W5100_SOCKET_MODE_UDP,
W5100_SOCKET_MODE_IPRAW,
W5100_SOCKET_MODE_MACRAW,
W5100_SOCKET_MODE_PPPOE,
} w5100_socket_mode;
typedef enum w5100_socket_state {
W5100_SOCKET_STATE_CLOSED = 0x00,
W5100_SOCKET_STATE_INIT = 0x13,
W5100_SOCKET_STATE_LISTEN,
W5100_SOCKET_STATE_ESTABLISHED = 0x17,
W5100_SOCKET_STATE_CLOSE_WAIT = 0x1c,
W5100_SOCKET_STATE_UDP = 0x22,
} w5100_socket_state;
enum w5100_socket_registers {
W5100_SOCKET_MR = 0x00,
W5100_SOCKET_CR,
W5100_SOCKET_IR,
W5100_SOCKET_SR,
W5100_SOCKET_PORT0,
W5100_SOCKET_PORT1,
W5100_SOCKET_DIPR0 = 0x0c,
W5100_SOCKET_DIPR1,
W5100_SOCKET_DIPR2,
W5100_SOCKET_DIPR3,
W5100_SOCKET_DPORT0,
W5100_SOCKET_DPORT1,
W5100_SOCKET_TX_FSR0 = 0x20,
W5100_SOCKET_TX_FSR1,
W5100_SOCKET_TX_RR0,
W5100_SOCKET_TX_RR1,
W5100_SOCKET_TX_WR0,
W5100_SOCKET_TX_WR1,
W5100_SOCKET_RX_RSR0,
W5100_SOCKET_RX_RSR1,
W5100_SOCKET_RX_RD0,
W5100_SOCKET_RX_RD1,
};
typedef struct nic_w5100_socket_t {
int id; /* For debug use only */
/* W5100 properties */
w5100_socket_mode mode;
libspectrum_byte flags;
w5100_socket_state state;
libspectrum_byte ir; /* Interrupt register */
libspectrum_byte port[2]; /* Source port */
libspectrum_byte dip[4]; /* Destination IP address */
libspectrum_byte dport[2];/* Destination port */
libspectrum_word tx_rr; /* Transmit read pointer */
libspectrum_word tx_wr; /* Transmit write pointer */
libspectrum_word rx_rsr; /* Received size */
libspectrum_word rx_rd; /* Received read pointer */
libspectrum_word old_rx_rd; /* Used in RECV command processing */
libspectrum_byte tx_buffer[0x800]; /* Transmit buffer */
libspectrum_byte rx_buffer[0x800]; /* Received buffer */
/* Host properties */
compat_socket_t fd; /* Socket file descriptor */
int bind_count; /* Number of writes to the Sn_PORTx registers we've received */
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 */
int last_send; /* The value of Sn_TX_WR when the SEND command was last sent */
int datagram_lengths[0x20]; /* The lengths of datagrams to be sent */
int datagram_count;
/* Flag used to indicate that a socket has been closed since we started
waiting for it in a select() call and therefore the socket should no
longer be used */
int ok_for_io;
pthread_mutex_t lock; /* Mutex for this socket */
} nic_w5100_socket_t;
struct nic_w5100_t {
libspectrum_byte gw[4]; /* Gateway IP address */
libspectrum_byte sub[4]; /* Our subnet mask */
libspectrum_byte sha[6]; /* MAC address */
libspectrum_byte sip[4]; /* Our IP address */
nic_w5100_socket_t socket[4];
pthread_t thread; /* Thread for doing I/O */
sig_atomic_t stop_io_thread; /* Flag to stop I/O thread */
compat_socket_selfpipe_t *selfpipe; /* Device for waking I/O thread */
};
void nic_w5100_socket_init( nic_w5100_socket_t *socket, int which );
void nic_w5100_socket_end( nic_w5100_socket_t *socket );
void nic_w5100_socket_reset( nic_w5100_socket_t *socket );
libspectrum_byte nic_w5100_socket_read( nic_w5100_t *self, libspectrum_word reg );
void nic_w5100_socket_write( nic_w5100_t *self, libspectrum_word reg, libspectrum_byte b );
libspectrum_byte nic_w5100_socket_read_rx_buffer( nic_w5100_t *self, libspectrum_word reg );
void nic_w5100_socket_write_tx_buffer( nic_w5100_t *self, libspectrum_word reg, libspectrum_byte b );
void nic_w5100_socket_add_to_sets( nic_w5100_socket_t *socket, fd_set *readfds,
fd_set *writefds, int *max_fd );
void nic_w5100_socket_process_io( nic_w5100_socket_t *socket, fd_set readfds,
fd_set writefds );
/* Debug routines */
/* Define this to spew debugging info to stdout */
#define W5100_DEBUG 0
void nic_w5100_debug( const char *format, ... );
void nic_w5100_vdebug( const char *format, va_list ap );
void nic_w5100_error( int severity, const char *format, ... );
#endif /* #ifndef FUSE_W5100_H */
|