ttpci-eeprom.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. Retrieve encoded MAC address from 24C16 serial 2-wire EEPROM,
  4. decode it and store it in the associated adapter struct for
  5. use by dvb_net.c
  6. This card appear to have the 24C16 write protect held to ground,
  7. thus permitting normal read/write operation. Theoretically it
  8. would be possible to write routines to burn a different (encoded)
  9. MAC address into the EEPROM.
  10. Robert Schlabbach GMX
  11. Michael Glaum KVH Industries
  12. Holger Waechtler Convergence
  13. Copyright (C) 2002-2003 Ralph Metzler <[email protected]>
  14. Metzler Brothers Systementwicklung GbR
  15. */
  16. #include <asm/errno.h>
  17. #include <linux/init.h>
  18. #include <linux/module.h>
  19. #include <linux/string.h>
  20. #include <linux/i2c.h>
  21. #include <linux/etherdevice.h>
  22. #include "ttpci-eeprom.h"
  23. #if 1
  24. #define dprintk(x...) do { printk(x); } while (0)
  25. #else
  26. #define dprintk(x...) do { } while (0)
  27. #endif
  28. static int check_mac_tt(u8 *buf)
  29. {
  30. int i;
  31. u16 tmp = 0xffff;
  32. for (i = 0; i < 8; i++) {
  33. tmp = (tmp << 8) | ((tmp >> 8) ^ buf[i]);
  34. tmp ^= (tmp >> 4) & 0x0f;
  35. tmp ^= (tmp << 12) ^ ((tmp & 0xff) << 5);
  36. }
  37. tmp ^= 0xffff;
  38. return (((tmp >> 8) ^ buf[8]) | ((tmp & 0xff) ^ buf[9]));
  39. }
  40. static int getmac_tt(u8 * decodedMAC, u8 * encodedMAC)
  41. {
  42. u8 xor[20] = { 0x72, 0x23, 0x68, 0x19, 0x5c, 0xa8, 0x71, 0x2c,
  43. 0x54, 0xd3, 0x7b, 0xf1, 0x9E, 0x23, 0x16, 0xf6,
  44. 0x1d, 0x36, 0x64, 0x78};
  45. u8 data[20];
  46. int i;
  47. /* In case there is a sig check failure have the orig contents available */
  48. memcpy(data, encodedMAC, 20);
  49. for (i = 0; i < 20; i++)
  50. data[i] ^= xor[i];
  51. for (i = 0; i < 10; i++)
  52. data[i] = ((data[2 * i + 1] << 8) | data[2 * i])
  53. >> ((data[2 * i + 1] >> 6) & 3);
  54. if (check_mac_tt(data))
  55. return -ENODEV;
  56. decodedMAC[0] = data[2]; decodedMAC[1] = data[1]; decodedMAC[2] = data[0];
  57. decodedMAC[3] = data[6]; decodedMAC[4] = data[5]; decodedMAC[5] = data[4];
  58. return 0;
  59. }
  60. int ttpci_eeprom_decode_mac(u8 *decodedMAC, u8 *encodedMAC)
  61. {
  62. u8 xor[20] = { 0x72, 0x23, 0x68, 0x19, 0x5c, 0xa8, 0x71, 0x2c,
  63. 0x54, 0xd3, 0x7b, 0xf1, 0x9E, 0x23, 0x16, 0xf6,
  64. 0x1d, 0x36, 0x64, 0x78};
  65. u8 data[20];
  66. int i;
  67. memcpy(data, encodedMAC, 20);
  68. for (i = 0; i < 20; i++)
  69. data[i] ^= xor[i];
  70. for (i = 0; i < 10; i++)
  71. data[i] = ((data[2 * i + 1] << 8) | data[2 * i])
  72. >> ((data[2 * i + 1] >> 6) & 3);
  73. if (check_mac_tt(data))
  74. return -ENODEV;
  75. decodedMAC[0] = data[2];
  76. decodedMAC[1] = data[1];
  77. decodedMAC[2] = data[0];
  78. decodedMAC[3] = data[6];
  79. decodedMAC[4] = data[5];
  80. decodedMAC[5] = data[4];
  81. return 0;
  82. }
  83. EXPORT_SYMBOL(ttpci_eeprom_decode_mac);
  84. static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encodedMAC)
  85. {
  86. int ret;
  87. u8 b0[] = { 0xcc };
  88. struct i2c_msg msg[] = {
  89. { .addr = 0x50, .flags = 0, .buf = b0, .len = 1 },
  90. { .addr = 0x50, .flags = I2C_M_RD, .buf = encodedMAC, .len = 20 }
  91. };
  92. /* dprintk("%s\n", __func__); */
  93. ret = i2c_transfer(adapter, msg, 2);
  94. if (ret != 2) /* Assume EEPROM isn't there */
  95. return (-ENODEV);
  96. return 0;
  97. }
  98. int ttpci_eeprom_parse_mac(struct i2c_adapter *adapter, u8 *proposed_mac)
  99. {
  100. int ret;
  101. u8 encodedMAC[20];
  102. u8 decodedMAC[6];
  103. ret = ttpci_eeprom_read_encodedMAC(adapter, encodedMAC);
  104. if (ret != 0) { /* Will only be -ENODEV */
  105. dprintk("Couldn't read from EEPROM: not there?\n");
  106. eth_zero_addr(proposed_mac);
  107. return ret;
  108. }
  109. ret = getmac_tt(decodedMAC, encodedMAC);
  110. if( ret != 0 ) {
  111. dprintk("adapter failed MAC signature check\n");
  112. dprintk("encoded MAC from EEPROM was %*phC",
  113. (int)sizeof(encodedMAC), &encodedMAC);
  114. eth_zero_addr(proposed_mac);
  115. return ret;
  116. }
  117. memcpy(proposed_mac, decodedMAC, 6);
  118. dprintk("adapter has MAC addr = %pM\n", decodedMAC);
  119. return 0;
  120. }
  121. EXPORT_SYMBOL(ttpci_eeprom_parse_mac);
  122. MODULE_LICENSE("GPL");
  123. MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
  124. MODULE_DESCRIPTION("Decode dvb_net MAC address from EEPROM of PCI DVB cards made by Siemens, Technotrend, Hauppauge");