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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
use core::option::Option;
use stm32f4xx_hal::stm32::ethernet_mac::{MACMIIAR, MACMIIDR};
use crate::smi::SMI;
#[allow(dead_code)]
mod consts {
pub const PHY_REG_BCR: u8 = 0x00;
pub const PHY_REG_BSR: u8 = 0x01;
pub const PHY_REG_ID1: u8 = 0x02;
pub const PHY_REG_ID2: u8 = 0x03;
pub const PHY_REG_ANTX: u8 = 0x04;
pub const PHY_REG_ANRX: u8 = 0x05;
pub const PHY_REG_ANEXP: u8 = 0x06;
pub const PHY_REG_ANNPTX: u8 = 0x07;
pub const PHY_REG_ANNPRX: u8 = 0x08;
pub const PHY_REG_SSR: u8 = 0x1F;
pub const PHY_REG_BCR_COLTEST: u16 = 1 << 7;
pub const PHY_REG_BCR_FD: u16 = 1 << 8;
pub const PHY_REG_BCR_ANRST: u16 = 1 << 9;
pub const PHY_REG_BCR_ISOLATE: u16 = 1 << 10;
pub const PHY_REG_BCR_POWERDN: u16 = 1 << 11;
pub const PHY_REG_BCR_AN: u16 = 1 << 12;
pub const PHY_REG_BCR_100M: u16 = 1 << 13;
pub const PHY_REG_BCR_LOOPBACK: u16 = 1 << 14;
pub const PHY_REG_BCR_RESET: u16 = 1 << 15;
pub const PHY_REG_BSR_JABBER: u16 = 1 << 1;
pub const PHY_REG_BSR_UP: u16 = 1 << 2;
pub const PHY_REG_BSR_FAULT: u16 = 1 << 4;
pub const PHY_REG_BSR_ANDONE: u16 = 1 << 5;
pub const PHY_REG_SSR_ANDONE: u16 = 1 << 12;
pub const PHY_REG_SSR_SPEED: u16 = 0b111 << 2;
pub const PHY_REG_SSR_10BASE_HD: u16 = 0b001 << 2;
pub const PHY_REG_SSR_10BASE_FD: u16 = 0b101 << 2;
pub const PHY_REG_SSR_100BASE_HD: u16 = 0b010 << 2;
pub const PHY_REG_SSR_100BASE_FD: u16 = 0b110 << 2;
}
use self::consts::*;
pub struct Phy<'a> {
smi: SMI<'a>,
phy: u8,
}
impl<'a> Phy<'a> {
pub fn new(macmiiar: &'a MACMIIAR, macmiidr: &'a MACMIIDR, phy: u8) -> Self {
let smi = SMI::new(macmiiar, macmiidr);
Phy {
smi,
phy,
}
}
pub fn status(&self) -> PhyStatus {
PhyStatus {
bsr: self.smi.read(self.phy, PHY_REG_BSR),
ssr: self.smi.read(self.phy, PHY_REG_SSR),
}
}
pub fn reset(&self) -> &Self {
self.smi.set_bits(
self.phy,
PHY_REG_BCR,
PHY_REG_BCR_RESET
);
while (self.smi.read(
self.phy,
PHY_REG_BCR
) & PHY_REG_BCR_RESET) == PHY_REG_BCR_RESET {}
self
}
pub fn set_autoneg(&self) -> &Self {
self.smi.set_bits(
self.phy,
PHY_REG_BCR,
PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M
);
self
}
}
#[derive(Copy, Clone)]
pub struct PhyStatus {
bsr: u16,
ssr: u16,
}
impl PhyStatus {
pub fn link_detected(&self) -> bool {
(self.bsr & PHY_REG_BSR_UP) == PHY_REG_BSR_UP
}
pub fn autoneg_done(&self) -> bool {
(self.bsr & PHY_REG_BSR_ANDONE) == PHY_REG_BSR_ANDONE ||
(self.ssr & PHY_REG_SSR_ANDONE) == PHY_REG_SSR_ANDONE
}
pub fn is_full_duplex(&self) -> Option<bool> {
match self.ssr & PHY_REG_SSR_SPEED {
PHY_REG_SSR_10BASE_HD |
PHY_REG_SSR_100BASE_HD =>
Some(false),
PHY_REG_SSR_10BASE_FD |
PHY_REG_SSR_100BASE_FD =>
Some(true),
_ =>
None,
}
}
pub fn speed(&self) -> u32 {
match self.ssr & PHY_REG_SSR_SPEED {
PHY_REG_SSR_10BASE_HD |
PHY_REG_SSR_10BASE_FD =>
10,
PHY_REG_SSR_100BASE_HD |
PHY_REG_SSR_100BASE_FD =>
100,
_ =>
0,
}
}
pub fn remote_fault(&self) -> bool {
(self.bsr & PHY_REG_BSR_FAULT) == PHY_REG_BSR_FAULT
}
}
impl PartialEq for PhyStatus {
fn eq(&self, other: &PhyStatus) -> bool {
(self.link_detected() == false &&
other.link_detected() == false)
||
(self.link_detected() == other.link_detected() &&
self.is_full_duplex() == other.is_full_duplex() &&
self.speed() == other.speed())
}
}