summaryrefslogtreecommitdiff
path: root/usrp2/firmware/lib
diff options
context:
space:
mode:
authoreb2009-03-18 20:00:41 +0000
committereb2009-03-18 20:00:41 +0000
commit545f3de12e535862a2fca41186ba5d9888cd0e2c (patch)
tree223c864e0d896815d5e56be1d29e059c187f79fd /usrp2/firmware/lib
parent8760688849a4faf902de90d6d28335a1edbfcc03 (diff)
downloadgnuradio-545f3de12e535862a2fca41186ba5d9888cd0e2c.tar.gz
gnuradio-545f3de12e535862a2fca41186ba5d9888cd0e2c.tar.bz2
gnuradio-545f3de12e535862a2fca41186ba5d9888cd0e2c.zip
Fixed ticket:339 (ethernet capability advertisement). We now
advertise that we only handle 1000BASE-T, and that we want to send PAUSE frames, but not receive them. The flow control resolution is currently printed out on the serial port when the link comes up. When we get what we want, it says "ethernet flow control: WE_TX". If it says "ethernet flow control: NONE" unthrottled transmission (e.g., usrp2_siggen.py) will be hosed. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@10634 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'usrp2/firmware/lib')
-rw-r--r--usrp2/firmware/lib/ethernet.c63
-rw-r--r--usrp2/firmware/lib/ethernet.h7
2 files changed, 68 insertions, 2 deletions
diff --git a/usrp2/firmware/lib/ethernet.c b/usrp2/firmware/lib/ethernet.c
index 0e2f46167..d19287044 100644
--- a/usrp2/firmware/lib/ethernet.c
+++ b/usrp2/firmware/lib/ethernet.c
@@ -86,6 +86,36 @@ ed_link_speed_change(int speed)
ed_link_up(speed);
}
+static void
+print_flow_control(int flow_control)
+{
+ static const char *flow_control_msg[4] = {
+ "NONE", "WE_TX", "WE_RX", "SYMMETRIC"
+ };
+ putstr("ethernet flow control: ");
+ puts(flow_control_msg[flow_control & 0x3]);
+}
+
+static void
+check_flow_control_resolution(void)
+{
+ static const unsigned char table[16] = {
+ // index = {local_asm, local_pause, partner_asm, partner_pause}
+ FC_NONE, FC_NONE, FC_NONE, FC_NONE,
+ FC_NONE, FC_SYMM, FC_NONE, FC_SYMM,
+ FC_NONE, FC_NONE, FC_NONE, FC_WE_TX,
+ FC_NONE, FC_SYMM, FC_WE_RX, FC_SYMM
+ };
+
+ int us = eth_mac_miim_read(PHY_AUTONEG_ADV);
+ int lp = eth_mac_miim_read(PHY_LP_ABILITY);
+ int index = (((us >> 10) & 0x3) << 2) | ((lp >> 10) & 0x3);
+ ed_state.flow_control = table[index];
+
+ if (1)
+ print_flow_control(ed_state.flow_control);
+}
+
/*
* Read the PHY state register to determine link state and speed
*/
@@ -123,6 +153,8 @@ ed_check_phy_state(void)
new_speed = S_UNKNOWN;
break;
}
+
+ check_flow_control_resolution();
}
else { // link's down
if (VERBOSE)
@@ -194,9 +226,36 @@ ethernet_init(void)
pic_register_handler(IRQ_PHY, eth_phy_irq_handler);
- // Advertise that we handle PAUSE frames and asymmetric pause direction.
+ // Advertise our flow control configuation.
+ //
+ // We and the link partner each specify two bits in the base page
+ // related to autoconfiguration: NWAY_AR_PAUSE and NWAY_AR_ASM_DIR.
+ // The bits say what a device is "willing" to do, not what may actually
+ // happen as a result of the negotiation. There are 4 cases:
+ //
+ // PAUSE ASM_DIR
+ //
+ // 0 0 I have no flow control capability.
+ //
+ // 1 0 I both assert and respond to flow control.
+ //
+ // 0 1 I assert flow control, but cannot respond. That is,
+ // I want to be able to send PAUSE frames, but will ignore any
+ // you send to me. (This is our configuration.)
+ //
+ // 1 1 I can both assert and respond to flow control AND I am willing
+ // to operate symmetrically OR asymmetrically in EITHER direction.
+ // (We hope the link partner advertises this, otherwise we don't
+ // get what we want.)
+
int t = eth_mac_miim_read(PHY_AUTONEG_ADV);
- eth_mac_miim_write(PHY_AUTONEG_ADV, t | NWAY_AR_PAUSE | NWAY_AR_ASM_DIR);
+ t &= ~(NWAY_AR_PAUSE | NWAY_AR_ASM_DIR);
+ t |= NWAY_AR_ASM_DIR;
+
+ // Say we can't to 10BASE-T or 100BASE-TX, half or full duplex
+ t &= ~(NWAY_AR_10T_HD_CAPS | NWAY_AR_10T_FD_CAPS | NWAY_AR_100TX_HD_CAPS | NWAY_AR_100TX_FD_CAPS);
+
+ eth_mac_miim_write(PHY_AUTONEG_ADV, t);
// Restart autonegotation.
// We want to ensure that we're advertising our PAUSE capabilities.
diff --git a/usrp2/firmware/lib/ethernet.h b/usrp2/firmware/lib/ethernet.h
index 4e5490460..aaed05d44 100644
--- a/usrp2/firmware/lib/ethernet.h
+++ b/usrp2/firmware/lib/ethernet.h
@@ -65,11 +65,18 @@ int ethernet_check_errors(void);
typedef enum { LS_UNKNOWN, LS_DOWN, LS_UP } eth_link_state_t;
+// flow control bitmasks
+#define FC_NONE 0x0
+#define FC_WE_TX 0x1 // we send PAUSE frames
+#define FC_WE_RX 0x2 // we honor received PAUSE frames
+#define FC_SYMM (FC_WE_TX | FC_WE_RX)
+
#define S_UNKNOWN (-1) // unknown link speed
typedef struct {
eth_link_state_t link_state;
int link_speed; // in Mb/s
+ int flow_control;
} ethernet_t;
#endif /* INCLUDED_ETHERNET_H */