976 } |
976 } |
977 |
977 |
978 // init EEPROM write request |
978 // init EEPROM write request |
979 INIT_LIST_HEAD(&request.list); |
979 INIT_LIST_HEAD(&request.list); |
980 request.slave = slave; |
980 request.slave = slave; |
981 request.words = (const uint16_t *) data; |
981 request.data = data; |
982 request.offset = 0; |
982 request.word_offset = 0; |
983 request.size = size / 2; |
983 request.word_size = size / 2; |
984 |
984 |
985 if (request.size < 0x0041) { |
985 if (request.word_size < 0x0041) { |
986 EC_ERR("EEPROM data too short! Dropping.\n"); |
986 EC_ERR("EEPROM data too short! Dropping.\n"); |
987 return -EINVAL; |
987 return -EINVAL; |
988 } |
988 } |
989 |
989 |
990 // calculate checksum |
990 // calculate checksum |
991 crc = ec_slave_eeprom_crc(data, 14); // CRC over words 0 to 6 |
991 crc = ec_slave_eeprom_crc(data, 14); // CRC over words 0 to 6 |
992 if (crc != data[14]) { |
992 if (crc != data[14]) { |
993 EC_WARN("EEPROM CRC incorrect. Must be 0x%02x.\n", crc); |
993 EC_WARN("EEPROM CRC incorrect. Must be 0x%02x.\n", crc); |
994 } |
994 } |
995 |
995 |
996 cat_header = request.words + EC_FIRST_EEPROM_CATEGORY_OFFSET; |
996 cat_header = (const uint16_t *) request.data |
|
997 + EC_FIRST_EEPROM_CATEGORY_OFFSET; |
997 cat_type = EC_READ_U16(cat_header); |
998 cat_type = EC_READ_U16(cat_header); |
998 while (cat_type != 0xFFFF) { // cycle through categories |
999 while (cat_type != 0xFFFF) { // cycle through categories |
999 if (cat_header + 1 > request.words + request.size) { |
1000 if (cat_header + 1 > |
|
1001 (const uint16_t *) request.data + request.word_size) { |
1000 EC_ERR("EEPROM data corrupted! Dropping.\n"); |
1002 EC_ERR("EEPROM data corrupted! Dropping.\n"); |
1001 return -EINVAL; |
1003 return -EINVAL; |
1002 } |
1004 } |
1003 cat_size = EC_READ_U16(cat_header + 1); |
1005 cat_size = EC_READ_U16(cat_header + 1); |
1004 if (cat_header + cat_size + 2 > request.words + request.size) { |
1006 if (cat_header + cat_size + 2 > |
|
1007 (const uint16_t *) request.data + request.word_size) { |
1005 EC_ERR("EEPROM data corrupted! Dropping.\n"); |
1008 EC_ERR("EEPROM data corrupted! Dropping.\n"); |
1006 return -EINVAL; |
1009 return -EINVAL; |
1007 } |
1010 } |
1008 cat_header += cat_size + 2; |
1011 cat_header += cat_size + 2; |
1009 cat_type = EC_READ_U16(cat_header); |
1012 cat_type = EC_READ_U16(cat_header); |
1028 size_t size /**< size of data in bytes */ |
1031 size_t size /**< size of data in bytes */ |
1029 ) |
1032 ) |
1030 { |
1033 { |
1031 ec_eeprom_write_request_t request; |
1034 ec_eeprom_write_request_t request; |
1032 char *remainder; |
1035 char *remainder; |
1033 uint16_t alias, words[8]; |
1036 uint16_t alias; |
1034 int ret; |
1037 int ret; |
1035 uint8_t crc; |
1038 uint8_t eeprom_data[16], crc; |
1036 |
1039 |
1037 if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME |
1040 if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME |
1038 EC_ERR("Writing to EEPROM is only allowed in idle mode!\n"); |
1041 EC_ERR("Writing to EEPROM is only allowed in idle mode!\n"); |
1039 return -EBUSY; |
1042 return -EBUSY; |
1040 } |
1043 } |
1050 slave->ring_position); |
1053 slave->ring_position); |
1051 return -EINVAL; |
1054 return -EINVAL; |
1052 } |
1055 } |
1053 |
1056 |
1054 // copy first 7 words of recent EEPROM contents |
1057 // copy first 7 words of recent EEPROM contents |
1055 memcpy(words, slave->eeprom_data, 14); |
1058 memcpy(eeprom_data, slave->eeprom_data, 14); |
1056 |
1059 |
1057 // write new alias address |
1060 // write new alias address in word 4 |
1058 EC_WRITE_U16(words + 4, alias); |
1061 EC_WRITE_U16(eeprom_data + 8, alias); |
1059 |
1062 |
1060 // calculate new checksum over words 0 to 6 |
1063 // calculate new checksum over words 0 to 6 |
1061 crc = ec_slave_eeprom_crc((const uint8_t *) words, 14); |
1064 crc = ec_slave_eeprom_crc(eeprom_data, 14); |
1062 EC_WRITE_U16(words + 7, crc); |
1065 EC_WRITE_U16(eeprom_data + 14, crc); |
1063 |
1066 |
1064 // init EEPROM write request |
1067 // init EEPROM write request |
1065 INIT_LIST_HEAD(&request.list); |
1068 INIT_LIST_HEAD(&request.list); |
1066 request.slave = slave; |
1069 request.slave = slave; |
1067 request.words = words; |
1070 request.data = eeprom_data; |
1068 request.offset = 0x0000; |
1071 request.word_offset = 0x0000; |
1069 request.size = 8; |
1072 request.word_size = 8; |
1070 |
1073 |
1071 if ((ret = ec_slave_schedule_eeprom_writing(&request))) |
1074 if ((ret = ec_slave_schedule_eeprom_writing(&request))) |
1072 return ret; // error code |
1075 return ret; // error code |
1073 |
1076 |
1074 slave->sii_alias = alias; // FIXME: do this in state machine |
1077 slave->sii_alias = alias; // FIXME: do this in state machine |