diff options
Diffstat (limited to 'libhw/w5500.c')
-rw-r--r-- | libhw/w5500.c | 45 |
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; |