/* hardware interface struct
* functions are defined in target tree
*/
struct i2c_struct
{
int (*i2c_start)(void);
void (*i2c_stop)(void);
int (*i2c_outb)(unsigned char byte)
int (*i2c_inb)(bool ack);
void (*i2c_hw_init)(void);
}

/* arbitrary choosen */
#define MAX_I2C_INTERFACES 5
/* global array which holds ptrs to struct with lowlevel,
* platform specific i2c functions
*/
static const struct i2c_struct *i2c_if[MAX_I2C_INTERFACES];

int i2c_write (int bus_index,
unsigned char i2c_addr,
int address,
const unsigned char *buf,
int count)
{
int i;
int ret = 0;
const struct i2c_struct *iface = i2c_if[bus_index];

iface->i2c_start();
if (!iface->i2c_outb(i2c_address & 0xfe))
{
ret = -2;
goto end;
}

if (address != -1)
{
if (!iface->i2c_outb(address))
{
ret = -3;
goto end;
}
}

for(i = 0;i < count;i++)
{
if (!iface->i2c_outb(buf[i]))
{
ret = -4;
break;
}
}

end:
iface->i2c_stop();
return ret;
}

int i2c_write (int bus_index,
unsigned char i2c_addr,
int address,
const unsigned char *buf,
int count)
{
int i;
int ret = 0;
const struct i2c_struct *iface = i2c_if[bus_index];

if (address != -1)
{
iface->i2c_start();
if (!iface->i2c_outb(bus_address & 0xfe))
{
ret = -2;
goto end;
}
if (!iface->i2c_outb(address))
{
ret = -3;
goto end;
}
}

iface->i2c_start();
if (!iface->i2c_outb(bus_address | 1))
{
ret = -4;
goto end;
}

for(i = 0;i < count-1;i++)
buf[i] = iface->i2c_inb(true);

buf[i] = iface->i2c_inb(false);

end:
iface->i2c_stop();
return ret;
}

int i2c_register_interface(int bus_index
struct i2c_struct *iface)
{
static unsigned char i2c_num_ifs = 0;

if ( bus_index < 0 )
{
/* assign next free index */
if (i2c_num_ifs == MAX_I2C_INTERFACES)
return -1;

bus_index = i2c_num_ifs++;
}

i2c_if[bus_index] = iface;
}

void i2c_init(void)
{
int i;
struct i2c_struct *iface;

for (i=0; i < MAX_I2C_INTERFACES; i++)
{
if (i2c_if[i] != NULL)
{
iface = i2c_if[i];
i2c_if->i2c_hw_init();
}
}
}