summaryrefslogtreecommitdiff
path: root/libhw/w5500.c
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-03-02 13:30:05 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-03-02 13:30:05 -0700
commit255baf6db201dcdf8da017d55c577622f217a888 (patch)
tree905a389bc9fdf072cbdf7e9f21b2b936881eb620 /libhw/w5500.c
parent188ac62a0c0f5519f5d45519fa7d224cb25305c6 (diff)
parent5a84ba2361cecade0343b88f696b6a63454cc3c6 (diff)
Merge branch 'lukeshu/iov'
Diffstat (limited to 'libhw/w5500.c')
-rw-r--r--libhw/w5500.c57
1 files changed, 44 insertions, 13 deletions
diff --git a/libhw/w5500.c b/libhw/w5500.c
index a8777db..64b373b 100644
--- a/libhw/w5500.c
+++ b/libhw/w5500.c
@@ -125,9 +125,19 @@ static const char *w5500_state_str(uint8_t state) {
/* libobj *********************************************************************/
+LO_IMPLEMENTATION_C(io_closer, struct _w5500_socket, w5500_tcplist, static)
LO_IMPLEMENTATION_C(net_stream_listener, struct _w5500_socket, w5500_tcplist, static)
+
+LO_IMPLEMENTATION_C(io_reader, struct _w5500_socket, w5500_tcp, static)
+LO_IMPLEMENTATION_C(io_writer, struct _w5500_socket, w5500_tcp, static)
+LO_IMPLEMENTATION_C(io_readwriter, struct _w5500_socket, w5500_tcp, static)
+LO_IMPLEMENTATION_C(io_closer, struct _w5500_socket, w5500_tcp, static)
+LO_IMPLEMENTATION_C(io_bidi_closer, struct _w5500_socket, w5500_tcp, static)
LO_IMPLEMENTATION_C(net_stream_conn, struct _w5500_socket, w5500_tcp, static)
+
+LO_IMPLEMENTATION_C(io_closer, struct _w5500_socket, w5500_udp, static)
LO_IMPLEMENTATION_C(net_packet_conn, struct _w5500_socket, w5500_udp, static)
+
LO_IMPLEMENTATION_C(net_iface, struct w5500, w5500_if, static)
/* mid-level utilities ********************************************************/
@@ -586,10 +596,14 @@ static int w5500_tcplist_close(struct _w5500_socket *socket) {
/* tcp_conn methods ***********************************************************/
-static ssize_t w5500_tcp_write(struct _w5500_socket *socket, void *buf, size_t count) {
+static ssize_t w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec *iov, int iovcnt) {
+ assert(iov);
+ assert(iovcnt > 0);
+ size_t count = 0;
+ for (int i = 0; i < iovcnt; i++)
+ count += iov[i].iov_len;
debugf("tcp_conn.write(%zu)", count);
ASSERT_SELF(stream_conn, TCP);
- assert(count == 0 || buf);
if (count == 0)
return 0;
@@ -639,7 +653,7 @@ static ssize_t w5500_tcp_write(struct _w5500_socket *socket, void *buf, size_t c
if ((size_t)freesize > count-done)
freesize = count-done;
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_writev(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, TX), iov, iovcnt, done, freesize);
w5500ll_write_sock_reg(chip->spidev, socknum, tx_write_pointer, uint16be_marshal(ptr+freesize));
/* Submit the queue. */
@@ -675,10 +689,14 @@ static void w5500_tcp_alarm_handler(void *_arg) {
cr_sema_signal_from_intrhandler(&socket->read_sema);
}
-static ssize_t w5500_tcp_read(struct _w5500_socket *socket, void *buf, size_t count) {
- debugf("tcp_conn.read()");
+static ssize_t w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec *iov, int iovcnt) {
+ assert(iov);
+ assert(iovcnt > 0);
+ size_t count = 0;
+ for (int i = 0; i < iovcnt; i++)
+ count += iov[i].iov_len;
+ debugf("tcp_conn.read(%zu)", count);
ASSERT_SELF(stream_conn, TCP);
- assert(count == 0 || buf);
if (count == 0)
return 0;
@@ -736,7 +754,7 @@ static ssize_t w5500_tcp_read(struct _w5500_socket *socket, void *buf, size_t co
/* Read the data. */
if ((size_t)avail > count)
avail = count;
- w5500ll_read(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, RX), buf, avail);
+ w5500ll_readv(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, RX), iov, iovcnt, avail);
/* Tell the chip that we read the data. */
w5500ll_write_sock_reg(chip->spidev, socknum, rx_read_pointer, uint16be_marshal(ptr+avail));
w5500_socket_cmd(socket, CMD_RECV);
@@ -746,7 +764,7 @@ static ssize_t w5500_tcp_read(struct _w5500_socket *socket, void *buf, size_t co
return avail;
}
-static int w5500_tcp_close(struct _w5500_socket *socket, bool rd, bool wr) {
+static int w5500_tcp_close_inner(struct _w5500_socket *socket, bool rd, bool wr) {
debugf("tcp_conn.close(rd=%s, wr=%s)", rd ? "true" : "false", wr ? "true" : "false");
ASSERT_SELF(stream_conn, TCP);
@@ -777,6 +795,10 @@ static int w5500_tcp_close(struct _w5500_socket *socket, bool rd, bool wr) {
return 0;
}
+static int w5500_tcp_close(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, true, true); }
+static int w5500_tcp_close_read(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, true, false); }
+static int w5500_tcp_close_write(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, false, true); }
+
/* udp_conn methods ***********************************************************/
static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t count,
@@ -816,7 +838,10 @@ static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t
w5500ll_write_sock_reg(chip->spidev, socknum, remote_port, uint16be_marshal(port));
/* Queue data to be sent. */
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), buf, count);
+ w5500ll_writev(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, TX), &((struct iovec){
+ .iov_base = buf,
+ .iov_len = count,
+ }), 1, 0, 0);
w5500ll_write_sock_reg(chip->spidev, socknum, tx_write_pointer, uint16be_marshal(ptr+count));
/* Submit the queue. */
w5500_socket_cmd(socket, CMD_SEND);
@@ -836,8 +861,8 @@ static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t
}
}
-static void w5500_udp_set_read_deadline(struct _w5500_socket *socket, uint64_t ns) {
- debugf("udp_conn.set_read_deadline(%"PRIu64")", ns);
+static void w5500_udp_set_recv_deadline(struct _w5500_socket *socket, uint64_t ns) {
+ debugf("udp_conn.set_recv_deadline(%"PRIu64")", ns);
ASSERT_SELF(packet_conn, UDP);
socket->read_deadline_ns = ns;
}
@@ -891,7 +916,10 @@ static ssize_t w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_
* can't find in the datasheet where it describes
* this; this is based off of socket.c:recvfrom(). */
uint8_t hdr[8];
- w5500ll_read(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, RX), hdr, sizeof(hdr));
+ w5500ll_readv(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, RX), &((struct iovec){
+ .iov_base = hdr,
+ .iov_len = sizeof(hdr),
+ }), 1, 0);
if (ret_node) {
ret_node->octets[0] = hdr[0];
ret_node->octets[1] = hdr[1];
@@ -905,7 +933,10 @@ static ssize_t w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_
/* Now read the actual data. */
if (count > len)
count = len;
- w5500ll_read(chip->spidev, ptr+8, CTL_BLOCK_SOCK(socknum, RX), buf, len);
+ w5500ll_readv(chip->spidev, ptr+8, CTL_BLOCK_SOCK(socknum, RX), &((struct iovec){
+ .iov_base = buf,
+ .iov_len = len,
+ }), 1, 0);
/* Tell the chip that we read the data. */
w5500ll_write_sock_reg(chip->spidev, socknum, rx_read_pointer, uint16be_marshal(ptr+8+len));
w5500_socket_cmd(socket, CMD_RECV);