summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/sbc_harness/hw/w5500.c16
-rw-r--r--cmd/sbc_harness/hw/w5500_ll.h53
-rw-r--r--libmisc/include/libmisc/endian.h129
3 files changed, 156 insertions, 42 deletions
diff --git a/cmd/sbc_harness/hw/w5500.c b/cmd/sbc_harness/hw/w5500.c
index b868eaa..b95ad88 100644
--- a/cmd/sbc_harness/hw/w5500.c
+++ b/cmd/sbc_harness/hw/w5500.c
@@ -229,7 +229,7 @@ static inline void w5500_post_reset(struct w5500 *chip, struct net_eth_addr addr
* The hysteresis is (intlevel+1)*4/(150MHz) (if intlevel is
* non-zero), or (intlevel+1)*26.7ns; so even the shortest-possible
* hysteresis much larger than necessary for us. */
- w5500ll_write_common_reg(chip->spidev, intlevel, encode_u16be(1));
+ w5500ll_write_common_reg(chip->spidev, intlevel, uint16be_marshal(1));
/* This implementation does not care about any of the chip-level
* interrupts. */
@@ -328,7 +328,7 @@ static implements_net_conn *w5500_accept(implements_net_listener *_self) {
/* Mimics socket.c:socket(). */
w5500_listener_cmd_close(self);
w5500ll_write_sock_reg(chip->spidev, socknum, mode, SOCKMODE_TCP);
- w5500ll_write_sock_reg(chip->spidev, socknum, local_port, encode_u16be(self->port));
+ w5500ll_write_sock_reg(chip->spidev, socknum, local_port, uint16be_marshal(self->port));
w5500_listener_cmd(self, CMD_OPEN);
while (w5500ll_read_sock_reg(chip->spidev, socknum, state) != STATE_TCP_INIT)
cr_yield();
@@ -403,7 +403,7 @@ static ssize_t w5500_write(implements_net_conn *_self, void *buf, size_t count)
if (state != STATE_TCP_ESTABLISHED && state != STATE_TCP_CLOSE_WAIT)
return -1;
- uint16_t freesize = decode_u16be(w5500ll_read_sock_reg(chip->spidev, socknum, tx_free_size));
+ uint16_t freesize = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, tx_free_size));
if (freesize < count-done && freesize < min_free_space) {
/* Wait for more buffer space. */
cr_yield();
@@ -411,9 +411,9 @@ static ssize_t w5500_write(implements_net_conn *_self, void *buf, size_t count)
}
/* Queue data to be sent. */
- uint16_t ptr = decode_u16be(w5500ll_read_sock_reg(chip->spidev, socknum, tx_write_pointer));
+ uint16_t ptr = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, tx_write_pointer));
w5500ll_write(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, TX), &((char *)buf)[done], freesize);
- w5500ll_write_sock_reg(chip->spidev, socknum, tx_write_pointer, encode_u16be(ptr+freesize));
+ w5500ll_write_sock_reg(chip->spidev, socknum, tx_write_pointer, uint16be_marshal(ptr+freesize));
/* Submit the queue. */
w5500_listener_cmd(listener, CMD_SEND);
@@ -441,16 +441,16 @@ static ssize_t w5500_read(implements_net_conn *_self, void *buf, size_t count) {
return -1;
}
- uint16_t avail = decode_u16be(w5500ll_read_sock_reg(chip->spidev, socknum, rx_size));
+ uint16_t avail = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, rx_size));
if (!avail) {
cr_sema_wait(&listener->read_sema);
continue;
}
if ((size_t)avail > count)
avail = count;
- uint16_t ptr = decode_u16be(w5500ll_read_sock_reg(chip->spidev, socknum, rx_read_pointer));
+ uint16_t ptr = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, rx_read_pointer));
w5500ll_read(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, RX), &((char *)buf)[done], avail);
- w5500ll_write_sock_reg(chip->spidev, socknum, rx_read_pointer, encode_u16be(ptr+avail));
+ w5500ll_write_sock_reg(chip->spidev, socknum, rx_read_pointer, uint16be_marshal(ptr+avail));
w5500_listener_cmd(listener, CMD_RECV);
done += avail;
diff --git a/cmd/sbc_harness/hw/w5500_ll.h b/cmd/sbc_harness/hw/w5500_ll.h
index b0a023a..7c57ce8 100644
--- a/cmd/sbc_harness/hw/w5500_ll.h
+++ b/cmd/sbc_harness/hw/w5500_ll.h
@@ -14,26 +14,11 @@
#include <stdint.h> /* for uint{n}_t */
#include <string.h> /* for memcmp() */
-#include <libmisc/net.h> /* for struct net_eth_addr, struct net_ip4_addr */
-#include <libmisc/vcall.h> /* for VCALL() */
-#include "hw/spi.h" /* for implements_spi */
+#include <libmisc/net.h> /* for struct net_eth_addr, struct net_ip4_addr */
+#include <libmisc/vcall.h> /* for VCALL() */
+#include <libmisc/endian.h> /* for uint16be_t */
+#include "hw/spi.h" /* for implements_spi */
-/* uint16 utilities. *********************************************************/
-
-struct uint16_be {
- uint8_t octets[2];
-};
-
-static inline struct uint16_be encode_u16be(uint16_t x) {
- struct uint16_be ret;
- ret.octets[0] = (uint8_t)(x>>8);
- ret.octets[1] = (uint8_t)x;
- return ret;
-}
-
-static inline uint16_t decode_u16be(struct uint16_be x) {
- return ((uint16_t)x.octets[0])<<8 | x.octets[1];
-}
/* Low-level protocol built on SPI frames. ***********************************/
@@ -110,24 +95,24 @@ struct w5500ll_block_common_reg {
struct net_eth_addr eth_addr; /* SHAR0 ... SHAR5 */
struct net_ip4_addr ip_addr; /* SIPR0 ... SIPR3 */
- struct uint16_be intlevel; /* INTLEVEL0, INTLEVEL1; if non-zero,
+ uint16be_t intlevel; /* INTLEVEL0, INTLEVEL1; if non-zero,
* hysteresis between pin_intr being pulled
* low (hysteresis=(intlevel+1)*4/(150MHz)) */
uint8_t chip_interrupt; /* IR; bitfield, see CHIPINTR_{x} below */
uint8_t chip_interrupt_mask; /* IMR; bitfield, see CHIPINTR_{x} below, 0=disable, 1=enable */
uint8_t sock_interrupt; /* SIR; bitfield of which sockets have their .interrupt set */
uint8_t sock_interrupt_mask; /* SIMR; bitfield of sockets, 0=disable, 1=enable */
- struct uint16_be retry_time; /* RTR0, RTR0; configures re-transmission period, in units of 100µs */
+ uint16be_t retry_time; /* RTR0, RTR0; configures re-transmission period, in units of 100µs */
uint8_t retry_count; /* RCR; configures max re-transmission count */
uint8_t ppp_lcp_request_timer; /* PTIMER */
uint8_t ppp_lcp_magic_bumber; /* PMAGIC */
struct net_eth_addr ppp_dst_eth_addr; /* PHAR0 ... PHAR5 */
- struct uint16_be ppp_sess_id; /* PSID0 ... PSID1 */
- struct uint16_be ppp_max_seg_size; /* PMRU0 ... PMRU1 */
+ uint16be_t ppp_sess_id; /* PSID0 ... PSID1 */
+ uint16be_t ppp_max_seg_size; /* PMRU0 ... PMRU1 */
struct net_ip4_addr unreachable_ip_addr; /* UIPR0 ... UIPR3 */
- struct uint16_be unreachable_port; /* UPORTR0, UPORTR1 */
+ uint16be_t unreachable_port; /* UPORTR0, UPORTR1 */
uint8_t phy_cfg; /* PHYCFGR */
@@ -176,12 +161,12 @@ struct w5500ll_block_sock_reg {
uint8_t command; /* Sn_CR; see CMD_{x} below */
uint8_t interrupt; /* Sn_IR; bitfield, see SOCKINTR_{x} below */
uint8_t state; /* Sn_SR; see STATE_{x} below */
- struct uint16_be local_port; /* Sn_PORT0, Sn_PORT1 */
+ uint16be_t local_port; /* Sn_PORT0, Sn_PORT1 */
struct net_eth_addr remote_eth_addr; /* Sn_DHAR0 ... SnDHAR5 */
struct net_ip4_addr remote_ip_addr; /* Sn_DIPR0 ... Sn_DIP3 */
- struct uint16_be remote_port; /* Sn_DPORT0 ... Sn_DPORT1 */
+ uint16be_t remote_port; /* Sn_DPORT0 ... Sn_DPORT1 */
- struct uint16_be max_seg_size; /* Sn_MSSR0, Sn_MSSR1 */
+ uint16be_t max_seg_size; /* Sn_MSSR0, Sn_MSSR1 */
uint8_t _reserved0[1];
uint8_t ip_tos; /* Sn_TOS */
uint8_t ip_ttl; /* Sn_TTL */
@@ -189,15 +174,15 @@ struct w5500ll_block_sock_reg {
uint8_t rx_buf_size; /* Sn_RXBUF_SIZE; in KiB, power of 2, <= 16 */
uint8_t tx_buf_size; /* Sn_TXBUF_SIZE; in KiB, power of 2, <= 16 */
- struct uint16_be tx_free_size; /* Sn_TX_FSR0, Sn_TX_FSR1 */
- struct uint16_be tx_read_pointer; /* Sn_TX_RD0, Sn_TX_RD1 */
- struct uint16_be tx_write_pointer; /* Sn_TX_WR0, Sn_TX_WR1 */
- struct uint16_be rx_size; /* Sn_RX_RSR0, Sn_RX_RSR1 */
- struct uint16_be rx_read_pointer; /* Sn_RX_RD0, Sn_RX_RD1 */
- struct uint16_be rx_write_pointer; /* Sn_RX_WR0, Sn_RX_WR1 */
+ uint16be_t tx_free_size; /* Sn_TX_FSR0, Sn_TX_FSR1 */
+ uint16be_t tx_read_pointer; /* Sn_TX_RD0, Sn_TX_RD1 */
+ uint16be_t tx_write_pointer; /* Sn_TX_WR0, Sn_TX_WR1 */
+ uint16be_t rx_size; /* Sn_RX_RSR0, Sn_RX_RSR1 */
+ uint16be_t rx_read_pointer; /* Sn_RX_RD0, Sn_RX_RD1 */
+ uint16be_t rx_write_pointer; /* Sn_RX_WR0, Sn_RX_WR1 */
uint8_t interrupt_mask; /* Sn_IMR */
- struct uint16_be fragment_offset; /* Sn_FRAG0, Sn_FRAG1 */
+ uint16be_t fragment_offset; /* Sn_FRAG0, Sn_FRAG1 */
uint8_t keepalive_timer; /* Sn_KPALVTR */
};
static_assert(sizeof(struct w5500ll_block_sock_reg) == 0x30);
diff --git a/libmisc/include/libmisc/endian.h b/libmisc/include/libmisc/endian.h
new file mode 100644
index 0000000..eaf9bae
--- /dev/null
+++ b/libmisc/include/libmisc/endian.h
@@ -0,0 +1,129 @@
+/* libmisc/endian.h - Endian-conversion helpers
+ *
+ * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-Licence-Identifier: AGPL-3.0-or-later
+ */
+
+#ifndef _LIBMISC_ENDIAN_H_
+#define _LIBMISC_ENDIAN_H_
+
+#include <assert.h>
+#include <stdint.h> /* for uint{n}_t */
+
+/* Big endian *****************************************************************/
+
+typedef struct {
+ uint8_t octets[2];
+} uint16be_t;
+static_assert(sizeof(uint16be_t) == 2);
+
+static inline void uint16be_encode(uint8_t *out, uint16_t in) {
+ out[0] = (uint8_t)((in >> 8) & 0xFF);
+ out[1] = (uint8_t)((in >> 0) & 0xFF);
+}
+
+static inline uint16_t uint16be_decode(uint8_t *in) {
+ return (((uint16_t)(in[0])) << 8)
+ | (((uint16_t)(in[1])) << 0)
+ ;
+}
+
+static inline uint16be_t uint16be_marshal(uint16_t in) {
+ uint16be_t out;
+ uint16be_encode(out.octets, in);
+ return out;
+}
+
+static inline uint16_t uint16be_unmarshal(uint16be_t in) {
+ return uint16be_decode(in.octets);
+}
+
+typedef struct {
+ uint8_t octets[4];
+} uint32be_t;
+static_assert(sizeof(uint32be_t) == 4);
+
+static inline void uint32be_encode(uint8_t *out, uint32_t in) {
+ out[0] = (uint8_t)((in >> 24) & 0xFF);
+ out[1] = (uint8_t)((in >> 16) & 0xFF);
+ out[2] = (uint8_t)((in >> 8) & 0xFF);
+ out[3] = (uint8_t)((in >> 0) & 0xFF);
+}
+
+static inline uint32_t uint32be_decode(uint8_t *in) {
+ return (((uint32_t)(in[0])) << 24)
+ | (((uint32_t)(in[1])) << 16)
+ | (((uint32_t)(in[2])) << 8)
+ | (((uint32_t)(in[3])) << 0)
+ ;
+}
+
+static inline uint32be_t uint32be_marshal(uint32_t in) {
+ uint32be_t out;
+ uint32be_encode(out.octets, in);
+ return out;
+}
+
+static inline uint32_t uint32be_unmarshal(uint32be_t in) {
+ return uint32be_decode(in.octets);
+}
+
+/* Little endian **************************************************************/
+
+typedef struct {
+ uint8_t octets[2];
+} uint16le_t;
+static_assert(sizeof(uint16le_t) == 2);
+
+static inline void uint16le_encode(uint8_t *out, uint16_t in) {
+ out[0] = (uint8_t)((in >> 0) & 0xFF);
+ out[1] = (uint8_t)((in >> 8) & 0xFF);
+}
+
+static inline uint16_t uint16le_decode(uint8_t *in) {
+ return (((uint16_t)(in[0])) << 0)
+ | (((uint16_t)(in[1])) << 8)
+ ;
+}
+
+static inline uint16le_t uint16le_marshal(uint16_t in) {
+ uint16le_t out;
+ uint16le_encode(out.octets, in);
+ return out;
+}
+
+static inline uint16_t uint16le_unmarshal(uint16le_t in) {
+ return uint16le_decode(in.octets);
+}
+
+typedef struct {
+ uint8_t octets[4];
+} uint32le_t;
+static_assert(sizeof(uint32le_t) == 4);
+
+static inline void uint32le_encode(uint8_t *out, uint32_t in) {
+ out[0] = (uint8_t)((in >> 0) & 0xFF);
+ out[1] = (uint8_t)((in >> 8) & 0xFF);
+ out[2] = (uint8_t)((in >> 16) & 0xFF);
+ out[3] = (uint8_t)((in >> 24) & 0xFF);
+}
+
+static inline uint32_t uint32le_decode(uint8_t *in) {
+ return (((uint32_t)(in[0])) << 0)
+ | (((uint32_t)(in[1])) << 8)
+ | (((uint32_t)(in[2])) << 16)
+ | (((uint32_t)(in[3])) << 24)
+ ;
+}
+
+static inline uint32le_t uint32le_marshal(uint32_t in) {
+ uint32le_t out;
+ uint32le_encode(out.octets, in);
+ return out;
+}
+
+static inline uint32_t uint32le_unmarshal(uint32le_t in) {
+ return uint32le_decode(in.octets);
+}
+
+#endif /* _LIBMISC_ENDIAN_H_ */