I2C overhaul part 2

This commit is contained in:
RichardG867
2020-11-20 19:23:14 -03:00
parent 886dbe09ea
commit 739fdc46cc
20 changed files with 430 additions and 641 deletions

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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
View 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);
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -84,6 +84,7 @@ typedef struct
pc_timer_t timer;
nvr_t *nvr;
apm_t *apm;
void *i2c;
} acpi_t;

View File

@@ -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;

View File

@@ -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);

View File

@@ -29,6 +29,7 @@ typedef struct
index,
data[SMBUS_PIIX4_BLOCK_DATA_SIZE];
pc_timer_t response_timer;
void *i2c;
} smbus_piix4_t;

View File

@@ -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,

View File

@@ -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*/

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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 \