/*
    Retrieve encoded MAC address from 24C16 serial 2-wire EEPROM,
    decode it and store it in the associated adapter struct for
    use by dvb_net.c

    This card appear to have the 24C16 write protect held to ground,
    thus permitting normal read/write operation. Theoretically it
    would be possible to write routines to burn a different (encoded)
    MAC address into the EEPROM.

    Robert Schlabbach	GMX
    Michael Glaum	KVH Industries
    Holger Waechtler	Convergence

    Copyright (C) 2002-2003 Ralph Metzler <rjkm@metzlerbros.de>
			    Metzler Brothers Systementwicklung GbR

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include <asm/errno.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/i2c.h>
#include <linux/etherdevice.h>

#include "ttpci-eeprom.h"

#if 1
#define dprintk(x...) do { printk(x); } while (0)
#else
#define dprintk(x...) do { } while (0)
#endif


static int check_mac_tt(u8 *buf)
{
	int i;
	u16 tmp = 0xffff;

	for (i = 0; i < 8; i++) {
		tmp  = (tmp << 8) | ((tmp >> 8) ^ buf[i]);
		tmp ^= (tmp >> 4) & 0x0f;
		tmp ^= (tmp << 12) ^ ((tmp & 0xff) << 5);
	}
	tmp ^= 0xffff;
	return (((tmp >> 8) ^ buf[8]) | ((tmp & 0xff) ^ buf[9]));
}

static int getmac_tt(u8 * decodedMAC, u8 * encodedMAC)
{
	u8 xor[20] = { 0x72, 0x23, 0x68, 0x19, 0x5c, 0xa8, 0x71, 0x2c,
		       0x54, 0xd3, 0x7b, 0xf1, 0x9E, 0x23, 0x16, 0xf6,
		       0x1d, 0x36, 0x64, 0x78};
	u8 data[20];
	int i;

	/* In case there is a sig check failure have the orig contents available */
	memcpy(data, encodedMAC, 20);

	for (i = 0; i < 20; i++)
		data[i] ^= xor[i];
	for (i = 0; i < 10; i++)
		data[i] = ((data[2 * i + 1] << 8) | data[2 * i])
			>> ((data[2 * i + 1] >> 6) & 3);

	if (check_mac_tt(data))
		return -ENODEV;

	decodedMAC[0] = data[2]; decodedMAC[1] = data[1]; decodedMAC[2] = data[0];
	decodedMAC[3] = data[6]; decodedMAC[4] = data[5]; decodedMAC[5] = data[4];
	return 0;
}

int ttpci_eeprom_decode_mac(u8 *decodedMAC, u8 *encodedMAC)
{
	u8 xor[20] = { 0x72, 0x23, 0x68, 0x19, 0x5c, 0xa8, 0x71, 0x2c,
		       0x54, 0xd3, 0x7b, 0xf1, 0x9E, 0x23, 0x16, 0xf6,
		       0x1d, 0x36, 0x64, 0x78};
	u8 data[20];
	int i;

	memcpy(data, encodedMAC, 20);

	for (i = 0; i < 20; i++)
		data[i] ^= xor[i];
	for (i = 0; i < 10; i++)
		data[i] = ((data[2 * i + 1] << 8) | data[2 * i])
			>> ((data[2 * i + 1] >> 6) & 3);

	if (check_mac_tt(data))
		return -ENODEV;

	decodedMAC[0] = data[2];
	decodedMAC[1] = data[1];
	decodedMAC[2] = data[0];
	decodedMAC[3] = data[6];
	decodedMAC[4] = data[5];
	decodedMAC[5] = data[4];
	return 0;
}
EXPORT_SYMBOL(ttpci_eeprom_decode_mac);

static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encodedMAC)
{
	int ret;
	u8 b0[] = { 0xcc };

	struct i2c_msg msg[] = {
		{ .addr = 0x50, .flags = 0, .buf = b0, .len = 1 },
		{ .addr = 0x50, .flags = I2C_M_RD, .buf = encodedMAC, .len = 20 }
	};

	/* dprintk("%s\n", __func__); */

	ret = i2c_transfer(adapter, msg, 2);

	if (ret != 2)		/* Assume EEPROM isn't there */
		return (-ENODEV);

	return 0;
}


int ttpci_eeprom_parse_mac(struct i2c_adapter *adapter, u8 *proposed_mac)
{
	int ret, i;
	u8 encodedMAC[20];
	u8 decodedMAC[6];

	ret = ttpci_eeprom_read_encodedMAC(adapter, encodedMAC);

	if (ret != 0) {		/* Will only be -ENODEV */
		dprintk("Couldn't read from EEPROM: not there?\n");
		eth_zero_addr(proposed_mac);
		return ret;
	}

	ret = getmac_tt(decodedMAC, encodedMAC);
	if( ret != 0 ) {
		dprintk("adapter failed MAC signature check\n");
		dprintk("encoded MAC from EEPROM was " );
		for(i=0; i<19; i++) {
			dprintk( "%.2x:", encodedMAC[i]);
		}
		dprintk("%.2x\n", encodedMAC[19]);
		eth_zero_addr(proposed_mac);
		return ret;
	}

	memcpy(proposed_mac, decodedMAC, 6);
	dprintk("adapter has MAC addr = %pM\n", decodedMAC);
	return 0;
}

EXPORT_SYMBOL(ttpci_eeprom_parse_mac);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
MODULE_DESCRIPTION("Decode dvb_net MAC address from EEPROM of PCI DVB cards "
		"made by Siemens, Technotrend, Hauppauge");
