DDC/I2C/SMBus overhaul (incomplete, commit for the night)

This commit is contained in:
RichardG867
2020-11-20 01:22:04 -03:00
parent 833635afaa
commit 886dbe09ea
18 changed files with 1368 additions and 1132 deletions

View File

@@ -25,11 +25,11 @@
#include <86box/device.h>
#include <86box/io.h>
#include "cpu.h"
#include <86box/smbus.h>
#include <86box/i2c.h>
#include <86box/hwm.h>
#define LM78_SMBUS 0x010000
#define LM78_I2C 0x010000
#define LM78_W83781D 0x020000
#define LM78_AS99127F_REV1 0x040000
#define LM78_AS99127F_REV2 0x080000
@@ -56,19 +56,19 @@ typedef struct {
uint8_t addr_register;
uint8_t data_register;
uint8_t smbus_addr;
uint8_t i2c_addr;
} lm78_t;
static uint8_t lm78_isa_read(uint16_t port, void *priv);
static uint8_t lm78_smbus_read_byte(uint8_t addr, void *priv);
static uint8_t lm78_smbus_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv);
static uint16_t lm78_smbus_read_word_cmd(uint8_t addr, uint8_t cmd, 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_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_smbus_write_byte(uint8_t addr, uint8_t val, void *priv);
static void lm78_smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv);
static void lm78_smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_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_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank);
static void lm78_reset(lm78_t *dev, uint8_t initialization);
@@ -98,29 +98,29 @@ lm78_remap(lm78_t *dev, uint8_t addr)
{
lm75_t *lm75;
if (!(dev->local & LM78_SMBUS)) return;
if (!(dev->local & LM78_I2C)) return;
lm78_log("LM78: remapping to SMBus %02Xh\n", addr);
lm78_log("LM78: remapping to I2C %02Xh\n", addr);
smbus_removehandler(dev->smbus_addr, 1,
lm78_smbus_read_byte, lm78_smbus_read_byte_cmd, lm78_smbus_read_word_cmd, NULL,
lm78_smbus_write_byte, lm78_smbus_write_byte_cmd, lm78_smbus_write_word_cmd, NULL,
dev);
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);
if (addr < 0x80) smbus_sethandler(addr, 1,
lm78_smbus_read_byte, lm78_smbus_read_byte_cmd, lm78_smbus_read_word_cmd, NULL,
lm78_smbus_write_byte, lm78_smbus_write_byte_cmd, lm78_smbus_write_word_cmd, 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);
dev->smbus_addr = addr;
dev->i2c_addr = addr;
if (dev->local & LM78_AS99127F) {
/* Store the main SMBus address on the LM75 devices to ensure reads/writes
/* Store the main I2C address on the LM75 devices to ensure reads/writes
to the AS99127F's proprietary registers are passed through to this side. */
for (uint8_t i = 0; i <= 1; i++) {
lm75 = device_get_priv(dev->lm75[i]);
if (lm75)
lm75->as99127f_smbus_addr = dev->smbus_addr;
lm75->as99127f_i2c_addr = dev->i2c_addr;
}
}
}
@@ -159,7 +159,7 @@ lm78_isa_read(uint16_t port, void *priv)
static uint8_t
lm78_smbus_read_byte(uint8_t addr, void *priv)
lm78_i2c_read_byte(void *bus, uint8_t addr, void *priv)
{
lm78_t *dev = (lm78_t *) priv;
return lm78_read(dev, dev->addr_register, LM78_WINBOND_BANK);
@@ -167,7 +167,7 @@ lm78_smbus_read_byte(uint8_t addr, void *priv)
static uint8_t
lm78_smbus_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv)
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);
@@ -175,7 +175,7 @@ lm78_smbus_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv)
static uint16_t
lm78_smbus_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv)
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);
@@ -265,7 +265,7 @@ lm78_isa_write(uint16_t port, uint8_t val, void *priv)
static void
lm78_smbus_write_byte(uint8_t addr, uint8_t val, void *priv)
lm78_i2c_write_byte(void *bus, uint8_t addr, uint8_t val, void *priv)
{
lm78_t *dev = (lm78_t *) priv;
dev->addr_register = val;
@@ -273,7 +273,7 @@ lm78_smbus_write_byte(uint8_t addr, uint8_t val, void *priv)
static void
lm78_smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv)
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);
@@ -281,7 +281,7 @@ lm78_smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv)
static void
lm78_smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv)
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);
@@ -354,13 +354,13 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank)
switch (reg) {
case 0x40:
if (val & 0x80) /* INITIALIZATION bit resets all registers except main SMBus address */
if (val & 0x80) /* INITIALIZATION bit resets all registers except main I2C address */
lm78_reset(dev, 1);
break;
case 0x48:
/* set main SMBus address */
if (dev->local & LM78_SMBUS)
/* set main I2C address */
if (dev->local & LM78_I2C)
lm78_remap(dev, dev->regs[0x48] & 0x7f);
break;
@@ -376,8 +376,8 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank)
break;
case 0x4a:
/* set LM75 SMBus addresses (Winbond only) */
if (dev->local & LM78_SMBUS) {
/* set LM75 I2C addresses (Winbond only) */
if (dev->local & LM78_I2C) {
for (uint8_t i = 0; i <= 1; i++) {
lm75 = device_get_priv(dev->lm75[i]);
if (!lm75)
@@ -412,10 +412,10 @@ lm78_reset(lm78_t *dev, uint8_t initialization)
dev->regs[0x40] = 0x08;
dev->regs[0x46] = 0x40;
dev->regs[0x47] = 0x50;
if (dev->local & LM78_SMBUS) {
if (!initialization) /* don't reset main SMBus address if the reset was triggered by the INITIALIZATION bit */
dev->smbus_addr = 0x2d;
dev->regs[0x48] = dev->smbus_addr;
if (dev->local & LM78_I2C) {
if (!initialization) /* don't reset main I2C address if the reset was triggered by the INITIALIZATION bit */
dev->i2c_addr = 0x2d;
dev->regs[0x48] = dev->i2c_addr;
if (dev->local & LM78_WINBOND)
dev->regs[0x4a] = 0x01;
} else {
@@ -469,7 +469,7 @@ lm78_reset(lm78_t *dev, uint8_t initialization)
dev->regs[0x49] = 0x40;
}
lm78_remap(dev, dev->smbus_addr);
lm78_remap(dev, dev->i2c_addr);
}
@@ -519,7 +519,7 @@ lm78_init(const device_t *info)
/* Set chip-specific default values. */
if (dev->local & LM78_AS99127F) {
/* AS99127: different -12V Rin value (bruteforced) */
/* AS99127: different -12V Rin value (bruteforced) */
defaults.voltages[5] = LM78_NEG_VOLTAGE(12000, 2400);
} else if (dev->local & LM78_W83782D) {
/* W83782D: different negative voltage formula */
@@ -536,7 +536,7 @@ lm78_init(const device_t *info)
dev->lm75[i] = (device_t *) malloc(sizeof(device_t));
memcpy(dev->lm75[i], &lm75_w83781d_device, sizeof(device_t));
dev->lm75[i]->local = (i + 1) << 8;
if (dev->local & LM78_SMBUS)
if (dev->local & LM78_I2C)
dev->lm75[i]->local |= 0x48 + i;
device_add(dev->lm75[i]);
} else {
@@ -558,7 +558,7 @@ lm78_init(const device_t *info)
const device_t lm78_device = {
"National Semiconductor LM78 Hardware Monitor",
DEVICE_ISA,
0x290 | LM78_SMBUS,
0x290 | LM78_I2C,
lm78_init, lm78_close, NULL,
{ NULL }, NULL, NULL,
NULL
@@ -569,19 +569,19 @@ const device_t lm78_device = {
const device_t w83781d_device = {
"Winbond W83781D Hardware Monitor",
DEVICE_ISA,
0x290 | LM78_SMBUS | LM78_W83781D,
0x290 | LM78_I2C | LM78_W83781D,
lm78_init, lm78_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
/* The ASUS AS99127F is a customized W83781D with no ISA interface (SMBus
/* The ASUS AS99127F is a customized W83781D with no ISA interface (I2C
only), added proprietary registers and different chip/vendor IDs. */
const device_t as99127f_device = {
"ASUS AS99127F Rev. 1 Hardware Monitor",
DEVICE_ISA,
LM78_SMBUS | LM78_AS99127F_REV1,
LM78_I2C | LM78_AS99127F_REV1,
lm78_init, lm78_close, NULL,
{ NULL }, NULL, NULL,
NULL
@@ -592,7 +592,7 @@ const device_t as99127f_device = {
const device_t as99127f_rev2_device = {
"ASUS AS99127F Rev. 2 Hardware Monitor",
DEVICE_ISA,
LM78_SMBUS | LM78_AS99127F_REV2,
LM78_I2C | LM78_AS99127F_REV2,
lm78_init, lm78_close, NULL,
{ NULL }, NULL, NULL,
NULL
@@ -603,7 +603,7 @@ const device_t as99127f_rev2_device = {
const device_t w83782d_device = {
"Winbond W83782D Hardware Monitor",
DEVICE_ISA,
0x290 | LM78_SMBUS | LM78_W83782D,
0x290 | LM78_I2C | LM78_W83782D,
lm78_init, lm78_close, NULL,
{ NULL }, NULL, NULL,
NULL