I2C overhaul part 2
This commit is contained in:
45
src/acpi.c
45
src/acpi.c
@@ -36,6 +36,7 @@
|
||||
#include <86box/apm.h>
|
||||
#include <86box/acpi.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/i2c.h>
|
||||
|
||||
|
||||
#ifdef ENABLE_ACPI_LOG
|
||||
@@ -92,7 +93,7 @@ acpi_raise_smi(void *priv)
|
||||
if ((!dev->regs.smi_lock || !dev->regs.smi_active)) {
|
||||
smi_line = 1;
|
||||
dev->regs.smi_active = 1;
|
||||
}
|
||||
}
|
||||
} else if (dev->vendor == VEN_INTEL) {
|
||||
smi_line = 1;
|
||||
/* Clear bit 16 of GLBCTL. */
|
||||
@@ -311,9 +312,18 @@ acpi_reg_read_via(int size, uint16_t addr, void *p)
|
||||
ret = dev->regs.gpio_val & 0xff;
|
||||
break;
|
||||
case 0x44:
|
||||
/* GPIO port Output Value */
|
||||
if (size == 1)
|
||||
/* GPIO port Input Value */
|
||||
if (size == 1) {
|
||||
ret = dev->regs.extsmi_val & 0xff;
|
||||
|
||||
if (dev->i2c) {
|
||||
ret &= 0xf9;
|
||||
if (!(dev->regs.gpio_dir & 0x02) && i2c_gpio_get_scl(dev->i2c))
|
||||
ret |= 0x02;
|
||||
if (!(dev->regs.gpio_dir & 0x04) && i2c_gpio_get_sda(dev->i2c))
|
||||
ret |= 0x04;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x46: case 0x47:
|
||||
/* GPO Port Output Value */
|
||||
@@ -652,13 +662,25 @@ acpi_reg_write_via(int size, uint16_t addr, uint8_t val, void *p)
|
||||
switch (addr) {
|
||||
case 0x40:
|
||||
/* GPIO Direction Control */
|
||||
if (size == 1)
|
||||
dev->regs.gpio_dir = val & 0xff;
|
||||
if (size == 1) {
|
||||
dev->regs.gpio_dir = val & 0x7f;
|
||||
|
||||
if (dev->i2c) {
|
||||
/* Check direction as well due to pull-ups. */
|
||||
i2c_gpio_set(dev->i2c, !(dev->regs.gpio_dir & 0x02) || (dev->regs.gpio_val & 0x02), !(dev->regs.gpio_dir & 0x04) || (dev->regs.gpio_val & 0x04));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x42:
|
||||
/* GPIO port Output Value */
|
||||
if (size == 1)
|
||||
dev->regs.gpio_val = val & 0xff;
|
||||
if (size == 1) {
|
||||
dev->regs.gpio_val = val & 0x1f;
|
||||
|
||||
if (dev->i2c) {
|
||||
/* Check direction as well due to pull-ups. */
|
||||
i2c_gpio_set(dev->i2c, !(dev->regs.gpio_dir & 0x02) || (dev->regs.gpio_val & 0x02), !(dev->regs.gpio_dir & 0x04) || (dev->regs.gpio_val & 0x04));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x46: case 0x47:
|
||||
/* GPO Port Output Value */
|
||||
@@ -1184,6 +1206,12 @@ acpi_close(void *priv)
|
||||
{
|
||||
acpi_t *dev = (acpi_t *) priv;
|
||||
|
||||
if (dev->i2c) {
|
||||
if (i2c_smbus == i2c_gpio_get_bus(dev->i2c))
|
||||
i2c_smbus = NULL;
|
||||
i2c_gpio_close(dev->i2c);
|
||||
}
|
||||
|
||||
timer_disable(&dev->timer);
|
||||
|
||||
free(dev);
|
||||
@@ -1206,6 +1234,9 @@ acpi_init(const device_t *info)
|
||||
if (dev->vendor == VEN_INTEL) {
|
||||
dev->apm = device_add(&apm_pci_acpi_device);
|
||||
io_sethandler(0x00b2, 0x0002, acpi_apm_in, NULL, NULL, acpi_apm_out, NULL, NULL, dev);
|
||||
} else if (dev->vendor == VEN_VIA) {
|
||||
dev->i2c = i2c_gpio_init("smbus_vt82c586b");
|
||||
i2c_smbus = i2c_gpio_get_bus(dev->i2c);
|
||||
}
|
||||
|
||||
timer_add(&dev->timer, acpi_timer_count, dev, 0);
|
||||
|
@@ -41,17 +41,14 @@ typedef struct {
|
||||
uint16_t regs[32];
|
||||
uint8_t addr_register;
|
||||
|
||||
uint8_t i2c_addr;
|
||||
uint8_t i2c_addr, i2c_state;
|
||||
} gl518sm_t;
|
||||
|
||||
|
||||
static uint8_t gl518sm_i2c_read_byte(void *bus, uint8_t addr, void *priv);
|
||||
static uint8_t gl518sm_i2c_read_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv);
|
||||
static uint16_t gl518sm_i2c_read_word_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv);
|
||||
static void gl518sm_i2c_start(void *bus, uint8_t addr, void *priv);
|
||||
static uint8_t gl518sm_i2c_read(void *bus, uint8_t addr, void *priv);
|
||||
static uint16_t gl518sm_read(gl518sm_t *dev, uint8_t reg);
|
||||
static void gl518sm_i2c_write_byte(void *bus, uint8_t addr, uint8_t val, void *priv);
|
||||
static void gl518sm_i2c_write_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, uint8_t val, void *priv);
|
||||
static void gl518sm_i2c_write_word_cmd(void *bus, uint8_t addr, uint8_t cmd, uint16_t val, void *priv);
|
||||
static uint8_t gl518sm_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv);
|
||||
static uint8_t gl518sm_write(gl518sm_t *dev, uint8_t reg, uint16_t val);
|
||||
static void gl518sm_reset(gl518sm_t *dev);
|
||||
|
||||
@@ -81,41 +78,40 @@ gl518sm_remap(gl518sm_t *dev, uint8_t addr)
|
||||
{
|
||||
gl518sm_log("GL518SM: remapping to I2C %02Xh\n", addr);
|
||||
|
||||
i2c_removehandler(i2c_smbus, dev->i2c_addr, 1,
|
||||
NULL, gl518sm_i2c_read_byte, gl518sm_i2c_read_byte_cmd, gl518sm_i2c_read_word_cmd, NULL,
|
||||
NULL, gl518sm_i2c_write_byte, gl518sm_i2c_write_byte_cmd, gl518sm_i2c_write_word_cmd, NULL,
|
||||
dev);
|
||||
i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev);
|
||||
|
||||
if (addr < 0x80) i2c_sethandler(i2c_smbus, addr, 1,
|
||||
NULL, gl518sm_i2c_read_byte, gl518sm_i2c_read_byte_cmd, gl518sm_i2c_read_word_cmd, NULL,
|
||||
NULL, gl518sm_i2c_write_byte, gl518sm_i2c_write_byte_cmd, gl518sm_i2c_write_word_cmd, NULL,
|
||||
dev);
|
||||
if (addr < 0x80)
|
||||
i2c_sethandler(i2c_smbus, addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev);
|
||||
|
||||
dev->i2c_addr = addr;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
gl518sm_i2c_read_byte(void *bus, uint8_t addr, void *priv)
|
||||
static void
|
||||
gl518sm_i2c_start(void *bus, uint8_t addr, void *priv)
|
||||
{
|
||||
gl518sm_t *dev = (gl518sm_t *) priv;
|
||||
return gl518sm_read(dev, dev->addr_register);
|
||||
|
||||
dev->i2c_state = 0;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
gl518sm_i2c_read_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv)
|
||||
gl518sm_i2c_read(void *bus, uint8_t addr, void *priv)
|
||||
{
|
||||
gl518sm_t *dev = (gl518sm_t *) priv;
|
||||
return gl518sm_read(dev, cmd);
|
||||
}
|
||||
uint16_t read = gl518sm_read(dev, dev->addr_register);
|
||||
uint8_t ret = 0;
|
||||
|
||||
if ((dev->i2c_state == 1) && (dev->addr_register >= 0x07) && (dev->addr_register <= 0x0c)) { /* two-byte registers: read MSB first */
|
||||
dev->i2c_state = 2;
|
||||
ret = read >> 8;
|
||||
} else
|
||||
ret = read;
|
||||
|
||||
static uint16_t
|
||||
gl518sm_i2c_read_word_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv)
|
||||
{
|
||||
gl518sm_t *dev = (gl518sm_t *) priv;
|
||||
return gl518sm_read(dev, cmd);
|
||||
dev->addr_register++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -157,37 +153,35 @@ gl518sm_read(gl518sm_t *dev, uint8_t reg)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Duplicate the low byte to the high byte on single-byte registers, although real hardware behavior is undefined. */
|
||||
if ((reg < 0x07) || (reg > 0x0c))
|
||||
ret |= ret << 8;
|
||||
|
||||
gl518sm_log("GL518SM: read(%02X) = %04X\n", reg, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gl518sm_i2c_write_byte(void *bus, uint8_t addr, uint8_t val, void *priv)
|
||||
static uint8_t
|
||||
gl518sm_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
||||
{
|
||||
gl518sm_t *dev = (gl518sm_t *) priv;
|
||||
dev->addr_register = val;
|
||||
}
|
||||
|
||||
switch (dev->i2c_state++) {
|
||||
case 0:
|
||||
dev->addr_register = data;
|
||||
break;
|
||||
|
||||
static void
|
||||
gl518sm_i2c_write_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, uint8_t val, void *priv)
|
||||
{
|
||||
gl518sm_t *dev = (gl518sm_t *) priv;
|
||||
gl518sm_write(dev, cmd, val);
|
||||
}
|
||||
case 1:
|
||||
gl518sm_write(dev, dev->addr_register, data);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
gl518sm_write(dev, dev->addr_register, (data << 8) | gl518sm_read(dev, dev->addr_register));
|
||||
break;
|
||||
|
||||
static void
|
||||
gl518sm_i2c_write_word_cmd(void *bus, uint8_t addr, uint8_t cmd, uint16_t val, void *priv)
|
||||
{
|
||||
gl518sm_t *dev = (gl518sm_t *) priv;
|
||||
gl518sm_write(dev, cmd, val);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -30,12 +30,9 @@
|
||||
#define LM75_TEMP_TO_REG(t) ((t) << 8)
|
||||
|
||||
|
||||
static uint8_t lm75_i2c_read_byte(void *bus, uint8_t addr, void *priv);
|
||||
static uint8_t lm75_i2c_read_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv);
|
||||
static uint16_t lm75_i2c_read_word_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv);
|
||||
static void lm75_i2c_write_byte(void *bus, uint8_t addr, uint8_t val, void *priv);
|
||||
static void lm75_i2c_write_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, uint8_t val, void *priv);
|
||||
static void lm75_i2c_write_word_cmd(void *bus, uint8_t addr, uint8_t cmd, uint16_t val, void *priv);
|
||||
static void lm75_i2c_start(void *bus, uint8_t addr, void *priv);
|
||||
static uint8_t lm75_i2c_read(void *bus, uint8_t addr, void *priv);
|
||||
static uint8_t lm75_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv);
|
||||
static void lm75_reset(lm75_t *dev);
|
||||
|
||||
|
||||
@@ -64,61 +61,49 @@ lm75_remap(lm75_t *dev, uint8_t addr)
|
||||
{
|
||||
lm75_log("LM75: remapping to I2C %02Xh\n", addr);
|
||||
|
||||
if (dev->i2c_addr < 0x80) i2c_removehandler(i2c_smbus, dev->i2c_addr, 1,
|
||||
NULL, lm75_i2c_read_byte, lm75_i2c_read_byte_cmd, lm75_i2c_read_word_cmd, NULL,
|
||||
NULL, lm75_i2c_write_byte, lm75_i2c_write_byte_cmd, lm75_i2c_write_word_cmd, NULL,
|
||||
dev);
|
||||
if (dev->i2c_addr < 0x80)
|
||||
i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev);
|
||||
|
||||
if (addr < 0x80) i2c_sethandler(i2c_smbus, addr, 1,
|
||||
NULL, lm75_i2c_read_byte, lm75_i2c_read_byte_cmd, lm75_i2c_read_word_cmd, NULL,
|
||||
NULL, lm75_i2c_write_byte, lm75_i2c_write_byte_cmd, lm75_i2c_write_word_cmd, NULL,
|
||||
dev);
|
||||
if (addr < 0x80)
|
||||
i2c_sethandler(i2c_smbus, addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev);
|
||||
|
||||
dev->i2c_addr = addr;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
lm75_i2c_read_byte(void *bus, uint8_t addr, void *priv)
|
||||
static void
|
||||
lm75_i2c_start(void *bus, uint8_t addr, void *priv)
|
||||
{
|
||||
lm75_t *dev = (lm75_t *) priv;
|
||||
return lm75_read(dev, dev->addr_register);
|
||||
|
||||
dev->i2c_state = 0;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
lm75_i2c_read_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv)
|
||||
lm75_i2c_read(void *bus, uint8_t addr, void *priv)
|
||||
{
|
||||
lm75_t *dev = (lm75_t *) priv;
|
||||
return lm75_read(dev, cmd);
|
||||
}
|
||||
uint8_t ret = 0;
|
||||
|
||||
static uint16_t
|
||||
lm75_i2c_read_word_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv)
|
||||
{
|
||||
lm75_t *dev = (lm75_t *) priv;
|
||||
uint8_t rethi = 0;
|
||||
uint8_t retlo = 0;
|
||||
|
||||
switch (cmd & 0x3) {
|
||||
switch (dev->addr_register & 0x3) {
|
||||
case 0x0: /* temperature */
|
||||
rethi = lm75_read(dev, 0x0);
|
||||
retlo = lm75_read(dev, 0x1);
|
||||
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x1 : 0x0);
|
||||
break;
|
||||
|
||||
case 0x1: /* configuration */
|
||||
rethi = retlo = lm75_read(dev, 0x2);
|
||||
ret = lm75_read(dev, 0x2);
|
||||
break;
|
||||
|
||||
case 0x2: /* Thyst */
|
||||
rethi = lm75_read(dev, 0x3);
|
||||
retlo = lm75_read(dev, 0x4);
|
||||
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x4 : 0x3);
|
||||
break;
|
||||
case 0x3: /* Tos */
|
||||
rethi = lm75_read(dev, 0x5);
|
||||
retlo = lm75_read(dev, 0x6);
|
||||
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x6 : 0x5);
|
||||
break;
|
||||
}
|
||||
|
||||
return (retlo << 8) | rethi; /* byte-swapped for some reason */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -130,9 +115,12 @@ lm75_read(lm75_t *dev, uint8_t reg)
|
||||
/* The AS99127F hardware monitor uses the addresses of its LM75 devices
|
||||
to access some of its proprietary registers. Pass this operation on to
|
||||
the main monitor address through an internal I2C call, if necessary. */
|
||||
if ((reg > 0x7) && ((reg & 0xf8) != 0x50) && (dev->as99127f_i2c_addr < 0x80))
|
||||
ret = i2c_read_byte_cmd(i2c_smbus, dev->as99127f_i2c_addr, reg);
|
||||
else if ((reg & 0x7) == 0x0) /* temperature high byte */
|
||||
if ((reg > 0x7) && ((reg & 0xf8) != 0x50) && (dev->as99127f_i2c_addr < 0x80)) {
|
||||
i2c_start(i2c_smbus, dev->as99127f_i2c_addr);
|
||||
i2c_write(i2c_smbus, dev->as99127f_i2c_addr, reg);
|
||||
ret = i2c_read(i2c_smbus, dev->as99127f_i2c_addr);
|
||||
i2c_stop(i2c_smbus, dev->as99127f_i2c_addr);
|
||||
} else if ((reg & 0x7) == 0x0) /* temperature high byte */
|
||||
ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]) >> 8;
|
||||
else if ((reg & 0x7) == 0x1) /* temperature low byte */
|
||||
ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]);
|
||||
@@ -145,47 +133,36 @@ lm75_read(lm75_t *dev, uint8_t reg)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lm75_i2c_write_byte(void *bus, uint8_t addr, uint8_t val, void *priv)
|
||||
static uint8_t
|
||||
lm75_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
||||
{
|
||||
lm75_t *dev = (lm75_t *) priv;
|
||||
dev->addr_register = val;
|
||||
}
|
||||
|
||||
if ((dev->i2c_state > 2) || ((dev->i2c_state == 2) && ((dev->addr_register & 0x3) == 0x1))) {
|
||||
return 0;
|
||||
} else if (dev->i2c_state == 0) {
|
||||
dev->addr_register = data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
lm75_i2c_write_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, uint8_t val, void *priv)
|
||||
{
|
||||
lm75_t *dev = (lm75_t *) priv;
|
||||
lm75_write(dev, cmd, val);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lm75_i2c_write_word_cmd(void *bus, uint8_t addr, uint8_t cmd, uint16_t val, void *priv)
|
||||
{
|
||||
lm75_t *dev = (lm75_t *) priv;
|
||||
uint8_t valhi = (val >> 8);
|
||||
uint8_t vallo = (val & 0xff);
|
||||
|
||||
switch (cmd & 0x3) {
|
||||
switch (dev->addr_register & 0x3) {
|
||||
case 0x0: /* temperature */
|
||||
lm75_write(dev, 0x0, valhi);
|
||||
lm75_write(dev, 0x1, vallo);
|
||||
lm75_write(dev, (dev->i2c_state == 1) ? 0x1 : 0x0, data);
|
||||
break;
|
||||
|
||||
case 0x1: /* configuration */
|
||||
lm75_write(dev, 0x2, vallo);
|
||||
lm75_write(dev, 0x2, data);
|
||||
break;
|
||||
|
||||
case 0x2: /* Thyst */
|
||||
lm75_write(dev, 0x3, valhi);
|
||||
lm75_write(dev, 0x4, vallo);
|
||||
lm75_write(dev, (dev->i2c_state == 1) ? 0x4 : 0x3, data);
|
||||
break;
|
||||
case 0x3: /* Tos */
|
||||
lm75_write(dev, 0x5, valhi);
|
||||
lm75_write(dev, 0x6, vallo);
|
||||
lm75_write(dev, (dev->i2c_state == 1) ? 0x6 : 0x5, data);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -198,7 +175,10 @@ lm75_write(lm75_t *dev, uint8_t reg, uint8_t val)
|
||||
to access some of its proprietary registers. Pass this operation on to
|
||||
the main monitor address through an internal I2C call, if necessary. */
|
||||
if ((reg > 0x7) && ((reg & 0xf8) != 0x50) && (dev->as99127f_i2c_addr < 0x80)) {
|
||||
i2c_write_byte_cmd(i2c_smbus, dev->as99127f_i2c_addr, reg, val);
|
||||
i2c_start(i2c_smbus, dev->as99127f_i2c_addr);
|
||||
i2c_write(i2c_smbus, dev->as99127f_i2c_addr, reg);
|
||||
i2c_write(i2c_smbus, dev->as99127f_i2c_addr, val);
|
||||
i2c_stop(i2c_smbus, dev->as99127f_i2c_addr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -56,19 +56,16 @@ typedef struct {
|
||||
uint8_t addr_register;
|
||||
uint8_t data_register;
|
||||
|
||||
uint8_t i2c_addr;
|
||||
uint8_t i2c_addr, i2c_state;
|
||||
} lm78_t;
|
||||
|
||||
|
||||
static void lm78_i2c_start(void *bus, uint8_t addr, void *priv);
|
||||
static uint8_t lm78_isa_read(uint16_t port, void *priv);
|
||||
static uint8_t lm78_i2c_read_byte(void *bus, uint8_t addr, void *priv);
|
||||
static uint8_t lm78_i2c_read_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv);
|
||||
static uint16_t lm78_i2c_read_word_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv);
|
||||
static uint8_t lm78_i2c_read(void *bus, uint8_t addr, void *priv);
|
||||
static uint8_t lm78_read(lm78_t *dev, uint8_t reg, uint8_t bank);
|
||||
static void lm78_isa_write(uint16_t port, uint8_t val, void *priv);
|
||||
static void lm78_i2c_write_byte(void *bus, uint8_t addr, uint8_t val, void *priv);
|
||||
static void lm78_i2c_write_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, uint8_t val, void *priv);
|
||||
static void lm78_i2c_write_word_cmd(void *bus, uint8_t addr, uint8_t cmd, uint16_t val, void *priv);
|
||||
static uint8_t lm78_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv);
|
||||
static uint8_t lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank);
|
||||
static void lm78_reset(lm78_t *dev, uint8_t initialization);
|
||||
|
||||
@@ -100,17 +97,12 @@ lm78_remap(lm78_t *dev, uint8_t addr)
|
||||
|
||||
if (!(dev->local & LM78_I2C)) return;
|
||||
|
||||
lm78_log("LM78: remapping to I2C %02Xh\n", addr);
|
||||
lm78_log("LM78: remapping to SMBus %02Xh\n", addr);
|
||||
|
||||
i2c_removehandler(i2c_smbus, dev->i2c_addr, 1,
|
||||
NULL, lm78_i2c_read_byte, lm78_i2c_read_byte_cmd, lm78_i2c_read_word_cmd, NULL,
|
||||
NULL, lm78_i2c_write_byte, lm78_i2c_write_byte_cmd, lm78_i2c_write_word_cmd, NULL,
|
||||
dev);
|
||||
i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, lm78_i2c_start, lm78_i2c_read, lm78_i2c_write, NULL, dev);
|
||||
|
||||
if (addr < 0x80) i2c_sethandler(i2c_smbus, addr, 1,
|
||||
NULL, lm78_i2c_read_byte, lm78_i2c_read_byte_cmd, lm78_i2c_read_word_cmd, NULL,
|
||||
NULL, lm78_i2c_write_byte, lm78_i2c_write_byte_cmd, lm78_i2c_write_word_cmd, NULL,
|
||||
dev);
|
||||
if (addr < 0x80)
|
||||
i2c_sethandler(i2c_smbus, addr, 1, lm78_i2c_start, lm78_i2c_read, lm78_i2c_write, NULL, dev);
|
||||
|
||||
dev->i2c_addr = addr;
|
||||
|
||||
@@ -126,6 +118,15 @@ lm78_remap(lm78_t *dev, uint8_t addr)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lm78_i2c_start(void *bus, uint8_t addr, void *priv)
|
||||
{
|
||||
lm78_t *dev = (lm78_t *) priv;
|
||||
|
||||
dev->i2c_state = 0;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
lm78_isa_read(uint16_t port, void *priv)
|
||||
{
|
||||
@@ -159,26 +160,11 @@ lm78_isa_read(uint16_t port, void *priv)
|
||||
|
||||
|
||||
static uint8_t
|
||||
lm78_i2c_read_byte(void *bus, uint8_t addr, void *priv)
|
||||
lm78_i2c_read(void *bus, uint8_t addr, void *priv)
|
||||
{
|
||||
lm78_t *dev = (lm78_t *) priv;
|
||||
return lm78_read(dev, dev->addr_register, LM78_WINBOND_BANK);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
lm78_i2c_read_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv)
|
||||
{
|
||||
lm78_t *dev = (lm78_t *) priv;
|
||||
return lm78_read(dev, cmd, LM78_WINBOND_BANK);
|
||||
}
|
||||
|
||||
|
||||
static uint16_t
|
||||
lm78_i2c_read_word_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv)
|
||||
{
|
||||
lm78_t *dev = (lm78_t *) priv;
|
||||
return (lm78_read(dev, cmd, LM78_WINBOND_BANK) << 8) | lm78_read(dev, cmd, LM78_WINBOND_BANK);
|
||||
return lm78_read(dev, dev->addr_register++, LM78_WINBOND_BANK);
|
||||
}
|
||||
|
||||
|
||||
@@ -264,27 +250,18 @@ lm78_isa_write(uint16_t port, uint8_t val, void *priv)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lm78_i2c_write_byte(void *bus, uint8_t addr, uint8_t val, void *priv)
|
||||
static uint8_t
|
||||
lm78_i2c_write(void *bus, uint8_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
lm78_t *dev = (lm78_t *) priv;
|
||||
dev->addr_register = val;
|
||||
}
|
||||
|
||||
if (dev->i2c_state == 0) {
|
||||
dev->i2c_state = 1;
|
||||
dev->addr_register = val;
|
||||
} else
|
||||
lm78_write(dev, dev->addr_register++, val, LM78_WINBOND_BANK);
|
||||
|
||||
static void
|
||||
lm78_i2c_write_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, uint8_t val, void *priv)
|
||||
{
|
||||
lm78_t *dev = (lm78_t *) priv;
|
||||
lm78_write(dev, cmd, val, LM78_WINBOND_BANK);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lm78_i2c_write_word_cmd(void *bus, uint8_t addr, uint8_t cmd, uint16_t val, void *priv)
|
||||
{
|
||||
lm78_t *dev = (lm78_t *) priv;
|
||||
lm78_write(dev, cmd, val, LM78_WINBOND_BANK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
327
src/device/i2c.c
327
src/device/i2c.c
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implement the I2C bus and its operations.
|
||||
* Implementation of the I2C bus and its operations.
|
||||
*
|
||||
*
|
||||
*
|
||||
@@ -30,17 +30,10 @@
|
||||
|
||||
|
||||
typedef struct _i2c_ {
|
||||
void (*read_quick)(void *bus, uint8_t addr, void *priv);
|
||||
uint8_t (*read_byte)(void *bus, uint8_t addr, void *priv);
|
||||
uint8_t (*read_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv);
|
||||
uint16_t (*read_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv);
|
||||
uint8_t (*read_block_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv);
|
||||
|
||||
void (*write_quick)(void *bus, uint8_t addr, void *priv);
|
||||
void (*write_byte)(void *bus, uint8_t addr, uint8_t val, void *priv);
|
||||
void (*write_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t val, void *priv);
|
||||
void (*write_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint16_t val, void *priv);
|
||||
void (*write_block_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv);
|
||||
void (*start)(void *bus, uint8_t addr, void *priv);
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv);
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv);
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv);
|
||||
|
||||
void *priv;
|
||||
|
||||
@@ -55,7 +48,7 @@ typedef struct {
|
||||
|
||||
void *i2c_smbus;
|
||||
|
||||
#define ENABLE_I2C_LOG 1
|
||||
|
||||
#ifdef ENABLE_I2C_LOG
|
||||
int i2c_do_log = ENABLE_I2C_LOG;
|
||||
|
||||
@@ -100,16 +93,10 @@ i2c_removebus(void *bus_handle)
|
||||
|
||||
void
|
||||
i2c_sethandler(void *bus_handle, uint8_t base, int size,
|
||||
void (*read_quick)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read_byte)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
||||
uint16_t (*read_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
||||
uint8_t (*read_block_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv),
|
||||
void (*write_quick)(void *bus, uint8_t addr, void *priv),
|
||||
void (*write_byte)(void *bus, uint8_t addr, uint8_t val, void *priv),
|
||||
void (*write_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t val, void *priv),
|
||||
void (*write_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint16_t val, void *priv),
|
||||
void (*write_block_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv),
|
||||
void (*start)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv),
|
||||
void *priv)
|
||||
{
|
||||
int c;
|
||||
@@ -131,15 +118,10 @@ i2c_sethandler(void *bus_handle, uint8_t base, int size,
|
||||
q->prev = NULL;
|
||||
}
|
||||
|
||||
q->read_byte = read_byte;
|
||||
q->read_byte_cmd = read_byte_cmd;
|
||||
q->read_word_cmd = read_word_cmd;
|
||||
q->read_block_cmd = read_block_cmd;
|
||||
|
||||
q->write_byte = write_byte;
|
||||
q->write_byte_cmd = write_byte_cmd;
|
||||
q->write_word_cmd = write_word_cmd;
|
||||
q->write_block_cmd = write_block_cmd;
|
||||
q->start = start;
|
||||
q->read = read;
|
||||
q->write = write;
|
||||
q->stop = stop;
|
||||
|
||||
q->priv = priv;
|
||||
q->next = NULL;
|
||||
@@ -151,16 +133,10 @@ i2c_sethandler(void *bus_handle, uint8_t base, int size,
|
||||
|
||||
void
|
||||
i2c_removehandler(void *bus_handle, uint8_t base, int size,
|
||||
void (*read_quick)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read_byte)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
||||
uint16_t (*read_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
||||
uint8_t (*read_block_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv),
|
||||
void (*write_quick)(void *bus, uint8_t addr, void *priv),
|
||||
void (*write_byte)(void *bus, uint8_t addr, uint8_t val, void *priv),
|
||||
void (*write_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t val, void *priv),
|
||||
void (*write_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint16_t val, void *priv),
|
||||
void (*write_block_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv),
|
||||
void (*start)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv),
|
||||
void *priv)
|
||||
{
|
||||
int c;
|
||||
@@ -176,11 +152,7 @@ i2c_removehandler(void *bus_handle, uint8_t base, int size,
|
||||
continue;
|
||||
while(p) {
|
||||
q = p->next;
|
||||
if ((p->read_byte == read_byte) && (p->read_byte_cmd == read_byte_cmd) &&
|
||||
(p->read_word_cmd == read_word_cmd) && (p->read_block_cmd == read_block_cmd) &&
|
||||
(p->write_byte == write_byte) && (p->write_byte_cmd == write_byte_cmd) &&
|
||||
(p->write_word_cmd == write_word_cmd) && (p->write_block_cmd == write_block_cmd) &&
|
||||
(p->priv == priv)) {
|
||||
if ((p->read == read) && (p->write == write) && (p->priv == priv)) {
|
||||
if (p->prev)
|
||||
p->prev->next = p->next;
|
||||
else
|
||||
@@ -201,22 +173,16 @@ i2c_removehandler(void *bus_handle, uint8_t base, int size,
|
||||
|
||||
void
|
||||
i2c_handler(int set, void *bus_handle, uint8_t base, int size,
|
||||
void (*read_quick)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read_byte)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
||||
uint16_t (*read_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
||||
uint8_t (*read_block_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv),
|
||||
void (*write_quick)(void *bus, uint8_t addr, void *priv),
|
||||
void (*write_byte)(void *bus, uint8_t addr, uint8_t val, void *priv),
|
||||
void (*write_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t val, void *priv),
|
||||
void (*write_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint16_t val, void *priv),
|
||||
void (*write_block_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv),
|
||||
void (*start)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv),
|
||||
void *priv)
|
||||
{
|
||||
if (set)
|
||||
i2c_sethandler(bus_handle, base, size, read_quick, read_byte, read_byte_cmd, read_word_cmd, read_block_cmd, write_quick, write_byte, write_byte_cmd, write_word_cmd, write_block_cmd, priv);
|
||||
i2c_sethandler(bus_handle, base, size, start, read, write, stop, priv);
|
||||
else
|
||||
i2c_removehandler(bus_handle, base, size, read_quick, read_byte, read_byte_cmd, read_word_cmd, read_block_cmd, write_quick, write_byte, write_byte_cmd, write_word_cmd, write_block_cmd, priv);
|
||||
i2c_removehandler(bus_handle, base, size, start, read, write, stop, priv);
|
||||
}
|
||||
|
||||
|
||||
@@ -233,11 +199,10 @@ i2c_has_device(void *bus_handle, uint8_t addr)
|
||||
|
||||
|
||||
void
|
||||
i2c_read_quick(void *bus_handle, uint8_t addr)
|
||||
i2c_start(void *bus_handle, uint8_t addr)
|
||||
{
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
i2c_t *p;
|
||||
int found = 0;
|
||||
|
||||
if (!bus)
|
||||
return;
|
||||
@@ -245,106 +210,23 @@ i2c_read_quick(void *bus_handle, uint8_t addr)
|
||||
p = bus->devices[addr];
|
||||
if (p) {
|
||||
while(p) {
|
||||
if (p->read_byte) {
|
||||
p->read_quick(bus_handle, addr, p->priv);
|
||||
found++;
|
||||
if (p->start) {
|
||||
p->start(bus_handle, addr, p->priv);
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C: read_quick(%s, %02X)\n", bus->name, addr);
|
||||
i2c_log("I2C: start(%s, %02X)\n", bus->name, addr);
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
i2c_read_byte(void *bus_handle, uint8_t addr)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
i2c_t *p;
|
||||
int found = 0;
|
||||
|
||||
if (!bus)
|
||||
return(ret);
|
||||
|
||||
p = bus->devices[addr];
|
||||
if (p) {
|
||||
while(p) {
|
||||
if (p->read_byte) {
|
||||
ret &= p->read_byte(bus_handle, addr, p->priv);
|
||||
found++;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C: read_byte(%s, %02X) = %02X\n", bus->name, addr, ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
i2c_read_byte_cmd(void *bus_handle, uint8_t addr, uint8_t cmd)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
i2c_t *p;
|
||||
int found = 0;
|
||||
|
||||
if (!bus)
|
||||
return(ret);
|
||||
|
||||
p = bus->devices[addr];
|
||||
if (p) {
|
||||
while(p) {
|
||||
if (p->read_byte_cmd) {
|
||||
ret &= p->read_byte_cmd(bus_handle, addr, cmd, p->priv);
|
||||
found++;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C: read_byte_cmd(%s, %02X, %02X) = %02X\n", bus->name, addr, cmd, ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
i2c_read_word_cmd(void *bus_handle, uint8_t addr, uint8_t cmd)
|
||||
{
|
||||
uint16_t ret = 0xffff;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
i2c_t *p;
|
||||
int found = 0;
|
||||
|
||||
if (!bus)
|
||||
return(ret);
|
||||
|
||||
p = bus->devices[addr];
|
||||
if (p) {
|
||||
while(p) {
|
||||
if (p->read_word_cmd) {
|
||||
ret &= p->read_word_cmd(bus_handle, addr, cmd, p->priv);
|
||||
found++;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C: read_word_cmd(%s, %02X, %02X) = %04X\n", bus->name, addr, cmd, ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
i2c_read_block_cmd(void *bus_handle, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len)
|
||||
i2c_read(void *bus_handle, uint8_t addr)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
i2c_t *p;
|
||||
int found = 0;
|
||||
|
||||
if (!bus)
|
||||
return(ret);
|
||||
@@ -352,26 +234,51 @@ i2c_read_block_cmd(void *bus_handle, uint8_t addr, uint8_t cmd, uint8_t *data, u
|
||||
p = bus->devices[addr];
|
||||
if (p) {
|
||||
while(p) {
|
||||
if (p->read_block_cmd) {
|
||||
ret = MAX(ret, p->read_block_cmd(bus_handle, addr, cmd, data, len, p->priv));
|
||||
found++;
|
||||
if (p->read) {
|
||||
ret = p->read(bus_handle, addr, p->priv);
|
||||
break;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C: read_block_cmd(%s, %02X, %02X) = %02X\n", bus->name, addr, cmd, len);
|
||||
i2c_log("I2C: read(%s, %02X) = %02X\n", bus->name, addr, ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
i2c_write(void *bus_handle, uint8_t addr, uint8_t data)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
i2c_t *p;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
|
||||
if (!bus)
|
||||
return(ret);
|
||||
|
||||
p = bus->devices[addr];
|
||||
if (p) {
|
||||
while(p) {
|
||||
if (p->write) {
|
||||
ret = p->write(bus_handle, addr, data, p->priv);
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C: write(%s, %02X, %02X) = %d\n", bus->name, addr, data, ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
i2c_write_quick(void *bus_handle, uint8_t addr)
|
||||
i2c_stop(void *bus_handle, uint8_t addr)
|
||||
{
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
i2c_t *p;
|
||||
int found = 0;
|
||||
|
||||
if (!bus)
|
||||
return;
|
||||
@@ -379,118 +286,12 @@ i2c_write_quick(void *bus_handle, uint8_t addr)
|
||||
p = bus->devices[addr];
|
||||
if (p) {
|
||||
while(p) {
|
||||
if (p->read_byte) {
|
||||
p->write_quick(bus_handle, addr, p->priv);
|
||||
found++;
|
||||
if (p->stop) {
|
||||
p->stop(bus_handle, addr, p->priv);
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C: write_quick(%s, %02X)\n", bus->name, addr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
i2c_write_byte(void *bus_handle, uint8_t addr, uint8_t val)
|
||||
{
|
||||
i2c_t *p;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
int found = 0;
|
||||
|
||||
if (!bus)
|
||||
return;
|
||||
|
||||
if (bus->devices[addr]) {
|
||||
p = bus->devices[addr];
|
||||
while(p) {
|
||||
if (p->write_byte) {
|
||||
p->write_byte(bus_handle, addr, val, p->priv);
|
||||
found++;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C: write_byte(%s, %02X, %02X)\n", bus->name, addr, val);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
i2c_write_byte_cmd(void *bus_handle, uint8_t addr, uint8_t cmd, uint8_t val)
|
||||
{
|
||||
i2c_t *p;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
int found = 0;
|
||||
|
||||
if (!bus)
|
||||
return;
|
||||
|
||||
if (bus->devices[addr]) {
|
||||
p = bus->devices[addr];
|
||||
while(p) {
|
||||
if (p->write_byte_cmd) {
|
||||
p->write_byte_cmd(bus_handle, addr, cmd, val, p->priv);
|
||||
found++;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C: write_byte_cmd(%s, %02X, %02X, %02X)\n", bus->name, addr, cmd, val);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
i2c_write_word_cmd(void *bus_handle, uint8_t addr, uint8_t cmd, uint16_t val)
|
||||
{
|
||||
i2c_t *p;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
int found = 0;
|
||||
|
||||
if (!bus)
|
||||
return;
|
||||
|
||||
if (bus->devices[addr]) {
|
||||
p = bus->devices[addr];
|
||||
while(p) {
|
||||
if (p->write_word_cmd) {
|
||||
p->write_word_cmd(bus_handle, addr, cmd, val, p->priv);
|
||||
found++;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C: write_word_cmd(%s, %02X, %02X, %04X)\n", bus->name, addr, cmd, val);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
i2c_write_block_cmd(void *bus_handle, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len)
|
||||
{
|
||||
i2c_t *p;
|
||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||
int found = 0;
|
||||
|
||||
if (!bus)
|
||||
return;
|
||||
|
||||
p = bus->devices[addr];
|
||||
if (p) {
|
||||
while(p) {
|
||||
if (p->write_block_cmd) {
|
||||
p->write_block_cmd(bus_handle, addr, cmd, data, len, p->priv);
|
||||
found++;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_log("I2C: write_block_cmd(%s, %02X, %02X, %02X)\n", bus->name, addr, cmd, len);
|
||||
|
||||
return;
|
||||
i2c_log("I2C: stop(%s, %02X)\n", bus->name, addr);
|
||||
}
|
||||
|
102
src/device/i2c_eeprom.c
Normal file
102
src/device/i2c_eeprom.c
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the AT24Cxx series of I2C EEPROMs.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: RichardG, <richardg867@gmail.com>
|
||||
*
|
||||
* Copyright 2020 RichardG.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/i2c.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
void *i2c;
|
||||
uint8_t addr;
|
||||
uint8_t *data;
|
||||
uint8_t writable;
|
||||
|
||||
uint16_t addr_mask;
|
||||
uint8_t addr_register;
|
||||
uint8_t i2c_state;
|
||||
} i2c_eeprom_t;
|
||||
|
||||
|
||||
void
|
||||
i2c_eeprom_start(void *bus, uint8_t addr, void *priv)
|
||||
{
|
||||
i2c_eeprom_t *dev = (i2c_eeprom_t *) priv;
|
||||
|
||||
dev->i2c_state = 0;
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
i2c_eeprom_read(void *bus, uint8_t addr, void *priv)
|
||||
{
|
||||
i2c_eeprom_t *dev = (i2c_eeprom_t *) priv;
|
||||
|
||||
return dev->data[((addr << 8) | dev->addr_register++) & dev->addr_mask];
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
i2c_eeprom_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
||||
{
|
||||
i2c_eeprom_t *dev = (i2c_eeprom_t *) priv;
|
||||
|
||||
if (dev->i2c_state == 0) {
|
||||
dev->i2c_state = 1;
|
||||
dev->addr_register = data;
|
||||
} else if (dev->writable)
|
||||
dev->data[((addr << 8) | dev->addr_register++) & dev->addr_mask] = data;
|
||||
else
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint16_t size, uint8_t writable)
|
||||
{
|
||||
i2c_eeprom_t *dev = (i2c_eeprom_t *) malloc(sizeof(i2c_eeprom_t));
|
||||
memset(dev, 0, sizeof(i2c_eeprom_t));
|
||||
|
||||
dev->i2c = i2c;
|
||||
dev->addr = addr;
|
||||
dev->data = data;
|
||||
dev->writable = writable;
|
||||
|
||||
dev->addr_mask = size - 1;
|
||||
|
||||
i2c_sethandler(i2c, dev->addr & ~(dev->addr_mask >> 8), (dev->addr_mask >> 8) + 1, i2c_eeprom_start, i2c_eeprom_read, i2c_eeprom_write, NULL, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
i2c_eeprom_close(void *dev_handle)
|
||||
{
|
||||
i2c_eeprom_t *dev = (i2c_eeprom_t *) dev_handle;
|
||||
|
||||
i2c_removehandler(dev->i2c, dev->addr & ~(dev->addr_mask >> 8), (dev->addr_mask >> 8) + 1, i2c_eeprom_start, i2c_eeprom_read, i2c_eeprom_write, NULL, dev);
|
||||
|
||||
free(dev);
|
||||
}
|
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of a GPIO-based I2C device.
|
||||
* Emulation of a GPIO-based I2C device.
|
||||
*
|
||||
*
|
||||
*
|
||||
@@ -16,13 +16,13 @@
|
||||
* Copyright 2008-2020 Sarah Walker.
|
||||
* Copyright 2020 RichardG.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/i2c.h>
|
||||
|
||||
@@ -53,8 +53,8 @@ enum {
|
||||
|
||||
typedef struct {
|
||||
void *i2c;
|
||||
uint8_t scl, sda, state, slave_state, slave_addr, slave_reg,
|
||||
slave_writing, slave_rw, last_sda, pos, transmit, byte;
|
||||
uint8_t scl, sda, state, slave_state, slave_addr,
|
||||
slave_rw, last_sda, pos, transmit, byte;
|
||||
} i2c_gpio_t;
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ i2c_gpio_init(char *bus_name)
|
||||
|
||||
dev->i2c = i2c_addbus(bus_name);
|
||||
dev->scl = dev->sda = 1;
|
||||
dev->slave_addr = 0xff;
|
||||
|
||||
return dev;
|
||||
}
|
||||
@@ -85,49 +86,46 @@ i2c_gpio_close(void *dev_handle)
|
||||
void
|
||||
i2c_gpio_next_byte(i2c_gpio_t *dev)
|
||||
{
|
||||
dev->byte = i2c_read_byte(dev->i2c, dev->slave_addr);
|
||||
dev->byte = i2c_read(dev->i2c, dev->slave_addr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
i2c_gpio_write(i2c_gpio_t *dev)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
switch (dev->slave_state) {
|
||||
case SLAVE_IDLE:
|
||||
i = dev->slave_addr;
|
||||
dev->slave_addr = dev->byte >> 1;
|
||||
dev->slave_rw = dev->byte & 1;
|
||||
|
||||
if (!i2c_has_device(dev->i2c, dev->slave_addr)) {
|
||||
dev->slave_state = SLAVE_INVALID;
|
||||
break;
|
||||
}
|
||||
dev->slave_rw = dev->byte & 1;
|
||||
dev->slave_writing = 0;
|
||||
|
||||
if (i == 0xff)
|
||||
i2c_start(dev->i2c, dev->slave_addr);
|
||||
|
||||
if (dev->slave_rw) {
|
||||
dev->slave_state = SLAVE_SENDDATA;
|
||||
dev->transmit = TRANSMITTER_SLAVE;
|
||||
dev->byte = i2c_read_byte(dev->i2c, dev->slave_addr);
|
||||
dev->byte = i2c_read(dev->i2c, dev->slave_addr);
|
||||
} else {
|
||||
dev->slave_state = SLAVE_RECEIVEADDR;
|
||||
dev->transmit = TRANSMITTER_MASTER;
|
||||
}
|
||||
pclog("slave_idle %02X %d\n", dev->slave_addr, dev->slave_rw);
|
||||
break;
|
||||
|
||||
case SLAVE_RECEIVEADDR:
|
||||
pclog("slave_receiveaddr %02X %d\n", dev->slave_addr, dev->slave_rw);
|
||||
i2c_write_byte(dev->i2c, dev->slave_addr, dev->byte);
|
||||
dev->slave_writing = 1;
|
||||
dev->slave_reg = dev->byte;
|
||||
i2c_write(dev->i2c, dev->slave_addr, dev->byte);
|
||||
dev->slave_state = dev->slave_rw ? SLAVE_SENDDATA : SLAVE_RECEIVEDATA;
|
||||
break;
|
||||
|
||||
case SLAVE_RECEIVEDATA:
|
||||
pclog("slave_receivedata %02X %d = %02X\n", dev->slave_addr, dev->slave_rw, dev->byte);
|
||||
dev->slave_writing = 0;
|
||||
i2c_write_byte_cmd(dev->i2c, dev->slave_addr, dev->slave_reg, dev->byte);
|
||||
break;
|
||||
|
||||
case SLAVE_SENDDATA:
|
||||
pclog("slave_senddata %02X %d = %02X\n", dev->slave_addr, dev->slave_rw, dev->byte);
|
||||
i2c_write(dev->i2c, dev->slave_addr, dev->byte);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -136,10 +134,9 @@ i2c_gpio_write(i2c_gpio_t *dev)
|
||||
void
|
||||
i2c_gpio_stop(i2c_gpio_t *dev)
|
||||
{
|
||||
pclog("stopping... state = %d\n", dev->slave_state);
|
||||
if (dev->slave_writing)
|
||||
i2c_write_byte(dev->i2c, dev->slave_addr, dev->slave_reg);
|
||||
i2c_stop(dev->i2c, dev->slave_addr);
|
||||
|
||||
dev->slave_addr = 0xff;
|
||||
dev->slave_state = SLAVE_IDLE;
|
||||
dev->transmit = TRANSMITTER_MASTER;
|
||||
}
|
||||
|
@@ -99,7 +99,6 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
smbus_piix4_t *dev = (smbus_piix4_t *) priv;
|
||||
uint8_t smbus_addr, smbus_read, prev_stat;
|
||||
uint16_t temp;
|
||||
|
||||
smbus_piix4_log("SMBus PIIX4: write(%02X, %02X)\n", addr, val);
|
||||
|
||||
@@ -132,46 +131,53 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
|
||||
}
|
||||
smbus_read = dev->addr & 0x01;
|
||||
|
||||
/* start transaction */
|
||||
i2c_start(i2c_smbus, smbus_addr);
|
||||
|
||||
/* decode the 3-bit command protocol */
|
||||
dev->next_stat = 0x2; /* raise INTER (command completed) by default */
|
||||
switch ((val >> 2) & 0x7) {
|
||||
case 0x0: /* quick R/W */
|
||||
if (smbus_read)
|
||||
i2c_read_quick(i2c_smbus, smbus_addr);
|
||||
else
|
||||
i2c_write_quick(i2c_smbus, smbus_addr);
|
||||
break;
|
||||
|
||||
case 0x1: /* byte R/W */
|
||||
if (smbus_read)
|
||||
dev->data0 = i2c_read_byte(i2c_smbus, smbus_addr);
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
else
|
||||
i2c_write_byte(i2c_smbus, smbus_addr, dev->data0);
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
break;
|
||||
|
||||
case 0x2: /* byte data R/W */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
if (smbus_read)
|
||||
dev->data0 = i2c_read_byte_cmd(i2c_smbus, smbus_addr, dev->cmd);
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
else
|
||||
i2c_write_byte_cmd(i2c_smbus, smbus_addr, dev->cmd, dev->data0);
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
break;
|
||||
|
||||
case 0x3: /* word data R/W */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
if (smbus_read) {
|
||||
temp = i2c_read_word_cmd(i2c_smbus, smbus_addr, dev->cmd);
|
||||
dev->data0 = temp;
|
||||
dev->data1 = temp >> 8;
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
dev->data1 = i2c_read(i2c_smbus, smbus_addr);
|
||||
} else {
|
||||
temp = (dev->data1 << 8) | dev->data0;
|
||||
i2c_write_word_cmd(i2c_smbus, smbus_addr, dev->cmd, temp);
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x5: /* block R/W */
|
||||
if (smbus_read)
|
||||
dev->data0 = i2c_read_block_cmd(i2c_smbus, smbus_addr, dev->cmd, dev->data, SMBUS_PIIX4_BLOCK_DATA_SIZE);
|
||||
else
|
||||
i2c_write_block_cmd(i2c_smbus, smbus_addr, dev->cmd, dev->data, dev->data0);
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
/* SMBus block data is preceded by a length */
|
||||
if (smbus_read) {
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
for (smbus_read = 0; smbus_read < MIN(SMBUS_PIIX4_BLOCK_DATA_SIZE, dev->data0); smbus_read++)
|
||||
dev->data[smbus_read] = i2c_read(i2c_smbus, smbus_addr);
|
||||
} else {
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
for (smbus_read = 0; smbus_read < MIN(SMBUS_PIIX4_BLOCK_DATA_SIZE, dev->data0); smbus_read++)
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data[smbus_read]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -179,6 +185,9 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
|
||||
dev->next_stat = 0x4;
|
||||
break;
|
||||
}
|
||||
|
||||
/* stop transaction */
|
||||
i2c_stop(i2c_smbus, smbus_addr);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -244,7 +253,7 @@ smbus_piix4_init(const device_t *info)
|
||||
smbus_piix4_t *dev = (smbus_piix4_t *) malloc(sizeof(smbus_piix4_t));
|
||||
memset(dev, 0, sizeof(smbus_piix4_t));
|
||||
|
||||
i2c_smbus = i2c_addbus("smbus_piix4");
|
||||
i2c_smbus = dev->i2c = i2c_addbus("smbus_piix4");
|
||||
|
||||
timer_add(&dev->response_timer, smbus_piix4_response, dev, 0);
|
||||
|
||||
@@ -257,8 +266,9 @@ smbus_piix4_close(void *priv)
|
||||
{
|
||||
smbus_piix4_t *dev = (smbus_piix4_t *) priv;
|
||||
|
||||
i2c_removebus(i2c_smbus);
|
||||
i2c_smbus = NULL;
|
||||
if (i2c_smbus == dev->i2c)
|
||||
i2c_smbus = NULL;
|
||||
i2c_removebus(dev->i2c);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
@@ -84,6 +84,7 @@ typedef struct
|
||||
pc_timer_t timer;
|
||||
nvr_t *nvr;
|
||||
apm_t *apm;
|
||||
void *i2c;
|
||||
} acpi_t;
|
||||
|
||||
|
||||
|
@@ -35,7 +35,7 @@ typedef struct {
|
||||
uint8_t regs[8];
|
||||
uint8_t addr_register;
|
||||
uint8_t temp_idx;
|
||||
uint8_t i2c_addr;
|
||||
uint8_t i2c_addr, i2c_state;
|
||||
|
||||
uint8_t as99127f_i2c_addr;
|
||||
} lm75_t;
|
||||
|
@@ -27,55 +27,35 @@ extern void *i2c_addbus(char *name);
|
||||
extern void i2c_removebus(void *bus_handle);
|
||||
|
||||
extern void i2c_sethandler(void *bus_handle, uint8_t base, int size,
|
||||
void (*read_quick)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read_byte)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
||||
uint16_t (*read_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
||||
uint8_t (*read_block_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv),
|
||||
void (*write_quick)(void *bus, uint8_t addr, void *priv),
|
||||
void (*write_byte)(void *bus, uint8_t addr, uint8_t val, void *priv),
|
||||
void (*write_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t val, void *priv),
|
||||
void (*write_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint16_t val, void *priv),
|
||||
void (*write_block_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv),
|
||||
void (*start)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv),
|
||||
void *priv);
|
||||
|
||||
extern void i2c_removehandler(void *bus_handle, uint8_t base, int size,
|
||||
void (*read_quick)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read_byte)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
||||
uint16_t (*read_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
||||
uint8_t (*read_block_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv),
|
||||
void (*write_quick)(void *bus, uint8_t addr, void *priv),
|
||||
void (*write_byte)(void *bus, uint8_t addr, uint8_t val, void *priv),
|
||||
void (*write_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t val, void *priv),
|
||||
void (*write_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint16_t val, void *priv),
|
||||
void (*write_block_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv),
|
||||
void (*start)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv),
|
||||
void *priv);
|
||||
|
||||
extern void i2c_handler(int set, void *bus_handle, uint8_t base, int size,
|
||||
void (*read_quick)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read_byte)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
||||
uint16_t (*read_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
||||
uint8_t (*read_block_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv),
|
||||
void (*write_quick)(void *bus, uint8_t addr, void *priv),
|
||||
void (*write_byte)(void *bus, uint8_t addr, uint8_t val, void *priv),
|
||||
void (*write_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t val, void *priv),
|
||||
void (*write_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint16_t val, void *priv),
|
||||
void (*write_block_cmd)(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv),
|
||||
void (*start)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||
void (*stop)(void *bus, uint8_t addr, void *priv),
|
||||
void *priv);
|
||||
|
||||
extern uint8_t i2c_has_device(void *bus_handle, uint8_t addr);
|
||||
extern void i2c_read_quick(void *bus_handle, uint8_t addr);
|
||||
extern uint8_t i2c_read_byte(void *bus_handle, uint8_t addr);
|
||||
extern uint8_t i2c_read_byte_cmd(void *bus_handle, uint8_t addr, uint8_t cmd);
|
||||
extern uint16_t i2c_read_word_cmd(void *bus_handle, uint8_t addr, uint8_t cmd);
|
||||
extern uint8_t i2c_read_block_cmd(void *bus_handle, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len);
|
||||
extern void i2c_write_quick(void *bus_handle, uint8_t addr);
|
||||
extern void i2c_write_byte(void *bus_handle, uint8_t addr, uint8_t val);
|
||||
extern void i2c_write_byte_cmd(void *bus_handle, uint8_t addr, uint8_t cmd, uint8_t val);
|
||||
extern void i2c_write_word_cmd(void *bus_handle, uint8_t addr, uint8_t cmd, uint16_t val);
|
||||
extern void i2c_write_block_cmd(void *bus_handle, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len);
|
||||
extern void i2c_start(void *bus_handle, uint8_t addr);
|
||||
extern uint8_t i2c_read(void *bus_handle, uint8_t addr);
|
||||
extern uint8_t i2c_write(void *bus_handle, uint8_t addr, uint8_t data);
|
||||
extern void i2c_stop(void *bus_handle, uint8_t addr);
|
||||
|
||||
/* i2c_eeprom.c */
|
||||
extern void *i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint16_t size, uint8_t writable);
|
||||
extern void i2c_eeprom_close(void *dev_handle);
|
||||
|
||||
/* i2c_gpio.c */
|
||||
extern void *i2c_gpio_init(char *bus_name);
|
||||
|
@@ -29,6 +29,7 @@ typedef struct
|
||||
index,
|
||||
data[SMBUS_PIIX4_BLOCK_DATA_SIZE];
|
||||
pc_timer_t response_timer;
|
||||
void *i2c;
|
||||
} smbus_piix4_t;
|
||||
|
||||
|
||||
|
@@ -47,17 +47,17 @@
|
||||
#define SPD_SDR_ATTR_VCC_HI_5 0x20
|
||||
|
||||
|
||||
typedef struct _spd_ {
|
||||
const device_t *info;
|
||||
uint8_t slot;
|
||||
uint16_t size;
|
||||
uint16_t row1;
|
||||
uint16_t row2;
|
||||
typedef struct {
|
||||
const device_t *info;
|
||||
uint8_t slot;
|
||||
uint16_t size;
|
||||
uint16_t row1;
|
||||
uint16_t row2;
|
||||
|
||||
uint8_t addr_register;
|
||||
void *eeprom;
|
||||
} spd_t;
|
||||
|
||||
typedef struct _spd_edo_ {
|
||||
typedef struct {
|
||||
uint8_t bytes_used, spd_size, mem_type,
|
||||
row_bits, col_bits, banks,
|
||||
data_width_lsb, data_width_msb,
|
||||
@@ -75,7 +75,7 @@ typedef struct _spd_edo_ {
|
||||
checksum2;
|
||||
} spd_edo_t;
|
||||
|
||||
typedef struct _spd_sdram_ {
|
||||
typedef struct {
|
||||
uint8_t bytes_used, spd_size, mem_type,
|
||||
row_bits, col_bits, rows,
|
||||
data_width_lsb, data_width_msb,
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#ifndef EMU_VID_DDC_H
|
||||
# define EMU_VID_DDC_H
|
||||
|
||||
extern void ddc_init(void *i2c);
|
||||
extern void *ddc_init(void *i2c);
|
||||
extern void ddc_close(void *dev_handle);
|
||||
|
||||
#endif /*EMU_VID_DDC_H*/
|
||||
|
@@ -57,49 +57,6 @@ spd_log(const char *fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
uint8_t
|
||||
spd_read_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv)
|
||||
{
|
||||
spd_t *dev = (spd_t *) priv;
|
||||
uint8_t ret = *(spd_data[dev->slot] + cmd);
|
||||
spd_log("SPD: read(%02X, %02X) = %02X\n", addr, cmd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
spd_read_byte(void *bus, uint8_t addr, void *priv)
|
||||
{
|
||||
spd_t *dev = (spd_t *) priv;
|
||||
return spd_read_byte_cmd(bus, addr, dev->addr_register, priv);
|
||||
}
|
||||
|
||||
|
||||
uint16_t
|
||||
spd_read_word_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv)
|
||||
{
|
||||
return (spd_read_byte_cmd(bus, addr, cmd + 1, priv) << 8) | spd_read_byte_cmd(bus, addr, cmd, priv);
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
spd_read_block_cmd(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv)
|
||||
{
|
||||
uint8_t read = 0;
|
||||
for (uint8_t i = cmd; (i < len) && (i < SPD_DATA_SIZE); i++)
|
||||
data[read++] = spd_read_byte_cmd(bus, addr, i, priv);
|
||||
return read;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
spd_write_byte(void *bus, uint8_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
spd_t *dev = (spd_t *) priv;
|
||||
dev->addr_register = val;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
spd_close(void *priv)
|
||||
{
|
||||
@@ -107,10 +64,7 @@ spd_close(void *priv)
|
||||
|
||||
spd_log("SPD: closing slot %d (SMBus %02X)\n", dev->slot, SPD_BASE_ADDR + dev->slot);
|
||||
|
||||
i2c_removehandler(i2c_smbus, SPD_BASE_ADDR + dev->slot, 1,
|
||||
NULL, spd_read_byte, spd_read_byte_cmd, spd_read_word_cmd, spd_read_block_cmd,
|
||||
NULL, spd_write_byte, NULL, NULL, NULL,
|
||||
dev);
|
||||
i2c_eeprom_close(dev->eeprom);
|
||||
|
||||
spd_present = 0;
|
||||
|
||||
@@ -125,10 +79,7 @@ spd_init(const device_t *info)
|
||||
|
||||
spd_log("SPD: initializing slot %d (SMBus %02X)\n", dev->slot, SPD_BASE_ADDR + dev->slot);
|
||||
|
||||
i2c_sethandler(i2c_smbus, SPD_BASE_ADDR + dev->slot, 1,
|
||||
NULL, spd_read_byte, spd_read_byte_cmd, spd_read_word_cmd, spd_read_block_cmd,
|
||||
NULL, spd_write_byte, NULL, NULL, NULL,
|
||||
dev);
|
||||
dev->eeprom = i2c_eeprom_init(i2c_smbus, SPD_BASE_ADDR + dev->slot, spd_data[info->local], SPD_DATA_SIZE, 0);
|
||||
|
||||
spd_present = 1;
|
||||
|
||||
|
@@ -253,7 +253,7 @@ typedef struct mach64_t
|
||||
|
||||
int overlay_v_acc;
|
||||
|
||||
void *i2c;
|
||||
void *i2c, *ddc;
|
||||
} mach64_t;
|
||||
|
||||
static video_timings_t timing_mach64_isa = {VIDEO_ISA, 3, 3, 6, 5, 5, 10};
|
||||
@@ -3372,7 +3372,7 @@ static void *mach64_common_init(const device_t *info)
|
||||
mach64->fifo_thread = thread_create(fifo_thread, mach64);
|
||||
|
||||
mach64->i2c = i2c_gpio_init("ddc_ati_mach64");
|
||||
ddc_init(i2c_gpio_get_bus(mach64->i2c));
|
||||
mach64->ddc = ddc_init(i2c_gpio_get_bus(mach64->i2c));
|
||||
|
||||
return mach64;
|
||||
}
|
||||
@@ -3464,6 +3464,9 @@ void mach64_close(void *p)
|
||||
thread_destroy_event(mach64->wake_fifo_thread);
|
||||
thread_destroy_event(mach64->fifo_not_full_event);
|
||||
|
||||
ddc_close(mach64->ddc);
|
||||
i2c_gpio_close(mach64->i2c);
|
||||
|
||||
free(mach64);
|
||||
}
|
||||
|
||||
|
@@ -27,11 +27,6 @@
|
||||
#include <86box/i2c.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t addr_register;
|
||||
} ddc_t;
|
||||
|
||||
|
||||
static uint8_t edid_data[128] = {
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, /* Fixed header pattern */
|
||||
0x09, 0xf8, /* Manufacturer "BOX" - apparently unassigned by UEFI - and it has to be big endian */
|
||||
@@ -74,59 +69,20 @@ static uint8_t edid_data[128] = {
|
||||
};
|
||||
|
||||
|
||||
uint8_t
|
||||
ddc_read_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv)
|
||||
{
|
||||
return edid_data[cmd & 0x7f];
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
ddc_read_byte(void *bus, uint8_t addr, void *priv)
|
||||
{
|
||||
ddc_t *dev = (ddc_t *) priv;
|
||||
return ddc_read_byte_cmd(bus, addr, dev->addr_register++, priv);
|
||||
}
|
||||
|
||||
|
||||
uint16_t
|
||||
ddc_read_word_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv)
|
||||
{
|
||||
return (ddc_read_byte_cmd(bus, addr, cmd + 1, priv) << 8) | ddc_read_byte_cmd(bus, addr, cmd, priv);
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
ddc_read_block_cmd(void *bus, uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv)
|
||||
{
|
||||
uint8_t read = 0;
|
||||
for (uint8_t i = cmd; (i < len) && (i < 0x80); i++)
|
||||
data[read++] = ddc_read_byte_cmd(bus, addr, i, priv);
|
||||
return read;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ddc_write_byte(void *bus, uint8_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
ddc_t *dev = (ddc_t *) priv;
|
||||
dev->addr_register = val;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
void *
|
||||
ddc_init(void *i2c)
|
||||
{
|
||||
ddc_t *dev = (ddc_t *) malloc(sizeof(ddc_t));
|
||||
memset(dev, 0, sizeof(ddc_t));
|
||||
|
||||
uint8_t checksum = 0;
|
||||
for (int c = 0; c < 127; c++)
|
||||
checksum += edid_data[c];
|
||||
edid_data[127] = 256 - checksum;
|
||||
|
||||
i2c_sethandler(i2c, 0x50, 1,
|
||||
NULL, ddc_read_byte, ddc_read_byte_cmd, ddc_read_word_cmd, ddc_read_block_cmd,
|
||||
NULL, ddc_write_byte, NULL, NULL, NULL,
|
||||
dev);
|
||||
return i2c_eeprom_init(i2c, 0x50, edid_data, sizeof(edid_data), 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ddc_close(void *dev_handle)
|
||||
{
|
||||
i2c_eeprom_close(dev_handle);
|
||||
}
|
||||
|
@@ -288,7 +288,7 @@ typedef struct virge_t
|
||||
|
||||
uint8_t serialport;
|
||||
|
||||
void *i2c;
|
||||
void *i2c, *ddc;
|
||||
} virge_t;
|
||||
|
||||
static video_timings_t timing_diamond_stealth3d_2000_vlb = {VIDEO_BUS, 2, 2, 3, 28, 28, 45};
|
||||
@@ -3849,7 +3849,7 @@ static void *s3_virge_init(const device_t *info)
|
||||
virge->fifo_thread = thread_create(fifo_thread, virge);
|
||||
|
||||
virge->i2c = i2c_gpio_init("ddc_s3_virge");
|
||||
ddc_init(i2c_gpio_get_bus(virge->i2c));
|
||||
virge->ddc = ddc_init(i2c_gpio_get_bus(virge->i2c));
|
||||
|
||||
return virge;
|
||||
}
|
||||
@@ -3868,6 +3868,9 @@ static void s3_virge_close(void *p)
|
||||
thread_destroy_event(virge->fifo_not_full_event);
|
||||
|
||||
svga_close(&virge->svga);
|
||||
|
||||
ddc_close(virge->ddc);
|
||||
i2c_gpio_close(virge->i2c);
|
||||
|
||||
free(virge);
|
||||
}
|
||||
|
@@ -118,7 +118,7 @@ typedef struct banshee_t
|
||||
|
||||
int type;
|
||||
|
||||
void *i2c;
|
||||
void *i2c, *ddc;
|
||||
} banshee_t;
|
||||
|
||||
enum
|
||||
@@ -2629,7 +2629,7 @@ static void *banshee_init_common(const device_t *info, wchar_t *fn, int has_sgra
|
||||
banshee->vidSerialParallelPort = VIDSERIAL_DDC_DCK_W | VIDSERIAL_DDC_DDA_W;
|
||||
|
||||
banshee->i2c = i2c_gpio_init("ddc_voodoo_banshee");
|
||||
ddc_init(i2c_gpio_get_bus(banshee->i2c));
|
||||
banshee->ddc = ddc_init(i2c_gpio_get_bus(banshee->i2c));
|
||||
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_banshee);
|
||||
|
||||
@@ -2676,6 +2676,7 @@ static void banshee_close(void *p)
|
||||
|
||||
voodoo_card_close(banshee->voodoo);
|
||||
svga_close(&banshee->svga);
|
||||
ddc_close(banshee->ddc);
|
||||
i2c_gpio_close(banshee->i2c);
|
||||
|
||||
free(banshee);
|
||||
|
@@ -654,7 +654,7 @@ MCHOBJ := machine.o machine_table.o \
|
||||
|
||||
DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm_5161.o isamem.o isartc.o \
|
||||
lpt.o pci_bridge.o postcard.o serial.o vpc2007.o \
|
||||
i2c.o i2c_gpio.o smbus_piix4.o \
|
||||
i2c.o i2c_eeprom.o i2c_gpio.o smbus_piix4.o \
|
||||
keyboard.o \
|
||||
keyboard_xt.o keyboard_at.o \
|
||||
mouse.o \
|
||||
|
Reference in New Issue
Block a user