Commit d9cc90d9 authored by Jeroen Vreeken's avatar Jeroen Vreeken
Browse files

Add eeprom crc calculation and write functions.

parent 2521e8d3
......@@ -299,7 +299,11 @@ void describe_esc(struct ec *ec, struct ec_dgram_addr *ec_addr)
r = esc_esi_eeprom_read(ec, ec_addr, &eeprom, 0, sizeof(eeprom));
if (r == sizeof(eeprom)) {
printf("\tESI EEPROM:\n");
uint8_t crc_dev = eeprom[0x0e];
uint8_t crc_calc = esc_esi_crc8(eeprom, 0x0e);
printf("\tESI EEPROM checksum: %s (device: 0x%02x, calculated: 0x%02x\n",
crc_dev == crc_calc ? "correct" : "incorrect", crc_dev, crc_calc);
printf("\tESI EEPROM content:\n");
for (i = 0; i < sizeof(eeprom)/sizeof(*eeprom); i += 16) {
char *c;
int j;
......
......@@ -169,6 +169,117 @@ err_out:
return readsize;
}
ssize_t esc_esi_eeprom_write(struct ec *ec, struct ec_dgram_addr *ec_addr,
void *buffer, size_t offset, size_t size)
{
int r;
uint8_t val8;
uint16_t val16, status;
uint32_t val32;
size_t i;
int retry = 0;
ssize_t writesize = 0;
/* See ET1100 pdf, chapter 11.2.2: Assignment to ECAT/PDI */
/* Request use of EEPROM by master (us) */
ec_addr->addr.position.off = ESC_ADDR_MAP_ESI_EEPROM_CONFIG;
val8 = ESC_ESI_EEPROM_CONFIG_REQUEST_ECAT;
r = ec_datagram_write(ec, ec_addr, &val8, 1);
if (r != 1)
return -1;
/* Make sure ecat side has eeprom control */
ec_addr->addr.position.off = ESC_ADDR_MAP_ESI_EEPROM_PDI_STATE;
do {
r = ec_datagram_read(ec, ec_addr, &val8, 1);
} while (val8 == ESC_ESI_EEPROM_PDI_BUSY && r == 1 && ++retry < MAX_RETRIES);
if (r != 1) {
writesize = -1;
goto err_out;
}
if (retry == MAX_RETRIES) {
log_send(LOG_T_DEBUG, "esc_esi_eeprom_write: forcing the PDI off the EEPROM bus");
/* Force the PDI off of the EEPROM bus */
ec_addr->addr.position.off = ESC_ADDR_MAP_ESI_EEPROM_CONFIG;
val8 = ESC_ESI_EEPROM_CONFIG_FORCE_ECAT;
r = ec_datagram_write(ec, ec_addr, &val8, 1);
if (r != 1) {
writesize = -1;
goto err_out;
}
/* Finish claiming the bus */
ec_addr->addr.position.off = ESC_ADDR_MAP_ESI_EEPROM_CONFIG;
val8 = ESC_ESI_EEPROM_CONFIG_REQUEST_ECAT;
r = ec_datagram_write(ec, ec_addr, &val8, 1);
if (r != 1) {
writesize = -1;
goto err_out;
}
}
/* get status */
ec_addr->addr.position.off = ESC_ADDR_MAP_ESI_EEPROM_CONTROL_STATUS;
r = ec_datagram_read(ec, ec_addr, &val16, 2);
if (r != 2) {
writesize = -1;
goto err_out;
}
status = le16toh(val16);
for (i = 0; i < size; i += 2) {
/* set address, word addressing... */
val32 = htole32((offset + i)/ 2);
ec_addr->addr.position.off = ESC_ADDR_MAP_ESI_EEPROM_ADDRESS;
r = ec_datagram_write(ec, ec_addr, &val32, 4);
/* Wait for other stuff to finish */
do {
r = ec_datagram_read(ec, ec_addr, &val16, 2);
} while (le16toh(val16) & ESC_ESI_EEPROM_CONTROL_STATUS_BUSY && r == 2);
/* write data */
ec_addr->addr.position.off = ESC_ADDR_MAP_ESI_EEPROM_DATA;
void *data = ((char*)buffer) + offset + i;
r = ec_datagram_write(ec, ec_addr, data, 2);
if (r != 2)
break;
/* Issue write command */
ec_addr->addr.position.off = ESC_ADDR_MAP_ESI_EEPROM_CONTROL_STATUS;
val16 = htole16(ESC_ESI_EEPROM_CONTROL_STATUS_ECAT_WRITE_ENABLE | ESC_ESI_EEPROM_CONTROL_STATUS_CMD_WRITE);
r = ec_datagram_write(ec, ec_addr, &val16, 2);
/* Wait for write to finish */
do {
r = ec_datagram_read(ec, ec_addr, &val16, 2);
} while (le16toh(val16) & ESC_ESI_EEPROM_CONTROL_STATUS_BUSY && r == 2);
/* make sure nothing is fucked up.... */
status = le16toh(val16);
if (status & ESC_ESI_EEPROM_CONTROL_STATUS_CHKSUM_ERR ||
status & ESC_ESI_EEPROM_CONTROL_STATUS_NOT_LOADED ||
status & ESC_ESI_EEPROM_CONTROL_STATUS_ACK_ERR ||
status & ESC_ESI_EEPROM_CONTROL_STATUS_WRITE_ERR) {
writesize = -1;
goto err_out;
}
writesize += 2;
}
err_out:
/* Give back the EEPROM to the PDI */
ec_addr->addr.position.off = ESC_ADDR_MAP_ESI_EEPROM_CONFIG;
val8 = ESC_ESI_EEPROM_CONFIG_PDI;
/* if this fails all hope is lost for the PDI :) */
(void)ec_datagram_write(ec, ec_addr, &val8, 1);
return writesize;
}
uint16_t esc_esi_read16(struct ec *ec, struct ec_dgram_addr *ec_addr, size_t offset)
{
......@@ -188,6 +299,39 @@ uint32_t esc_esi_read32(struct ec *ec, struct ec_dgram_addr *ec_addr, size_t off
return le32toh(val32);
}
int esc_esi_write16(struct ec *ec, struct ec_dgram_addr *ec_addr, size_t offset, uint16_t val)
{
val = htole16(val);
ssize_t r = esc_esi_eeprom_write(ec, ec_addr, &val, offset, sizeof(uint16_t));
if (r == 2)
return 0;
return -1;
}
uint8_t esc_esi_crc8(void *data, size_t size)
{
uint8_t r = 0xff;
uint8_t pol = 0x07;
uint8_t *datab = data;
size_t i;
int bit;
for (i=0; i < size; i++) {
r ^= datab[i];
for (bit = 0; bit < 8; bit++) {
if (r & 0x80)
r = (r << 1) ^ pol;
else
r = (r << 1);
}
}
return r;
}
size_t esc_esi_standard_rx_mailbox_offset_get(struct ec *ec, struct ec_dgram_addr *ec_addr)
{
return esc_esi_read16(ec, ec_addr, ESC_ESI_STANDARD_RX_MAILBOX_OFFSET);
......
......@@ -24,10 +24,14 @@
ssize_t esc_esi_eeprom_read(struct ec *ec, struct ec_dgram_addr *ec_addr,
void *buffer, size_t offset, size_t size);
ssize_t esc_esi_eeprom_write(struct ec *ec, struct ec_dgram_addr *ec_addr,
void *buffer, size_t offset, size_t size);
uint16_t esc_esi_read16(struct ec *ec, struct ec_dgram_addr *ec_addr, size_t offset);
uint32_t esc_esi_read32(struct ec *ec, struct ec_dgram_addr *ec_addr, size_t offset);
uint8_t esc_esi_crc8(void *data, size_t size);
uint32_t esc_esi_vendorid_get(struct esc_device *esc);
uint32_t esc_esi_productcode_get(struct esc_device *esc);
uint32_t esc_esi_revisionno_get(struct esc_device *esc);
......
......@@ -73,8 +73,10 @@
#define ESC_ESI_EEPROM_PDI_BUSY 0x01
#define ESC_ESI_EEPROM_FREE 0x00
#define ESC_ADDR_MAP_ESI_EEPROM_CONTROL_STATUS 0x0502
#define ESC_ESI_EEPROM_CONTROL_STATUS_ECAT_WRITE_ENABLE 0x0001
#define ESC_ESI_EEPROM_CONTROL_STATUS_READ_8B 0x0040
#define ESC_ESI_EEPROM_CONTROL_STATUS_CMD_READ 0x0100
#define ESC_ESI_EEPROM_CONTROL_STATUS_CMD_WRITE 0x0200
#define ESC_ESI_EEPROM_CONTROL_STATUS_CHKSUM_ERR 0x0800
#define ESC_ESI_EEPROM_CONTROL_STATUS_NOT_LOADED 0x1000
#define ESC_ESI_EEPROM_CONTROL_STATUS_ACK_ERR 0x2000
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment