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