summaryrefslogtreecommitdiff
path: root/libhw/w5500.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhw/w5500.c')
-rw-r--r--libhw/w5500.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/libhw/w5500.c b/libhw/w5500.c
index d94a88d..c039226 100644
--- a/libhw/w5500.c
+++ b/libhw/w5500.c
@@ -221,18 +221,18 @@ static COROUTINE w5500_irq_cr(void *_chip) {
switch (socket->mode) {
case W5500_MODE_NONE:
break;
- case W5500_MODE_TCP:
- /* SOCKINTR_SEND_OK is useless; just count on the write methods to
- * poll instead of waiting on notification from here. */
- uint8_t listen_bits = sockintr & (SOCKINTR_TIMEOUT|SOCKINTR_CONN),
- read_bits = sockintr & (SOCKINTR_TIMEOUT|SOCKINTR_RECV|SOCKINTR_FIN);
+ case W5500_MODE_TCP: case W5500_MODE_UDP:
+ uint8_t listen_bits = sockintr & SOCKINTR_CONN,
+ send_bits = sockintr & (SOCKINTR_SEND_OK|SOCKINTR_SEND_TIMEOUT),
+ recv_bits = sockintr & (SOCKINTR_RECV_DAT|SOCKINTR_RECV_FIN);
if (listen_bits)
cr_sema_signal(&socket->listen_sema);
- /* fallthrough */
- case W5500_MODE_UDP:
- if (read_bits)
+ if (recv_bits)
cr_sema_signal(&socket->read_sema);
+ if (send_bits)
+ _w5500_sockintr_ch_send(&socket->write_ch, send_bits);
+ break;
}
w5500ll_write_sock_reg(chip->spidev, socknum, interrupt, sockintr);
@@ -630,7 +630,17 @@ static ssize_t w5500_tcp_write(implements_net_stream_conn *_socket, void *buf, s
/* Submit the queue. */
w5500_socket_cmd(socket, CMD_SEND);
- done += freesize;
+ switch (_w5500_sockintr_ch_recv(&socket->write_ch)) {
+ case SOCKINTR_SEND_OK:
+ done += freesize;
+ break;
+ case SOCKINTR_SEND_TIMEOUT:
+ return -NET_EACK_TIMEOUT;
+ case SOCKINTR_SEND_OK|SOCKINTR_SEND_TIMEOUT:
+ assert_notreached("send both OK and timed out?");
+ default:
+ assert_notreached("invalid write_ch bits");
+ }
}
return done;
}
@@ -666,7 +676,7 @@ static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, si
}
if (socket->read_deadline_ns && socket->read_deadline_ns <= VCALL(bootclock, get_time_ns)) {
VCALL(bootclock, del_trigger, &trigger);
- return -NET_ETIMEDOUT;
+ return -NET_ERECV_TIMEOUT;
}
uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state);
switch (state) {
@@ -768,7 +778,16 @@ static ssize_t w5500_udp_sendto(implements_net_packet_conn *_socket, void *buf,
/* Submit the queue. */
w5500_socket_cmd(socket, CMD_SEND);
- return count;
+ switch (_w5500_sockintr_ch_recv(&socket->write_ch)) {
+ case SOCKINTR_SEND_OK:
+ return count;
+ case SOCKINTR_SEND_TIMEOUT:
+ return -NET_EARP_TIMEOUT;
+ case SOCKINTR_SEND_OK|SOCKINTR_SEND_TIMEOUT:
+ assert_notreached("send both OK and timed out?");
+ default:
+ assert_notreached("invalid write_ch bits");
+ }
}
static void w5500_udp_set_read_deadline(implements_net_packet_conn *_socket, uint64_t ns) {
@@ -799,7 +818,7 @@ static ssize_t w5500_udp_recvfrom(implements_net_packet_conn *_socket, void *buf
for (;;) {
if (socket->read_deadline_ns && socket->read_deadline_ns <= VCALL(bootclock, get_time_ns)) {
VCALL(bootclock, del_trigger, &trigger);
- return -NET_ETIMEDOUT;
+ return -NET_ERECV_TIMEOUT;
}
uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state);
if (state != STATE_UDP) {
@@ -807,7 +826,7 @@ static ssize_t w5500_udp_recvfrom(implements_net_packet_conn *_socket, void *buf
return -NET_ECLOSED;
}
- uint16_t avail = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, rx_size));
+ avail = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, rx_size));
if (avail)
/* We have data to read. */
break;