1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
/* hw/w5500.h - libmisc/net.h implementation for the WIZnet W5500 chip
*
* Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-Licence-Identifier: AGPL-3.0-or-later
*/
#ifndef _HW_W5500_H_
#define _HW_W5500_H_
#include <libcr_ipc/sema.h>
#include <libcr_ipc/mutex.h>
#include <libmisc/net.h>
#include "hw/spi.h"
struct _w5500_listener;
struct _w5500_conn {
/* const-after-init */
implements_net_conn;
/* mutable */
bool read_open;
bool write_open;
};
struct _w5500_listener {
/* const-after-init */
implements_net_listener;
uint8_t socknum;
struct _w5500_conn active_conn;
/* mutable */
uint16_t port;
cr_mutex_t cmd_mu;
cr_sema_t listen_sema, read_sema;
};
struct w5500 {
/* const-after-init */
struct spi *spidev;
uint pin_intr;
uint pin_reset;
/* mutable */
uint16_t next_local_port;
struct _w5500_listener listeners[8];
cr_sema_t intr;
};
/**
* Initialize a WIZnet W5500 Ethernet-and-TCP/IP-offload chip.
*
* The W5500 has 3 lines of communication with the MCU:
*
* - An SPI-based RPC protocol:
* + mode: mode 0 or mode 3
* + bit-order: MSB-first
* + clock frequency: 33.3MHz - 80MHz
* - An interrupt pin that it pulls low when an event happens (to let
* the MCU know that it should do an SPI RPC "get" to see what
* happened.)
* - A reset pin that the MCU can pull low to reset the W5500.
*/
#define w5500_init(self, name, spi, pin_intr, pin_reset, eth_addr) do { \
bi_decl(bi_2pins_with_names(pin_intr, name" interrupt", \
pin_reset, name" reset")); \
_w5500_init(self, spi, pin_intr, pin_reset, eth_addr); \
} while (0)
void _w5500_init(struct w5500 *self,
struct spi* spi, uint pin_intr, uint pin_reset,
struct net_eth_addr addr);
/**
* TODO.
*/
void w5500_hard_reset(struct w5500 *self, struct net_eth_addr addr);
/**
* TODO.
*/
void w5500_soft_reset(struct w5500 *self, struct net_eth_addr addr);
struct w5500_netcfg {
struct net_ip4_addr gateway_addr;
struct net_ip4_addr subnet_mask;
struct net_ip4_addr addr;
};
/**
* TODO.
*/
void w5500_netcfg(struct w5500 *self, struct w5500_netcfg cfg);
implements_net_listener *w5500_listen(struct w5500 *self, uint8_t socknum,
uint16_t port);
#endif /* _HW_W5500_H_ */
|