I2C overhaul part 2
This commit is contained in:
43
src/acpi.c
43
src/acpi.c
@@ -36,6 +36,7 @@
|
|||||||
#include <86box/apm.h>
|
#include <86box/apm.h>
|
||||||
#include <86box/acpi.h>
|
#include <86box/acpi.h>
|
||||||
#include <86box/machine.h>
|
#include <86box/machine.h>
|
||||||
|
#include <86box/i2c.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_ACPI_LOG
|
#ifdef ENABLE_ACPI_LOG
|
||||||
@@ -311,9 +312,18 @@ acpi_reg_read_via(int size, uint16_t addr, void *p)
|
|||||||
ret = dev->regs.gpio_val & 0xff;
|
ret = dev->regs.gpio_val & 0xff;
|
||||||
break;
|
break;
|
||||||
case 0x44:
|
case 0x44:
|
||||||
/* GPIO port Output Value */
|
/* GPIO port Input Value */
|
||||||
if (size == 1)
|
if (size == 1) {
|
||||||
ret = dev->regs.extsmi_val & 0xff;
|
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;
|
break;
|
||||||
case 0x46: case 0x47:
|
case 0x46: case 0x47:
|
||||||
/* GPO Port Output Value */
|
/* GPO Port Output Value */
|
||||||
@@ -652,13 +662,25 @@ acpi_reg_write_via(int size, uint16_t addr, uint8_t val, void *p)
|
|||||||
switch (addr) {
|
switch (addr) {
|
||||||
case 0x40:
|
case 0x40:
|
||||||
/* GPIO Direction Control */
|
/* GPIO Direction Control */
|
||||||
if (size == 1)
|
if (size == 1) {
|
||||||
dev->regs.gpio_dir = val & 0xff;
|
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;
|
break;
|
||||||
case 0x42:
|
case 0x42:
|
||||||
/* GPIO port Output Value */
|
/* GPIO port Output Value */
|
||||||
if (size == 1)
|
if (size == 1) {
|
||||||
dev->regs.gpio_val = val & 0xff;
|
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;
|
break;
|
||||||
case 0x46: case 0x47:
|
case 0x46: case 0x47:
|
||||||
/* GPO Port Output Value */
|
/* GPO Port Output Value */
|
||||||
@@ -1184,6 +1206,12 @@ acpi_close(void *priv)
|
|||||||
{
|
{
|
||||||
acpi_t *dev = (acpi_t *) 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);
|
timer_disable(&dev->timer);
|
||||||
|
|
||||||
free(dev);
|
free(dev);
|
||||||
@@ -1206,6 +1234,9 @@ acpi_init(const device_t *info)
|
|||||||
if (dev->vendor == VEN_INTEL) {
|
if (dev->vendor == VEN_INTEL) {
|
||||||
dev->apm = device_add(&apm_pci_acpi_device);
|
dev->apm = device_add(&apm_pci_acpi_device);
|
||||||
io_sethandler(0x00b2, 0x0002, acpi_apm_in, NULL, NULL, acpi_apm_out, NULL, NULL, dev);
|
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);
|
timer_add(&dev->timer, acpi_timer_count, dev, 0);
|
||||||
|
|||||||
@@ -41,17 +41,14 @@ typedef struct {
|
|||||||
uint16_t regs[32];
|
uint16_t regs[32];
|
||||||
uint8_t addr_register;
|
uint8_t addr_register;
|
||||||
|
|
||||||
uint8_t i2c_addr;
|
uint8_t i2c_addr, i2c_state;
|
||||||
} gl518sm_t;
|
} gl518sm_t;
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
static uint8_t gl518sm_i2c_read_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv);
|
static uint8_t gl518sm_i2c_read(void *bus, uint8_t addr, void *priv);
|
||||||
static uint16_t gl518sm_i2c_read_word_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv);
|
|
||||||
static uint16_t gl518sm_read(gl518sm_t *dev, uint8_t reg);
|
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 uint8_t gl518sm_i2c_write(void *bus, uint8_t addr, uint8_t data, 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_write(gl518sm_t *dev, uint8_t reg, uint16_t val);
|
static uint8_t gl518sm_write(gl518sm_t *dev, uint8_t reg, uint16_t val);
|
||||||
static void gl518sm_reset(gl518sm_t *dev);
|
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);
|
gl518sm_log("GL518SM: remapping to I2C %02Xh\n", addr);
|
||||||
|
|
||||||
i2c_removehandler(i2c_smbus, dev->i2c_addr, 1,
|
i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev);
|
||||||
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,
|
if (addr < 0x80)
|
||||||
NULL, gl518sm_i2c_read_byte, gl518sm_i2c_read_byte_cmd, gl518sm_i2c_read_word_cmd, NULL,
|
i2c_sethandler(i2c_smbus, addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev);
|
||||||
NULL, gl518sm_i2c_write_byte, gl518sm_i2c_write_byte_cmd, gl518sm_i2c_write_word_cmd, NULL,
|
|
||||||
dev);
|
|
||||||
|
|
||||||
dev->i2c_addr = addr;
|
dev->i2c_addr = addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static void
|
||||||
gl518sm_i2c_read_byte(void *bus, uint8_t addr, void *priv)
|
gl518sm_i2c_start(void *bus, uint8_t addr, void *priv)
|
||||||
{
|
{
|
||||||
gl518sm_t *dev = (gl518sm_t *) priv;
|
gl518sm_t *dev = (gl518sm_t *) priv;
|
||||||
return gl518sm_read(dev, dev->addr_register);
|
|
||||||
|
dev->i2c_state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
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;
|
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
|
dev->addr_register++;
|
||||||
gl518sm_i2c_read_word_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv)
|
|
||||||
{
|
return ret;
|
||||||
gl518sm_t *dev = (gl518sm_t *) priv;
|
|
||||||
return gl518sm_read(dev, cmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -157,37 +153,35 @@ gl518sm_read(gl518sm_t *dev, uint8_t reg)
|
|||||||
break;
|
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);
|
gl518sm_log("GL518SM: read(%02X) = %04X\n", reg, ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static uint8_t
|
||||||
gl518sm_i2c_write_byte(void *bus, uint8_t addr, uint8_t val, void *priv)
|
gl518sm_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
||||||
{
|
{
|
||||||
gl518sm_t *dev = (gl518sm_t *) priv;
|
gl518sm_t *dev = (gl518sm_t *) priv;
|
||||||
dev->addr_register = val;
|
|
||||||
|
switch (dev->i2c_state++) {
|
||||||
|
case 0:
|
||||||
|
dev->addr_register = data;
|
||||||
|
break;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,12 +30,9 @@
|
|||||||
#define LM75_TEMP_TO_REG(t) ((t) << 8)
|
#define LM75_TEMP_TO_REG(t) ((t) << 8)
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
static uint8_t lm75_i2c_read_byte_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv);
|
static uint8_t lm75_i2c_read(void *bus, uint8_t addr, void *priv);
|
||||||
static uint16_t lm75_i2c_read_word_cmd(void *bus, uint8_t addr, uint8_t cmd, void *priv);
|
static uint8_t lm75_i2c_write(void *bus, uint8_t addr, uint8_t data, 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_reset(lm75_t *dev);
|
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);
|
lm75_log("LM75: remapping to I2C %02Xh\n", addr);
|
||||||
|
|
||||||
if (dev->i2c_addr < 0x80) i2c_removehandler(i2c_smbus, dev->i2c_addr, 1,
|
if (dev->i2c_addr < 0x80)
|
||||||
NULL, lm75_i2c_read_byte, lm75_i2c_read_byte_cmd, lm75_i2c_read_word_cmd, NULL,
|
i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev);
|
||||||
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,
|
if (addr < 0x80)
|
||||||
NULL, lm75_i2c_read_byte, lm75_i2c_read_byte_cmd, lm75_i2c_read_word_cmd, NULL,
|
i2c_sethandler(i2c_smbus, addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev);
|
||||||
NULL, lm75_i2c_write_byte, lm75_i2c_write_byte_cmd, lm75_i2c_write_word_cmd, NULL,
|
|
||||||
dev);
|
|
||||||
|
|
||||||
dev->i2c_addr = addr;
|
dev->i2c_addr = addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static void
|
||||||
lm75_i2c_read_byte(void *bus, uint8_t addr, void *priv)
|
lm75_i2c_start(void *bus, uint8_t addr, void *priv)
|
||||||
{
|
{
|
||||||
lm75_t *dev = (lm75_t *) priv;
|
lm75_t *dev = (lm75_t *) priv;
|
||||||
return lm75_read(dev, dev->addr_register);
|
|
||||||
|
dev->i2c_state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
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;
|
lm75_t *dev = (lm75_t *) priv;
|
||||||
return lm75_read(dev, cmd);
|
uint8_t ret = 0;
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t
|
switch (dev->addr_register & 0x3) {
|
||||||
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) {
|
|
||||||
case 0x0: /* temperature */
|
case 0x0: /* temperature */
|
||||||
rethi = lm75_read(dev, 0x0);
|
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x1 : 0x0);
|
||||||
retlo = lm75_read(dev, 0x1);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1: /* configuration */
|
case 0x1: /* configuration */
|
||||||
rethi = retlo = lm75_read(dev, 0x2);
|
ret = lm75_read(dev, 0x2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2: /* Thyst */
|
case 0x2: /* Thyst */
|
||||||
rethi = lm75_read(dev, 0x3);
|
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x4 : 0x3);
|
||||||
retlo = lm75_read(dev, 0x4);
|
|
||||||
break;
|
break;
|
||||||
case 0x3: /* Tos */
|
case 0x3: /* Tos */
|
||||||
rethi = lm75_read(dev, 0x5);
|
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x6 : 0x5);
|
||||||
retlo = lm75_read(dev, 0x6);
|
|
||||||
break;
|
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
|
/* The AS99127F hardware monitor uses the addresses of its LM75 devices
|
||||||
to access some of its proprietary registers. Pass this operation on to
|
to access some of its proprietary registers. Pass this operation on to
|
||||||
the main monitor address through an internal I2C call, if necessary. */
|
the main monitor address through an internal I2C call, if necessary. */
|
||||||
if ((reg > 0x7) && ((reg & 0xf8) != 0x50) && (dev->as99127f_i2c_addr < 0x80))
|
if ((reg > 0x7) && ((reg & 0xf8) != 0x50) && (dev->as99127f_i2c_addr < 0x80)) {
|
||||||
ret = i2c_read_byte_cmd(i2c_smbus, dev->as99127f_i2c_addr, reg);
|
i2c_start(i2c_smbus, dev->as99127f_i2c_addr);
|
||||||
else if ((reg & 0x7) == 0x0) /* temperature high byte */
|
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;
|
ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]) >> 8;
|
||||||
else if ((reg & 0x7) == 0x1) /* temperature low byte */
|
else if ((reg & 0x7) == 0x1) /* temperature low byte */
|
||||||
ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]);
|
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
|
static uint8_t
|
||||||
lm75_i2c_write_byte(void *bus, uint8_t addr, uint8_t val, void *priv)
|
lm75_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
||||||
{
|
{
|
||||||
lm75_t *dev = (lm75_t *) 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (dev->addr_register & 0x3) {
|
||||||
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) {
|
|
||||||
case 0x0: /* temperature */
|
case 0x0: /* temperature */
|
||||||
lm75_write(dev, 0x0, valhi);
|
lm75_write(dev, (dev->i2c_state == 1) ? 0x1 : 0x0, data);
|
||||||
lm75_write(dev, 0x1, vallo);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1: /* configuration */
|
case 0x1: /* configuration */
|
||||||
lm75_write(dev, 0x2, vallo);
|
lm75_write(dev, 0x2, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2: /* Thyst */
|
case 0x2: /* Thyst */
|
||||||
lm75_write(dev, 0x3, valhi);
|
lm75_write(dev, (dev->i2c_state == 1) ? 0x4 : 0x3, data);
|
||||||
lm75_write(dev, 0x4, vallo);
|
|
||||||
break;
|
break;
|
||||||
case 0x3: /* Tos */
|
case 0x3: /* Tos */
|
||||||
lm75_write(dev, 0x5, valhi);
|
lm75_write(dev, (dev->i2c_state == 1) ? 0x6 : 0x5, data);
|
||||||
lm75_write(dev, 0x6, vallo);
|
|
||||||
break;
|
|
||||||
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
|
to access some of its proprietary registers. Pass this operation on to
|
||||||
the main monitor address through an internal I2C call, if necessary. */
|
the main monitor address through an internal I2C call, if necessary. */
|
||||||
if ((reg > 0x7) && ((reg & 0xf8) != 0x50) && (dev->as99127f_i2c_addr < 0x80)) {
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,19 +56,16 @@ typedef struct {
|
|||||||
uint8_t addr_register;
|
uint8_t addr_register;
|
||||||
uint8_t data_register;
|
uint8_t data_register;
|
||||||
|
|
||||||
uint8_t i2c_addr;
|
uint8_t i2c_addr, i2c_state;
|
||||||
} lm78_t;
|
} 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_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(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_read(lm78_t *dev, uint8_t reg, uint8_t bank);
|
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_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 data, 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_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank);
|
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);
|
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;
|
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,
|
i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, lm78_i2c_start, lm78_i2c_read, lm78_i2c_write, NULL, dev);
|
||||||
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,
|
if (addr < 0x80)
|
||||||
NULL, lm78_i2c_read_byte, lm78_i2c_read_byte_cmd, lm78_i2c_read_word_cmd, NULL,
|
i2c_sethandler(i2c_smbus, addr, 1, lm78_i2c_start, lm78_i2c_read, lm78_i2c_write, NULL, dev);
|
||||||
NULL, lm78_i2c_write_byte, lm78_i2c_write_byte_cmd, lm78_i2c_write_word_cmd, NULL,
|
|
||||||
dev);
|
|
||||||
|
|
||||||
dev->i2c_addr = addr;
|
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
|
static uint8_t
|
||||||
lm78_isa_read(uint16_t port, void *priv)
|
lm78_isa_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
@@ -159,26 +160,11 @@ lm78_isa_read(uint16_t port, void *priv)
|
|||||||
|
|
||||||
|
|
||||||
static uint8_t
|
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;
|
lm78_t *dev = (lm78_t *) priv;
|
||||||
return lm78_read(dev, dev->addr_register, LM78_WINBOND_BANK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -264,27 +250,18 @@ lm78_isa_write(uint16_t port, uint8_t val, void *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static uint8_t
|
||||||
lm78_i2c_write_byte(void *bus, uint8_t addr, uint8_t val, void *priv)
|
lm78_i2c_write(void *bus, uint8_t addr, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
lm78_t *dev = (lm78_t *) priv;
|
lm78_t *dev = (lm78_t *) priv;
|
||||||
|
|
||||||
|
if (dev->i2c_state == 0) {
|
||||||
|
dev->i2c_state = 1;
|
||||||
dev->addr_register = val;
|
dev->addr_register = val;
|
||||||
}
|
} else
|
||||||
|
lm78_write(dev, dev->addr_register++, val, LM78_WINBOND_BANK);
|
||||||
|
|
||||||
|
return 1;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
327
src/device/i2c.c
327
src/device/i2c.c
@@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the 86Box distribution.
|
* 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_ {
|
typedef struct _i2c_ {
|
||||||
void (*read_quick)(void *bus, uint8_t addr, void *priv);
|
void (*start)(void *bus, uint8_t addr, void *priv);
|
||||||
uint8_t (*read_byte)(void *bus, uint8_t addr, void *priv);
|
uint8_t (*read)(void *bus, uint8_t addr, void *priv);
|
||||||
uint8_t (*read_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv);
|
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv);
|
||||||
uint16_t (*read_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv);
|
void (*stop)(void *bus, uint8_t addr, 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 *priv;
|
void *priv;
|
||||||
|
|
||||||
@@ -55,7 +48,7 @@ typedef struct {
|
|||||||
|
|
||||||
void *i2c_smbus;
|
void *i2c_smbus;
|
||||||
|
|
||||||
#define ENABLE_I2C_LOG 1
|
|
||||||
#ifdef ENABLE_I2C_LOG
|
#ifdef ENABLE_I2C_LOG
|
||||||
int i2c_do_log = ENABLE_I2C_LOG;
|
int i2c_do_log = ENABLE_I2C_LOG;
|
||||||
|
|
||||||
@@ -100,16 +93,10 @@ i2c_removebus(void *bus_handle)
|
|||||||
|
|
||||||
void
|
void
|
||||||
i2c_sethandler(void *bus_handle, uint8_t base, int size,
|
i2c_sethandler(void *bus_handle, uint8_t base, int size,
|
||||||
void (*read_quick)(void *bus, uint8_t addr, void *priv),
|
void (*start)(void *bus, uint8_t addr, void *priv),
|
||||||
uint8_t (*read_byte)(void *bus, uint8_t addr, void *priv),
|
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||||
uint8_t (*read_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||||
uint16_t (*read_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
void (*stop)(void *bus, uint8_t addr, 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 *priv)
|
void *priv)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
@@ -131,15 +118,10 @@ i2c_sethandler(void *bus_handle, uint8_t base, int size,
|
|||||||
q->prev = NULL;
|
q->prev = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
q->read_byte = read_byte;
|
q->start = start;
|
||||||
q->read_byte_cmd = read_byte_cmd;
|
q->read = read;
|
||||||
q->read_word_cmd = read_word_cmd;
|
q->write = write;
|
||||||
q->read_block_cmd = read_block_cmd;
|
q->stop = stop;
|
||||||
|
|
||||||
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->priv = priv;
|
q->priv = priv;
|
||||||
q->next = NULL;
|
q->next = NULL;
|
||||||
@@ -151,16 +133,10 @@ i2c_sethandler(void *bus_handle, uint8_t base, int size,
|
|||||||
|
|
||||||
void
|
void
|
||||||
i2c_removehandler(void *bus_handle, uint8_t base, int size,
|
i2c_removehandler(void *bus_handle, uint8_t base, int size,
|
||||||
void (*read_quick)(void *bus, uint8_t addr, void *priv),
|
void (*start)(void *bus, uint8_t addr, void *priv),
|
||||||
uint8_t (*read_byte)(void *bus, uint8_t addr, void *priv),
|
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||||
uint8_t (*read_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||||
uint16_t (*read_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
void (*stop)(void *bus, uint8_t addr, 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 *priv)
|
void *priv)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
@@ -176,11 +152,7 @@ i2c_removehandler(void *bus_handle, uint8_t base, int size,
|
|||||||
continue;
|
continue;
|
||||||
while(p) {
|
while(p) {
|
||||||
q = p->next;
|
q = p->next;
|
||||||
if ((p->read_byte == read_byte) && (p->read_byte_cmd == read_byte_cmd) &&
|
if ((p->read == read) && (p->write == write) && (p->priv == priv)) {
|
||||||
(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->prev)
|
if (p->prev)
|
||||||
p->prev->next = p->next;
|
p->prev->next = p->next;
|
||||||
else
|
else
|
||||||
@@ -201,22 +173,16 @@ i2c_removehandler(void *bus_handle, uint8_t base, int size,
|
|||||||
|
|
||||||
void
|
void
|
||||||
i2c_handler(int set, void *bus_handle, uint8_t base, int size,
|
i2c_handler(int set, void *bus_handle, uint8_t base, int size,
|
||||||
void (*read_quick)(void *bus, uint8_t addr, void *priv),
|
void (*start)(void *bus, uint8_t addr, void *priv),
|
||||||
uint8_t (*read_byte)(void *bus, uint8_t addr, void *priv),
|
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||||
uint8_t (*read_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||||
uint16_t (*read_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
void (*stop)(void *bus, uint8_t addr, 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 *priv)
|
void *priv)
|
||||||
{
|
{
|
||||||
if (set)
|
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
|
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
|
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_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||||
i2c_t *p;
|
i2c_t *p;
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
if (!bus)
|
if (!bus)
|
||||||
return;
|
return;
|
||||||
@@ -245,106 +210,23 @@ i2c_read_quick(void *bus_handle, uint8_t addr)
|
|||||||
p = bus->devices[addr];
|
p = bus->devices[addr];
|
||||||
if (p) {
|
if (p) {
|
||||||
while(p) {
|
while(p) {
|
||||||
if (p->read_byte) {
|
if (p->start) {
|
||||||
p->read_quick(bus_handle, addr, p->priv);
|
p->start(bus_handle, addr, p->priv);
|
||||||
found++;
|
|
||||||
}
|
}
|
||||||
p = p->next;
|
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
|
uint8_t
|
||||||
i2c_read_byte(void *bus_handle, uint8_t addr)
|
i2c_read(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)
|
|
||||||
{
|
{
|
||||||
uint8_t ret = 0;
|
uint8_t ret = 0;
|
||||||
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
i2c_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||||
i2c_t *p;
|
i2c_t *p;
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
if (!bus)
|
if (!bus)
|
||||||
return(ret);
|
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];
|
p = bus->devices[addr];
|
||||||
if (p) {
|
if (p) {
|
||||||
while(p) {
|
while(p) {
|
||||||
if (p->read_block_cmd) {
|
if (p->read) {
|
||||||
ret = MAX(ret, p->read_block_cmd(bus_handle, addr, cmd, data, len, p->priv));
|
ret = p->read(bus_handle, addr, p->priv);
|
||||||
found++;
|
break;
|
||||||
}
|
}
|
||||||
p = p->next;
|
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);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
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_bus_t *bus = (i2c_bus_t *) bus_handle;
|
||||||
i2c_t *p;
|
i2c_t *p;
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
if (!bus)
|
if (!bus)
|
||||||
return;
|
return;
|
||||||
@@ -379,118 +286,12 @@ i2c_write_quick(void *bus_handle, uint8_t addr)
|
|||||||
p = bus->devices[addr];
|
p = bus->devices[addr];
|
||||||
if (p) {
|
if (p) {
|
||||||
while(p) {
|
while(p) {
|
||||||
if (p->read_byte) {
|
if (p->stop) {
|
||||||
p->write_quick(bus_handle, addr, p->priv);
|
p->stop(bus_handle, addr, p->priv);
|
||||||
found++;
|
|
||||||
}
|
}
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_log("I2C: write_quick(%s, %02X)\n", bus->name, addr);
|
i2c_log("I2C: stop(%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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
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.
|
* 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 2008-2020 Sarah Walker.
|
||||||
* Copyright 2020 RichardG.
|
* Copyright 2020 RichardG.
|
||||||
*/
|
*/
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stddef.h>
|
#include <string.h>
|
||||||
|
#define HAVE_STDARG_H
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <math.h>
|
|
||||||
#include <86box/86box.h>
|
#include <86box/86box.h>
|
||||||
#include <86box/i2c.h>
|
#include <86box/i2c.h>
|
||||||
|
|
||||||
@@ -53,8 +53,8 @@ enum {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *i2c;
|
void *i2c;
|
||||||
uint8_t scl, sda, state, slave_state, slave_addr, slave_reg,
|
uint8_t scl, sda, state, slave_state, slave_addr,
|
||||||
slave_writing, slave_rw, last_sda, pos, transmit, byte;
|
slave_rw, last_sda, pos, transmit, byte;
|
||||||
} i2c_gpio_t;
|
} i2c_gpio_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -66,6 +66,7 @@ i2c_gpio_init(char *bus_name)
|
|||||||
|
|
||||||
dev->i2c = i2c_addbus(bus_name);
|
dev->i2c = i2c_addbus(bus_name);
|
||||||
dev->scl = dev->sda = 1;
|
dev->scl = dev->sda = 1;
|
||||||
|
dev->slave_addr = 0xff;
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
@@ -85,49 +86,46 @@ i2c_gpio_close(void *dev_handle)
|
|||||||
void
|
void
|
||||||
i2c_gpio_next_byte(i2c_gpio_t *dev)
|
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
|
void
|
||||||
i2c_gpio_write(i2c_gpio_t *dev)
|
i2c_gpio_write(i2c_gpio_t *dev)
|
||||||
{
|
{
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
switch (dev->slave_state) {
|
switch (dev->slave_state) {
|
||||||
case SLAVE_IDLE:
|
case SLAVE_IDLE:
|
||||||
|
i = dev->slave_addr;
|
||||||
dev->slave_addr = dev->byte >> 1;
|
dev->slave_addr = dev->byte >> 1;
|
||||||
|
dev->slave_rw = dev->byte & 1;
|
||||||
|
|
||||||
if (!i2c_has_device(dev->i2c, dev->slave_addr)) {
|
if (!i2c_has_device(dev->i2c, dev->slave_addr)) {
|
||||||
dev->slave_state = SLAVE_INVALID;
|
dev->slave_state = SLAVE_INVALID;
|
||||||
break;
|
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) {
|
if (dev->slave_rw) {
|
||||||
dev->slave_state = SLAVE_SENDDATA;
|
dev->slave_state = SLAVE_SENDDATA;
|
||||||
dev->transmit = TRANSMITTER_SLAVE;
|
dev->transmit = TRANSMITTER_SLAVE;
|
||||||
dev->byte = i2c_read_byte(dev->i2c, dev->slave_addr);
|
dev->byte = i2c_read(dev->i2c, dev->slave_addr);
|
||||||
} else {
|
} else {
|
||||||
dev->slave_state = SLAVE_RECEIVEADDR;
|
dev->slave_state = SLAVE_RECEIVEADDR;
|
||||||
dev->transmit = TRANSMITTER_MASTER;
|
dev->transmit = TRANSMITTER_MASTER;
|
||||||
}
|
}
|
||||||
pclog("slave_idle %02X %d\n", dev->slave_addr, dev->slave_rw);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SLAVE_RECEIVEADDR:
|
case SLAVE_RECEIVEADDR:
|
||||||
pclog("slave_receiveaddr %02X %d\n", dev->slave_addr, dev->slave_rw);
|
i2c_write(dev->i2c, dev->slave_addr, dev->byte);
|
||||||
i2c_write_byte(dev->i2c, dev->slave_addr, dev->byte);
|
|
||||||
dev->slave_writing = 1;
|
|
||||||
dev->slave_reg = dev->byte;
|
|
||||||
dev->slave_state = dev->slave_rw ? SLAVE_SENDDATA : SLAVE_RECEIVEDATA;
|
dev->slave_state = dev->slave_rw ? SLAVE_SENDDATA : SLAVE_RECEIVEDATA;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SLAVE_RECEIVEDATA:
|
case SLAVE_RECEIVEDATA:
|
||||||
pclog("slave_receivedata %02X %d = %02X\n", dev->slave_addr, dev->slave_rw, dev->byte);
|
i2c_write(dev->i2c, dev->slave_addr, 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);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,10 +134,9 @@ i2c_gpio_write(i2c_gpio_t *dev)
|
|||||||
void
|
void
|
||||||
i2c_gpio_stop(i2c_gpio_t *dev)
|
i2c_gpio_stop(i2c_gpio_t *dev)
|
||||||
{
|
{
|
||||||
pclog("stopping... state = %d\n", dev->slave_state);
|
i2c_stop(dev->i2c, dev->slave_addr);
|
||||||
if (dev->slave_writing)
|
|
||||||
i2c_write_byte(dev->i2c, dev->slave_addr, dev->slave_reg);
|
|
||||||
|
|
||||||
|
dev->slave_addr = 0xff;
|
||||||
dev->slave_state = SLAVE_IDLE;
|
dev->slave_state = SLAVE_IDLE;
|
||||||
dev->transmit = TRANSMITTER_MASTER;
|
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;
|
smbus_piix4_t *dev = (smbus_piix4_t *) priv;
|
||||||
uint8_t smbus_addr, smbus_read, prev_stat;
|
uint8_t smbus_addr, smbus_read, prev_stat;
|
||||||
uint16_t temp;
|
|
||||||
|
|
||||||
smbus_piix4_log("SMBus PIIX4: write(%02X, %02X)\n", addr, val);
|
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;
|
smbus_read = dev->addr & 0x01;
|
||||||
|
|
||||||
|
/* start transaction */
|
||||||
|
i2c_start(i2c_smbus, smbus_addr);
|
||||||
|
|
||||||
/* decode the 3-bit command protocol */
|
/* decode the 3-bit command protocol */
|
||||||
dev->next_stat = 0x2; /* raise INTER (command completed) by default */
|
dev->next_stat = 0x2; /* raise INTER (command completed) by default */
|
||||||
switch ((val >> 2) & 0x7) {
|
switch ((val >> 2) & 0x7) {
|
||||||
case 0x0: /* quick R/W */
|
case 0x0: /* quick R/W */
|
||||||
if (smbus_read)
|
|
||||||
i2c_read_quick(i2c_smbus, smbus_addr);
|
|
||||||
else
|
|
||||||
i2c_write_quick(i2c_smbus, smbus_addr);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1: /* byte R/W */
|
case 0x1: /* byte R/W */
|
||||||
if (smbus_read)
|
if (smbus_read)
|
||||||
dev->data0 = i2c_read_byte(i2c_smbus, smbus_addr);
|
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||||
else
|
else
|
||||||
i2c_write_byte(i2c_smbus, smbus_addr, dev->data0);
|
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2: /* byte data R/W */
|
case 0x2: /* byte data R/W */
|
||||||
|
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||||
if (smbus_read)
|
if (smbus_read)
|
||||||
dev->data0 = i2c_read_byte_cmd(i2c_smbus, smbus_addr, dev->cmd);
|
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||||
else
|
else
|
||||||
i2c_write_byte_cmd(i2c_smbus, smbus_addr, dev->cmd, dev->data0);
|
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x3: /* word data R/W */
|
case 0x3: /* word data R/W */
|
||||||
|
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||||
if (smbus_read) {
|
if (smbus_read) {
|
||||||
temp = i2c_read_word_cmd(i2c_smbus, smbus_addr, dev->cmd);
|
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||||
dev->data0 = temp;
|
dev->data1 = i2c_read(i2c_smbus, smbus_addr);
|
||||||
dev->data1 = temp >> 8;
|
|
||||||
} else {
|
} else {
|
||||||
temp = (dev->data1 << 8) | dev->data0;
|
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||||
i2c_write_word_cmd(i2c_smbus, smbus_addr, dev->cmd, temp);
|
i2c_write(i2c_smbus, smbus_addr, dev->data1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x5: /* block R/W */
|
case 0x5: /* block R/W */
|
||||||
if (smbus_read)
|
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||||
dev->data0 = i2c_read_block_cmd(i2c_smbus, smbus_addr, dev->cmd, dev->data, SMBUS_PIIX4_BLOCK_DATA_SIZE);
|
/* SMBus block data is preceded by a length */
|
||||||
else
|
if (smbus_read) {
|
||||||
i2c_write_block_cmd(i2c_smbus, smbus_addr, dev->cmd, dev->data, dev->data0);
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -179,6 +185,9 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
dev->next_stat = 0x4;
|
dev->next_stat = 0x4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* stop transaction */
|
||||||
|
i2c_stop(i2c_smbus, smbus_addr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -244,7 +253,7 @@ smbus_piix4_init(const device_t *info)
|
|||||||
smbus_piix4_t *dev = (smbus_piix4_t *) malloc(sizeof(smbus_piix4_t));
|
smbus_piix4_t *dev = (smbus_piix4_t *) malloc(sizeof(smbus_piix4_t));
|
||||||
memset(dev, 0, 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);
|
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;
|
smbus_piix4_t *dev = (smbus_piix4_t *) priv;
|
||||||
|
|
||||||
i2c_removebus(i2c_smbus);
|
if (i2c_smbus == dev->i2c)
|
||||||
i2c_smbus = NULL;
|
i2c_smbus = NULL;
|
||||||
|
i2c_removebus(dev->i2c);
|
||||||
|
|
||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ typedef struct
|
|||||||
pc_timer_t timer;
|
pc_timer_t timer;
|
||||||
nvr_t *nvr;
|
nvr_t *nvr;
|
||||||
apm_t *apm;
|
apm_t *apm;
|
||||||
|
void *i2c;
|
||||||
} acpi_t;
|
} acpi_t;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ typedef struct {
|
|||||||
uint8_t regs[8];
|
uint8_t regs[8];
|
||||||
uint8_t addr_register;
|
uint8_t addr_register;
|
||||||
uint8_t temp_idx;
|
uint8_t temp_idx;
|
||||||
uint8_t i2c_addr;
|
uint8_t i2c_addr, i2c_state;
|
||||||
|
|
||||||
uint8_t as99127f_i2c_addr;
|
uint8_t as99127f_i2c_addr;
|
||||||
} lm75_t;
|
} lm75_t;
|
||||||
|
|||||||
@@ -27,55 +27,35 @@ extern void *i2c_addbus(char *name);
|
|||||||
extern void i2c_removebus(void *bus_handle);
|
extern void i2c_removebus(void *bus_handle);
|
||||||
|
|
||||||
extern void i2c_sethandler(void *bus_handle, uint8_t base, int size,
|
extern void i2c_sethandler(void *bus_handle, uint8_t base, int size,
|
||||||
void (*read_quick)(void *bus, uint8_t addr, void *priv),
|
void (*start)(void *bus, uint8_t addr, void *priv),
|
||||||
uint8_t (*read_byte)(void *bus, uint8_t addr, void *priv),
|
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||||
uint8_t (*read_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||||
uint16_t (*read_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
void (*stop)(void *bus, uint8_t addr, 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 *priv);
|
void *priv);
|
||||||
|
|
||||||
extern void i2c_removehandler(void *bus_handle, uint8_t base, int size,
|
extern void i2c_removehandler(void *bus_handle, uint8_t base, int size,
|
||||||
void (*read_quick)(void *bus, uint8_t addr, void *priv),
|
void (*start)(void *bus, uint8_t addr, void *priv),
|
||||||
uint8_t (*read_byte)(void *bus, uint8_t addr, void *priv),
|
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||||
uint8_t (*read_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||||
uint16_t (*read_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
void (*stop)(void *bus, uint8_t addr, 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 *priv);
|
void *priv);
|
||||||
|
|
||||||
extern void i2c_handler(int set, void *bus_handle, uint8_t base, int size,
|
extern void i2c_handler(int set, void *bus_handle, uint8_t base, int size,
|
||||||
void (*read_quick)(void *bus, uint8_t addr, void *priv),
|
void (*start)(void *bus, uint8_t addr, void *priv),
|
||||||
uint8_t (*read_byte)(void *bus, uint8_t addr, void *priv),
|
uint8_t (*read)(void *bus, uint8_t addr, void *priv),
|
||||||
uint8_t (*read_byte_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
uint8_t (*write)(void *bus, uint8_t addr, uint8_t data, void *priv),
|
||||||
uint16_t (*read_word_cmd)(void *bus, uint8_t addr, uint8_t cmd, void *priv),
|
void (*stop)(void *bus, uint8_t addr, 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 *priv);
|
void *priv);
|
||||||
|
|
||||||
extern uint8_t i2c_has_device(void *bus_handle, uint8_t addr);
|
extern uint8_t i2c_has_device(void *bus_handle, uint8_t addr);
|
||||||
extern void i2c_read_quick(void *bus_handle, uint8_t addr);
|
extern void i2c_start(void *bus_handle, uint8_t addr);
|
||||||
extern uint8_t i2c_read_byte(void *bus_handle, uint8_t addr);
|
extern uint8_t i2c_read(void *bus_handle, uint8_t addr);
|
||||||
extern uint8_t i2c_read_byte_cmd(void *bus_handle, uint8_t addr, uint8_t cmd);
|
extern uint8_t i2c_write(void *bus_handle, uint8_t addr, uint8_t data);
|
||||||
extern uint16_t i2c_read_word_cmd(void *bus_handle, uint8_t addr, uint8_t cmd);
|
extern void i2c_stop(void *bus_handle, uint8_t addr);
|
||||||
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);
|
/* i2c_eeprom.c */
|
||||||
extern void i2c_write_byte(void *bus_handle, uint8_t addr, uint8_t val);
|
extern void *i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint16_t size, uint8_t writable);
|
||||||
extern void i2c_write_byte_cmd(void *bus_handle, uint8_t addr, uint8_t cmd, uint8_t val);
|
extern void i2c_eeprom_close(void *dev_handle);
|
||||||
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);
|
|
||||||
|
|
||||||
/* i2c_gpio.c */
|
/* i2c_gpio.c */
|
||||||
extern void *i2c_gpio_init(char *bus_name);
|
extern void *i2c_gpio_init(char *bus_name);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ typedef struct
|
|||||||
index,
|
index,
|
||||||
data[SMBUS_PIIX4_BLOCK_DATA_SIZE];
|
data[SMBUS_PIIX4_BLOCK_DATA_SIZE];
|
||||||
pc_timer_t response_timer;
|
pc_timer_t response_timer;
|
||||||
|
void *i2c;
|
||||||
} smbus_piix4_t;
|
} smbus_piix4_t;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -47,17 +47,17 @@
|
|||||||
#define SPD_SDR_ATTR_VCC_HI_5 0x20
|
#define SPD_SDR_ATTR_VCC_HI_5 0x20
|
||||||
|
|
||||||
|
|
||||||
typedef struct _spd_ {
|
typedef struct {
|
||||||
const device_t *info;
|
const device_t *info;
|
||||||
uint8_t slot;
|
uint8_t slot;
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
uint16_t row1;
|
uint16_t row1;
|
||||||
uint16_t row2;
|
uint16_t row2;
|
||||||
|
|
||||||
uint8_t addr_register;
|
void *eeprom;
|
||||||
} spd_t;
|
} spd_t;
|
||||||
|
|
||||||
typedef struct _spd_edo_ {
|
typedef struct {
|
||||||
uint8_t bytes_used, spd_size, mem_type,
|
uint8_t bytes_used, spd_size, mem_type,
|
||||||
row_bits, col_bits, banks,
|
row_bits, col_bits, banks,
|
||||||
data_width_lsb, data_width_msb,
|
data_width_lsb, data_width_msb,
|
||||||
@@ -75,7 +75,7 @@ typedef struct _spd_edo_ {
|
|||||||
checksum2;
|
checksum2;
|
||||||
} spd_edo_t;
|
} spd_edo_t;
|
||||||
|
|
||||||
typedef struct _spd_sdram_ {
|
typedef struct {
|
||||||
uint8_t bytes_used, spd_size, mem_type,
|
uint8_t bytes_used, spd_size, mem_type,
|
||||||
row_bits, col_bits, rows,
|
row_bits, col_bits, rows,
|
||||||
data_width_lsb, data_width_msb,
|
data_width_lsb, data_width_msb,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#ifndef EMU_VID_DDC_H
|
#ifndef EMU_VID_DDC_H
|
||||||
# define 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*/
|
#endif /*EMU_VID_DDC_H*/
|
||||||
|
|||||||
@@ -57,49 +57,6 @@ spd_log(const char *fmt, ...)
|
|||||||
#endif
|
#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
|
static void
|
||||||
spd_close(void *priv)
|
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);
|
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,
|
i2c_eeprom_close(dev->eeprom);
|
||||||
NULL, spd_read_byte, spd_read_byte_cmd, spd_read_word_cmd, spd_read_block_cmd,
|
|
||||||
NULL, spd_write_byte, NULL, NULL, NULL,
|
|
||||||
dev);
|
|
||||||
|
|
||||||
spd_present = 0;
|
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);
|
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,
|
dev->eeprom = i2c_eeprom_init(i2c_smbus, SPD_BASE_ADDR + dev->slot, spd_data[info->local], SPD_DATA_SIZE, 0);
|
||||||
NULL, spd_read_byte, spd_read_byte_cmd, spd_read_word_cmd, spd_read_block_cmd,
|
|
||||||
NULL, spd_write_byte, NULL, NULL, NULL,
|
|
||||||
dev);
|
|
||||||
|
|
||||||
spd_present = 1;
|
spd_present = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ typedef struct mach64_t
|
|||||||
|
|
||||||
int overlay_v_acc;
|
int overlay_v_acc;
|
||||||
|
|
||||||
void *i2c;
|
void *i2c, *ddc;
|
||||||
} mach64_t;
|
} mach64_t;
|
||||||
|
|
||||||
static video_timings_t timing_mach64_isa = {VIDEO_ISA, 3, 3, 6, 5, 5, 10};
|
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->fifo_thread = thread_create(fifo_thread, mach64);
|
||||||
|
|
||||||
mach64->i2c = i2c_gpio_init("ddc_ati_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;
|
return mach64;
|
||||||
}
|
}
|
||||||
@@ -3464,6 +3464,9 @@ void mach64_close(void *p)
|
|||||||
thread_destroy_event(mach64->wake_fifo_thread);
|
thread_destroy_event(mach64->wake_fifo_thread);
|
||||||
thread_destroy_event(mach64->fifo_not_full_event);
|
thread_destroy_event(mach64->fifo_not_full_event);
|
||||||
|
|
||||||
|
ddc_close(mach64->ddc);
|
||||||
|
i2c_gpio_close(mach64->i2c);
|
||||||
|
|
||||||
free(mach64);
|
free(mach64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,11 +27,6 @@
|
|||||||
#include <86box/i2c.h>
|
#include <86box/i2c.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t addr_register;
|
|
||||||
} ddc_t;
|
|
||||||
|
|
||||||
|
|
||||||
static uint8_t edid_data[128] = {
|
static uint8_t edid_data[128] = {
|
||||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, /* Fixed header pattern */
|
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 */
|
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
|
void *
|
||||||
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
|
|
||||||
ddc_init(void *i2c)
|
ddc_init(void *i2c)
|
||||||
{
|
{
|
||||||
ddc_t *dev = (ddc_t *) malloc(sizeof(ddc_t));
|
|
||||||
memset(dev, 0, sizeof(ddc_t));
|
|
||||||
|
|
||||||
uint8_t checksum = 0;
|
uint8_t checksum = 0;
|
||||||
for (int c = 0; c < 127; c++)
|
for (int c = 0; c < 127; c++)
|
||||||
checksum += edid_data[c];
|
checksum += edid_data[c];
|
||||||
edid_data[127] = 256 - checksum;
|
edid_data[127] = 256 - checksum;
|
||||||
|
|
||||||
i2c_sethandler(i2c, 0x50, 1,
|
return i2c_eeprom_init(i2c, 0x50, edid_data, sizeof(edid_data), 0);
|
||||||
NULL, ddc_read_byte, ddc_read_byte_cmd, ddc_read_word_cmd, ddc_read_block_cmd,
|
}
|
||||||
NULL, ddc_write_byte, NULL, NULL, NULL,
|
|
||||||
dev);
|
|
||||||
|
void
|
||||||
|
ddc_close(void *dev_handle)
|
||||||
|
{
|
||||||
|
i2c_eeprom_close(dev_handle);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ typedef struct virge_t
|
|||||||
|
|
||||||
uint8_t serialport;
|
uint8_t serialport;
|
||||||
|
|
||||||
void *i2c;
|
void *i2c, *ddc;
|
||||||
} virge_t;
|
} virge_t;
|
||||||
|
|
||||||
static video_timings_t timing_diamond_stealth3d_2000_vlb = {VIDEO_BUS, 2, 2, 3, 28, 28, 45};
|
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->fifo_thread = thread_create(fifo_thread, virge);
|
||||||
|
|
||||||
virge->i2c = i2c_gpio_init("ddc_s3_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;
|
return virge;
|
||||||
}
|
}
|
||||||
@@ -3869,6 +3869,9 @@ static void s3_virge_close(void *p)
|
|||||||
|
|
||||||
svga_close(&virge->svga);
|
svga_close(&virge->svga);
|
||||||
|
|
||||||
|
ddc_close(virge->ddc);
|
||||||
|
i2c_gpio_close(virge->i2c);
|
||||||
|
|
||||||
free(virge);
|
free(virge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ typedef struct banshee_t
|
|||||||
|
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
void *i2c;
|
void *i2c, *ddc;
|
||||||
} banshee_t;
|
} banshee_t;
|
||||||
|
|
||||||
enum
|
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->vidSerialParallelPort = VIDSERIAL_DDC_DCK_W | VIDSERIAL_DDC_DDA_W;
|
||||||
|
|
||||||
banshee->i2c = i2c_gpio_init("ddc_voodoo_banshee");
|
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);
|
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_banshee);
|
||||||
|
|
||||||
@@ -2676,6 +2676,7 @@ static void banshee_close(void *p)
|
|||||||
|
|
||||||
voodoo_card_close(banshee->voodoo);
|
voodoo_card_close(banshee->voodoo);
|
||||||
svga_close(&banshee->svga);
|
svga_close(&banshee->svga);
|
||||||
|
ddc_close(banshee->ddc);
|
||||||
i2c_gpio_close(banshee->i2c);
|
i2c_gpio_close(banshee->i2c);
|
||||||
|
|
||||||
free(banshee);
|
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 \
|
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 \
|
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.o \
|
||||||
keyboard_xt.o keyboard_at.o \
|
keyboard_xt.o keyboard_at.o \
|
||||||
mouse.o \
|
mouse.o \
|
||||||
|
|||||||
Reference in New Issue
Block a user