summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/sbc_harness/hw/w5500.c164
1 files changed, 91 insertions, 73 deletions
diff --git a/cmd/sbc_harness/hw/w5500.c b/cmd/sbc_harness/hw/w5500.c
index b4000f4..7470401 100644
--- a/cmd/sbc_harness/hw/w5500.c
+++ b/cmd/sbc_harness/hw/w5500.c
@@ -163,11 +163,11 @@ struct w5500_block_sock_reg {
uint8_t mode; /* Sn_MR; see MODE_{x} below */
uint8_t command; /* Sn_CR; see CMD_{x} below */
uint8_t interrupt; /* Sn_IR */
- uint8_t status; /* Sn_SR; see STATUS_{x} below */
- uint8_t local_port[2]; /* Sn_PORT0, Sn_PORT1 */
- uint8_t remote_eth_addr[6]; /* Sn_DHAR0 ... SnDHAR5 */
- uint8_t remote_ip_addr[4]; /* Sn_DIPR0 ... Sn_DIP3 */
- uint8_t remote_port[2]; /* Sn_DPORT0 ... Sn_DPORT1 */
+ uint8_t state; /* Sn_SR; see STATE_{x} below */
+ uint8_t local_port[2]; /* Sn_PORT0, Sn_PORT1 */
+ uint8_t remote_eth_addr[6]; /* Sn_DHAR0 ... SnDHAR5 */
+ uint8_t remote_ip_addr[4]; /* Sn_DIPR0 ... Sn_DIP3 */
+ uint8_t remote_port[2]; /* Sn_DPORT0 ... Sn_DPORT1 */
uint8_t max_seg_size[2]; /* Sn_MSSR0, Sn_MSSR1 */
uint8_t _reserved0[1];
@@ -218,74 +218,92 @@ static_assert(sizeof(struct w5500_block_sock_reg) == 0x30);
#define CMD_SEND_KEEP ((uint8_t)0x22) /* TCP-only: send a keepalive without any data */
#define CMD_RECV ((uint8_t)0x40)
-#define STATUS_CLOSED ((uint8_t)0x00)
+#define STATE_CLOSED ((uint8_t)0x00)
-/* The status modes starting with an underscore are expected to be
- * very short-lived. */
-
-#define STATUS_TCP_INIT ((uint8_t)0x13)
-#define STATUS_TCP_LISTEN ((uint8_t)0x14)
-#define _STATUS_TCP_SYNSENT ((uint8_t)0x15) /* in the CMD_CONNECT INIT->SYNSENT->ESTABLISHED transition */
-#define _STATUS_TCP_SYNRECV ((uint8_t)0x16) /* in the CMD_LISTEN LISTEN->SYNRECV->ESTABLISHED transition */
-#define STATUS_TCP_ESTABLISHED ((uint8_t)0x17)
-/* The "graceful shutdown" state diagram (with the exception that
- * reading the W5500's "status" register does not distinguish between
- * FIN_WAIT_1 and FIN_WAIT_2; it just has a single FIN_WAIT):
- *
- * ║
- * V
- * ┌─────────────┐
- * "active close" │ ESTABLISHED │ "passive close"
- * (we send FIN first) └─────────────┘ (we send FIN second)
- * V V
- * ╔═══════════╝ ╚═════════╗
- * (CMD_DISCON) ║
- * ┌┈┈┈<(send FIN)>┈┈┈┈┈┈┈┈┐ ║
- * ┊ ║ └┈┈┈┈┈┈┈>(recv FIN)
- * ┊ V ┌┈┈┈┈┈┈┈<(send ACK)
- * "double active" ┊ ┌────────────┐ ┊ ║
- * (both sides think ┊ │ FIN_WAIT_1 │ ┊ V
- * they sent FIN first) ┊ └────────────┘ ┊ ┌────────────┐
- * ┊ V V ┊ │ CLOSE_WAIT │
- * ╔═════════════════╝ ╔══╝ ┊ └────────────┘
- * (recv FIN)<┈┈┈┈┈┤ ║ ┊ V
- * ┌┈┈<(send ACK)>┈┈┈┐ ┊ ║ ┊ ║
- * ┊ ║ └┈┈┈┈┈>(recv ACK)<┈┈┈┈┈┈┈┈┘ ║
- * ┊ ║ ┊ ║ ║
- * ┊ V ┊ V ║
- * ┊ ┌─────────┐ ┊ ┌────────────┐ ║
- * ┊ │ CLOSING │ ┊ │ FIN_WAIT_2 │ ║
- * ┊ └─────────┘ ┊ └────────────┘ ║
- * ┊ V ┊ V (CMD_DISCON)
- * ┊ ║ ┊ ║ ┌┈┈┈┈┈┈┈<(send FIN)
- * ┊ ║ └┈┈┈>(recv FIN)<┈┈┈┈┈┈┈┈┘ ║
- * ┊ ║ ┌┈┈┈┈┈<(send ACK)>┈┈┈┈┈┈┈┈┐ V
- * └┈┈>(recv ACK)<┈┈┈┘ ║ ┊ ┌──────────┐
- * ╚═════════════════╗ ╚═╗ ┊ │ LAST_ACK │
- * V V ┊ └──────────┘
- * ┌───────────┐ ┊ V
- * │ TIME_WAIT │ ┊ ║
- * └───────────┘ └┈┈┈┈┈┈┈>(recv ACK)
- * V ║
- * ║ ║
- * (2*MSL has elapsed) ║
- * ╚═══════════╗ ╔══════════╝
- * V V
- * ┌────────┐
- * │ CLOSED │
- * └────────┘
+/**
+ * The TCP state diagram is as follows.
+ * - Reading the W5500's "state" register does not distinguish between FIN_WAIT_1 and FIN_WAIT_2;
+ * it just has a single FIN_WAIT.
+ * - At any point the state can jump to "CLOSED" either by CMD_CLOSE or by a timeout.
+ * - Writing data is valid in ESTABLISHED and CLOSE_WAIT.
+ * - Reading data is valid in ESTABLISHED and FIN_WAIT.
*
- * One can still write in CLOSE_WAIT, and can still read in FIN_WAIT.
+ * │ CLOSED │
+ * └────────┘
+ * V
+ * (CMD_OPEN)
+ * V
+ * ┌────────┐
+ * ┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━│ INIT │━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓
+ * ┃ server ┃ └────────┘ ┃ client ┃
+ * ┣━━━━━━━━━━━━━━━━┛ V ┃┃ V ┗━━━━━━━━━━━━━━━━┫
+ * ┃ ╔═══════════╝ ┃┃ ╚═══════════╗ ┃
+ * ┃ (CMD_LISTEN) ┃┃ (CMD_CONNECT) ┃
+ * ┃ V ┌┃┃┈┈┈┈┈┈┈┈<(send SYN) ┃
+ * ┃ ┌────────┐ ┊┃┃ V ┃
+ * ┃ │ LISTEN │ ┊┃┃ ┌─────────┐ ┃
+ * ┃ └────────┘ ┊┃┃ │ SYNSENT │ ┃
+ * ┃ V ┊┃┃ └─────────┘ ┃
+ * ┃ (recv SYN)<┈┈┈┈┈┈┘┃┃ V ┃
+ * ┃ (send SYN+ACK)>┈┈┈┈┐┃┃ ║ ┃
+ * ┃ V └┃┃┈┈┈┈┈┈>(recv SYN+ACK) ┃
+ * ┃ ┌─────────┐ ┌┃┃┈┈┈┈┈┈┈┈<(send ack) ┃
+ * ┃ │ SYNRECV │ ┊┃┃ ║ ┃
+ * ┃ └─────────┘ ┊┃┃ ║ ┃
+ * ┃ V V ┊┃┃ ║ ┃
+ * ┃ ║ (recv ACK)<┈┈┈┘┃┃ ║ ┃
+ * ┃ ║ ╚═════════╗ ┃┃ ╔═══════════╝ ┃
+ * ┃ ╚═══╗ V ┃┃ V ┃
+ * ┃ ║ ┌─────────────┐ ┃
+ * ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━║━━━━━━━│ ESTABLISHED │━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
+ * ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━║━━━━━━━└─────────────┘━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
+ * ┃ ║ V ┃┃ V ┃
+ * ┃ ╠═══════════╝ ┃┃ ╚═══════════╗ ┃
+ * ┃ (CMD_DISCON) ┃┃ ║ ┃
+ * ┃ ┌┈┈┈<(send FIN)>┈┈┈┈┈┈┐┃┃ ║ ┃
+ * ┃ ┊ V └┃┃┈┈┈┈┈┈┈┈>(recv FIN) ┃
+ * ┃ ┊ ┌────────────┐ ┌┃┃┈┈┈┈┈┈┈┈<(send ACK) ┃
+ * ┃ ┊ │ FIN_WAIT_1 │ ┊┃┃ V ┃
+ * ┃ ┊ └────────────┘ ┊┃┃ ┌────────────┐ ┃
+ * ┃ ┊ V V ┊┃┃ │ CLOSE_WAIT │ ┃
+ * ┃ ╔════════════════╝ ╔══╝ ┊┃┃ └────────────┘ ┃
+ * ┃ (recv FIN)<┈┈┈┈┤ ║ ┊┃┃ V ┃
+ * ┃ ┌┈┈<(send ACK)>┈┈┐ ┊ ║ ┊┃┃ ║ ┃
+ * ┃ ┊ ║ └┈┈┈┈┈>(recv ACK)<┈┈┈┈┈┈┘┃┃ ║ ┃
+ * ┃ ┊ V ┊ V ┃┃ ║ ┃
+ * ┃ ┊ ┌─────────┐ ┊ ┌────────────┐ ┃┃ ║ ┃
+ * ┃ ┊ │ CLOSING │ ┊ │ FIN_WAIT_2 │ ┃┃ ║ ┃
+ * ┃ ┊ └─────────┘ ┊ └────────────┘ ┃┃ (CMD_DISCON) ┃
+ * ┃ ┊ V ┊ V ┌┃┃┈┈┈┈┈┈┈┈<(send FIN) ┃
+ * ┃ ┊ ║ └┈┈┈>(recv FIN)<┈┈┈┈┈┈┘┃┃ ║ ┃
+ * ┃ ┊ ║ ┌┈┈┈┈┈<(send ACK)>┈┈┈┈┈┈┐┃┃ V ┃
+ * ┃ └┈┈>(recv ACK)<┈┈┘ ║ ┊┃┃ ┌──────────┐ ┃
+ * ┃ ╚════════════════╗ ╚═╗ ┊┃┃ │ LAST_ACK │ ┃
+ * ┃ `------, ,-------' V V ┊┃┃ └──────────┘ ┃
+ * ┃ \/ ┌───────────┐ ┊┃┃ V ┃
+ * ┃ Both sides sent │ TIME_WAIT │ ┊┃┃ ║ ┃
+ * ┃ FIN at the "same" └───────────┘ └┃┃┈┈┈┈┈┈┈┈>(recv ACK) ┃
+ * ┃ time; both are V ┃┃ ║ ┃
+ * ┃ active closers (2*MSL has elapsed) ┃┃ ║ ┃
+ * ┃ ╚═══════════╗ ┃┃ ╔══════════╝ ┃
+ * ┣━━━━━━━━━━━━━━━━┓ V ┃┃ V ┏━━━━━━━━━━━━━━━━┫
+ * ┃ active closer ┃ ┌────────┐ ┃ passive closer ┃
+ * ┗━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━│ CLOSED │━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━┛
*/
-#define _STATUS_TCP_FIN_WAIT ((uint8_t)0x18) /* during active close */
-#define _STATUS_TCP_CLOSING ((uint8_t)0x1a) /* during active close */
-#define _STATUS_TCP_TIME_WAIT ((uint8_t)0x1b) /* during active close */
-#define STATUS_TCP_CLOSE_WAIT ((uint8_t)0x1c) /* during passive close */
-#define _STATUS_TCP_LAST_ACK ((uint8_t)0x1d) /* during passive close */
+#define STATE_TCP_INIT ((uint8_t)0x13)
+#define STATE_TCP_LISTEN ((uint8_t)0x14) /* server */
+#define STATE_TCP_SYNSENT ((uint8_t)0x15) /* client; during dial */
+#define STATE_TCP_SYNRECV ((uint8_t)0x16) /* server; during accept */
+#define STATE_TCP_ESTABLISHED ((uint8_t)0x17)
+#define STATE_TCP_FIN_WAIT ((uint8_t)0x18) /* during active close */
+#define STATE_TCP_CLOSING ((uint8_t)0x1a) /* during active close */
+#define STATE_TCP_TIME_WAIT ((uint8_t)0x1b) /* during active close */
+#define STATE_TCP_CLOSE_WAIT ((uint8_t)0x1c) /* during passive close */
+#define STATE_TCP_LAST_ACK ((uint8_t)0x1d) /* during passive close */
-#define STATUS_UDP ((uint8_t)0x22)
+#define STATE_UDP ((uint8_t)0x22)
-#define STATUS_MACRAW ((uint8_t)0x42)
+#define STATE_MACRAW ((uint8_t)0x42)
#define REGWRITE_COMMON(spidev, field, val) do { \
assert(sizeof(val) == sizeof((struct w5500_block_common_reg).field)); \
@@ -401,7 +419,7 @@ struct libnet_listener *w5500_listen(struct w5500 *chip, uint8_t socknum, uint16
REGWRITE_SOCK(chip->spidev, socknum, command, CMD_OPEN);
while (REGREAD_SOCK(chip->spidev, socknum, command, uint8_t) != 0x00)
cr_yield();
- while (REGREAD_SOCK(spidev, socknum, status, uint8_t) != STATUS_TCP_INIT)
+ while (REGREAD_SOCK(spidev, socknum, state, uint8_t) != STATE_TCP_INIT)
cr_yield();
return (struct libnet_listener *)&chip->_listeners[socknum];
@@ -425,10 +443,10 @@ static struct libnet_conn *w5500_accept(struct libnet_listener *_self) {
while (REGREAD_SOCK(chip->spidev, socknum, command, uint8_t) != 0x00)
cr_yield();
for (;;) {
- uint8_t mode = REGREAD_SOCK(spidev, socknum, status, uint8_t);
+ uint8_t mode = REGREAD_SOCK(spidev, socknum, state, uint8_t);
switch (mode) {
- case STATUS_TCP_LISTEN:
- case _STATUS_TCP_SYNRECV:
+ case STATE_TCP_LISTEN:
+ case STATE_TCP_SYNRECV:
cr_yield();
break;
default:
@@ -464,7 +482,7 @@ static int w5500_close(struct libnet_conn *_self, bool rd, bool wr) {
while (REGREAD_SOCK(chip->spidev, socknum, command, uint8_t) != 0x00)
cr_yield();
REGWRITE_SOCK(chip->spidev, socknum, interrupt, (uint8_t)0xff);
- while (REGREAD_SOCK(chip->spidev, socknum, status, uint8_t) != STATUS_CLOSED)
+ while (REGREAD_SOCK(chip->spidev, socknum, state, uint8_t) != STATE_CLOSED)
cr_yield();
return 0;