mirror of
https://github.com/saymrwulf/uhd.git
synced 2026-05-14 20:58:09 +00:00
This pulls out a lot of code from x300_impl and puts it into its own compilation units: - EEPROM code goes to x300_mb_eeprom.* - Claim code goes to x300_claim.* - PCIe code goes to uhd::usrp::x300::pcie_manager - Ethernet code goes to uhd::usrp::x300::eth_manager
201 lines
7.4 KiB
C++
201 lines
7.4 KiB
C++
//
|
|
// Copyright 2017-18 Ettus Research (National Instruments Corp.)
|
|
//
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
//
|
|
|
|
#include "x300_mb_eeprom.hpp"
|
|
#include <uhd/types/serial.hpp>
|
|
#include <uhd/usrp/mboard_eeprom.hpp>
|
|
#include <uhdlib/utils/eeprom_utils.hpp>
|
|
|
|
namespace {
|
|
const uint8_t X300_EEPROM_ADDR = 0x50;
|
|
|
|
struct x300_eeprom_map
|
|
{
|
|
// identifying numbers
|
|
unsigned char revision[2];
|
|
unsigned char product[2];
|
|
unsigned char revision_compat[2];
|
|
uint8_t _pad0[2];
|
|
|
|
// all the mac addrs
|
|
uint8_t mac_addr0[6];
|
|
uint8_t _pad1[2];
|
|
uint8_t mac_addr1[6];
|
|
uint8_t _pad2[2];
|
|
|
|
// all the IP addrs
|
|
uint32_t gateway;
|
|
uint32_t subnet[4];
|
|
uint32_t ip_addr[4];
|
|
uint8_t _pad3[16];
|
|
|
|
// names and serials
|
|
unsigned char name[NAME_MAX_LEN];
|
|
unsigned char serial[SERIAL_LEN];
|
|
};
|
|
} // namespace
|
|
|
|
using namespace uhd;
|
|
using uhd::usrp::mboard_eeprom_t;
|
|
|
|
mboard_eeprom_t uhd::usrp::x300::get_mb_eeprom(uhd::i2c_iface::sptr iface)
|
|
{
|
|
byte_vector_t bytes =
|
|
iface->read_eeprom(X300_EEPROM_ADDR, 0, sizeof(struct x300_eeprom_map));
|
|
|
|
mboard_eeprom_t mb_eeprom;
|
|
if (bytes.empty()) {
|
|
return mb_eeprom;
|
|
}
|
|
|
|
// extract the revision number
|
|
mb_eeprom["revision"] = uint16_bytes_to_string(
|
|
byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, revision),
|
|
bytes.begin() + (offsetof(x300_eeprom_map, revision) + 2)));
|
|
|
|
// extract the revision compat number
|
|
mb_eeprom["revision_compat"] = uint16_bytes_to_string(
|
|
byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, revision_compat),
|
|
bytes.begin() + (offsetof(x300_eeprom_map, revision_compat) + 2)));
|
|
|
|
// extract the product code
|
|
mb_eeprom["product"] = uint16_bytes_to_string(
|
|
byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, product),
|
|
bytes.begin() + (offsetof(x300_eeprom_map, product) + 2)));
|
|
|
|
// extract the mac addresses
|
|
mb_eeprom["mac-addr0"] = mac_addr_t::from_bytes(
|
|
byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, mac_addr0),
|
|
bytes.begin() + (offsetof(x300_eeprom_map, mac_addr0) + 6)))
|
|
.to_string();
|
|
mb_eeprom["mac-addr1"] = mac_addr_t::from_bytes(
|
|
byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, mac_addr1),
|
|
bytes.begin() + (offsetof(x300_eeprom_map, mac_addr1) + 6)))
|
|
.to_string();
|
|
|
|
// extract the ip addresses
|
|
boost::asio::ip::address_v4::bytes_type ip_addr_bytes;
|
|
byte_copy(byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, gateway),
|
|
bytes.begin() + (offsetof(x300_eeprom_map, gateway) + 4)),
|
|
ip_addr_bytes);
|
|
mb_eeprom["gateway"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
|
|
for (size_t i = 0; i < 4; i++) {
|
|
const std::string n(1, char(i) + '0');
|
|
byte_copy(
|
|
byte_vector_t(bytes.begin() + (offsetof(x300_eeprom_map, ip_addr) + (i * 4)),
|
|
bytes.begin() + (offsetof(x300_eeprom_map, ip_addr) + (i * 4) + 4)),
|
|
ip_addr_bytes);
|
|
mb_eeprom["ip-addr" + n] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
|
|
|
|
byte_copy(
|
|
byte_vector_t(bytes.begin() + (offsetof(x300_eeprom_map, subnet) + (i * 4)),
|
|
bytes.begin() + (offsetof(x300_eeprom_map, subnet) + (i * 4) + 4)),
|
|
ip_addr_bytes);
|
|
mb_eeprom["subnet" + n] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
|
|
}
|
|
|
|
// extract the serial
|
|
mb_eeprom["serial"] =
|
|
bytes_to_string(byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, serial),
|
|
bytes.begin() + (offsetof(x300_eeprom_map, serial) + SERIAL_LEN)));
|
|
|
|
// extract the name
|
|
mb_eeprom["name"] =
|
|
bytes_to_string(byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, name),
|
|
bytes.begin() + (offsetof(x300_eeprom_map, name) + NAME_MAX_LEN)));
|
|
|
|
return mb_eeprom;
|
|
}
|
|
|
|
void uhd::usrp::x300::set_mb_eeprom(
|
|
i2c_iface::sptr iface, const mboard_eeprom_t& mb_eeprom)
|
|
{
|
|
const mboard_eeprom_t curr_eeprom = uhd::usrp::x300::get_mb_eeprom(iface);
|
|
|
|
// Check for duplicate MAC and IP addresses
|
|
const std::vector<std::string> mac_keys{"mac-addr0", "mac-addr1"};
|
|
const std::vector<std::string> ip_keys{
|
|
"ip-addr0", "ip-addr1", "ip-addr2", "ip-addr3"};
|
|
|
|
// make sure there are no duplicate values
|
|
if (check_for_duplicates<uhd::mac_addr_t>(
|
|
"X300", mb_eeprom, curr_eeprom, "MAC address", mac_keys)
|
|
or check_for_duplicates<boost::asio::ip::address_v4>(
|
|
"X300", mb_eeprom, curr_eeprom, "IP address", ip_keys)) {
|
|
throw uhd::value_error(
|
|
"Duplicate values not permitted - write to EEPROM aborted");
|
|
}
|
|
|
|
// parse the revision number
|
|
if (mb_eeprom.has_key("revision"))
|
|
iface->write_eeprom(X300_EEPROM_ADDR,
|
|
offsetof(x300_eeprom_map, revision),
|
|
string_to_uint16_bytes(mb_eeprom["revision"]));
|
|
|
|
// parse the revision compat number
|
|
if (mb_eeprom.has_key("revision_compat"))
|
|
iface->write_eeprom(X300_EEPROM_ADDR,
|
|
offsetof(x300_eeprom_map, revision_compat),
|
|
string_to_uint16_bytes(mb_eeprom["revision_compat"]));
|
|
|
|
// parse the product code
|
|
if (mb_eeprom.has_key("product"))
|
|
iface->write_eeprom(X300_EEPROM_ADDR,
|
|
offsetof(x300_eeprom_map, product),
|
|
string_to_uint16_bytes(mb_eeprom["product"]));
|
|
|
|
// store the mac addresses
|
|
if (mb_eeprom.has_key("mac-addr0"))
|
|
iface->write_eeprom(X300_EEPROM_ADDR,
|
|
offsetof(x300_eeprom_map, mac_addr0),
|
|
mac_addr_t::from_string(mb_eeprom["mac-addr0"]).to_bytes());
|
|
if (mb_eeprom.has_key("mac-addr1"))
|
|
iface->write_eeprom(X300_EEPROM_ADDR,
|
|
offsetof(x300_eeprom_map, mac_addr1),
|
|
mac_addr_t::from_string(mb_eeprom["mac-addr1"]).to_bytes());
|
|
|
|
// store the ip addresses
|
|
byte_vector_t ip_addr_bytes(4);
|
|
if (mb_eeprom.has_key("gateway")) {
|
|
byte_copy(
|
|
boost::asio::ip::address_v4::from_string(mb_eeprom["gateway"]).to_bytes(),
|
|
ip_addr_bytes);
|
|
iface->write_eeprom(
|
|
X300_EEPROM_ADDR, offsetof(x300_eeprom_map, gateway), ip_addr_bytes);
|
|
}
|
|
for (size_t i = 0; i < 4; i++) {
|
|
const std::string n(1, char(i) + '0');
|
|
if (mb_eeprom.has_key("ip-addr" + n)) {
|
|
byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["ip-addr" + n])
|
|
.to_bytes(),
|
|
ip_addr_bytes);
|
|
iface->write_eeprom(X300_EEPROM_ADDR,
|
|
offsetof(x300_eeprom_map, ip_addr) + (i * 4),
|
|
ip_addr_bytes);
|
|
}
|
|
|
|
if (mb_eeprom.has_key("subnet" + n)) {
|
|
byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["subnet" + n])
|
|
.to_bytes(),
|
|
ip_addr_bytes);
|
|
iface->write_eeprom(X300_EEPROM_ADDR,
|
|
offsetof(x300_eeprom_map, subnet) + (i * 4),
|
|
ip_addr_bytes);
|
|
}
|
|
}
|
|
|
|
// store the serial
|
|
if (mb_eeprom.has_key("serial"))
|
|
iface->write_eeprom(X300_EEPROM_ADDR,
|
|
offsetof(x300_eeprom_map, serial),
|
|
string_to_bytes(mb_eeprom["serial"], SERIAL_LEN));
|
|
|
|
// store the name
|
|
if (mb_eeprom.has_key("name"))
|
|
iface->write_eeprom(X300_EEPROM_ADDR,
|
|
offsetof(x300_eeprom_map, name),
|
|
string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN));
|
|
}
|