From 928c494e6c41e756e888d1a18d64ee7c64f79ac2 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 18 May 2020 22:47:50 -0300 Subject: [PATCH 1/4] Fix SMBus logging, enabling logging should no longer return bad values. --- src/smbus.c | 46 ++++++++++++++++------------------------------ 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/src/smbus.c b/src/smbus.c index fdb98ea78..d86b167c1 100644 --- a/src/smbus.c +++ b/src/smbus.c @@ -69,18 +69,6 @@ smbus_log(const char *fmt, ...) #endif -#ifdef ENABLE_SMBUS_LOG -static uint8_t smbus_null_read_byte(uint8_t addr, void *priv) { smbus_log("SMBus: read_byte(%02x)\n", addr); return(0xff); } -static uint8_t smbus_null_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv) { smbus_log("SMBus: read_byte_cmd(%02x, %02x)\n", addr, cmd); return(0xff); } -static uint16_t smbus_null_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv) { smbus_log("SMBus: read_word_cmd(%02x, %02x)\n", addr, cmd); return(0xffff); } -static uint8_t smbus_null_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv) { smbus_log("SMBus: read_block_cmd(%02x, %02x)\n", addr, cmd); return(0x00); }; -static void smbus_null_write_byte(uint8_t addr, uint8_t val, void *priv) { smbus_log("SMBus: write_byte(%02x, %02x)\n", addr, val); } -static void smbus_null_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv) { smbus_log("SMBus: write_byte_cmd(%02x, %02x, %02x)\n", addr, cmd, val); } -static void smbus_null_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv) { smbus_log("SMBus: write_word_cmd(%02x, %02x, %04x)\n", addr, cmd, val); } -static void smbus_null_write_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv) { smbus_log("SMBus: write_block_cmd(%02x, %02x, %02x)\n", addr, cmd, len); } -#endif - - void smbus_init(void) { @@ -106,26 +94,8 @@ smbus_init(void) p = NULL; } -#ifdef ENABLE_SMBUS_LOG - /* smbus[c] should be the only handler, pointing at the NULL catch handler. */ - p = (smbus_t *) malloc(sizeof(smbus_t)); - memset(p, 0, sizeof(smbus_t)); - smbus[c] = smbus_last[c] = p; - p->next = NULL; - p->prev = NULL; - p->read_byte = smbus_null_read_byte; - p->read_byte_cmd = smbus_null_read_byte_cmd; - p->read_word_cmd = smbus_null_read_word_cmd; - p->read_block_cmd = smbus_null_read_block_cmd; - p->write_byte = smbus_null_write_byte; - p->write_byte_cmd = smbus_null_write_byte_cmd; - p->write_word_cmd = smbus_null_write_word_cmd; - p->write_block_cmd = smbus_null_write_block_cmd; - p->priv = NULL; -#else /* smbus[c] should be NULL. */ smbus[c] = smbus_last[c] = NULL; -#endif } } @@ -262,6 +232,8 @@ smbus_read_byte(uint8_t addr) } } + smbus_log("SMBus: read_byte(%02X) = %02X\n", addr, ret); + return(ret); } @@ -283,6 +255,8 @@ smbus_read_byte_cmd(uint8_t addr, uint8_t cmd) } } + smbus_log("SMBus: read_byte_cmd(%02X, %02X) = %02X\n", addr, cmd, ret); + return(ret); } @@ -304,6 +278,8 @@ smbus_read_word_cmd(uint8_t addr, uint8_t cmd) } } + smbus_log("SMBus: read_word_cmd(%02X, %02X) = %04X\n", addr, cmd, ret); + return(ret); } @@ -325,6 +301,8 @@ smbus_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len) } } + smbus_log("SMBus: read_block_cmd(%02X, %02X) = %02X\n", addr, cmd, len); + return(ret); } @@ -346,6 +324,8 @@ smbus_write_byte(uint8_t addr, uint8_t val) } } + smbus_log("SMBus: write_byte(%02X, %02X)\n", addr, val); + return; } @@ -366,6 +346,8 @@ smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val) } } + smbus_log("SMBus: write_byte_cmd(%02X, %02X, %02X)\n", addr, cmd, val); + return; } @@ -386,6 +368,8 @@ smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val) } } + smbus_log("SMBus: write_word_cmd(%02X, %02X, %04X)\n", addr, cmd, val); + return; } @@ -406,5 +390,7 @@ smbus_write_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len) } } + smbus_log("SMBus: write_block_cmd(%02X, %02X, %02X)\n", addr, cmd, len); + return; } From 2ff06457d5979eca91e3f8d5587688825207b0ae Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 18 May 2020 22:54:59 -0300 Subject: [PATCH 2/4] Hardware monitor refactoring, part 2 --- src/hwm.c | 1 + src/hwm_lm75.c | 269 ++++++++++++++++++++++++++++++++++ src/hwm_lm78.c | 261 +++++++++++---------------------- src/include/86box/hwm.h | 19 +++ src/machine/m_at_slot1.c | 2 +- src/machine/m_at_socket370.c | 2 +- src/machine/m_at_socket7_s7.c | 4 +- src/win/Makefile.mingw | 2 +- src/win/Makefile_ndr.mingw | 2 +- 9 files changed, 382 insertions(+), 180 deletions(-) create mode 100644 src/hwm_lm75.c diff --git a/src/hwm.c b/src/hwm.c index cac194d98..7ef55b3ef 100644 --- a/src/hwm.c +++ b/src/hwm.c @@ -11,6 +11,7 @@ * * * Author: RichardG, + * * Copyright 2020 RichardG. */ diff --git a/src/hwm_lm75.c b/src/hwm_lm75.c new file mode 100644 index 000000000..1b6431395 --- /dev/null +++ b/src/hwm_lm75.c @@ -0,0 +1,269 @@ +/* + * 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 National Semiconductor LM75 temperature sensor chip. + * + * + * + * Author: RichardG, + * + * Copyright 2020 RichardG. + */ +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/smbus.h> +#include <86box/hwm.h> + + +#define LM75_TEMP_TO_REG(t) ((t) << 8) + + +static uint8_t lm75_smbus_read_byte(uint8_t addr, void *priv); +static uint8_t lm75_smbus_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv); +static uint16_t lm75_smbus_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv); +static void lm75_smbus_write_byte(uint8_t addr, uint8_t val, void *priv); +static void lm75_smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv); +static void lm75_smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv); +static void lm75_reset(lm75_t *dev); + + +#ifdef ENABLE_LM75_LOG +int lm75_do_log = ENABLE_LM75_LOG; + + +static void +lm75_log(const char *fmt, ...) +{ + va_list ap; + + if (lm75_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define lm75_log(fmt, ...) +#endif + + +void +lm75_remap(lm75_t *dev) +{ + lm75_log("LM75: remapping to SMBus %02Xh\n", dev->smbus_addr); + + smbus_removehandler(dev->smbus_addr, 1, + lm75_smbus_read_byte, lm75_smbus_read_byte_cmd, lm75_smbus_read_word_cmd, NULL, + lm75_smbus_write_byte, lm75_smbus_write_byte_cmd, lm75_smbus_write_word_cmd, NULL, + dev); + + if (dev->smbus_addr) smbus_sethandler(dev->smbus_addr, 1, + lm75_smbus_read_byte, lm75_smbus_read_byte_cmd, lm75_smbus_read_word_cmd, NULL, + lm75_smbus_write_byte, lm75_smbus_write_byte_cmd, lm75_smbus_write_word_cmd, NULL, + dev); +} + + +static uint8_t +lm75_smbus_read_byte(uint8_t addr, void *priv) +{ + lm75_t *dev = (lm75_t *) priv; + return lm75_read(dev, dev->addr_register); +} + + +static uint8_t +lm75_smbus_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv) +{ + lm75_t *dev = (lm75_t *) priv; + return lm75_read(dev, cmd); +} + +static uint16_t +lm75_smbus_read_word_cmd(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 */ + rethi = lm75_read(dev, 0x0); + retlo = lm75_read(dev, 0x1); + break; + case 0x1: /* configuration */ + rethi = retlo = lm75_read(dev, 0x2); + break; + case 0x2: /* Thyst */ + rethi = lm75_read(dev, 0x3); + retlo = lm75_read(dev, 0x4); + break; + case 0x3: /* Tos */ + rethi = lm75_read(dev, 0x5); + retlo = lm75_read(dev, 0x6); + break; + } + + return (retlo << 8) | rethi; /* byte-swapped for some reason */ +} + + +uint8_t +lm75_read(lm75_t *dev, uint8_t reg) +{ + uint8_t ret; + + /* 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 SMBus call, if necessary. */ + if ((reg >= 0x80) && (dev->as99127f_smbus_addr)) + ret = smbus_read_byte_cmd(dev->as99127f_smbus_addr, reg); + else + ret = dev->regs[reg & 0x7]; + + lm75_log("LM75: read(%x) = %02x\n", reg, ret); + + return ret; +} + + +static void +lm75_smbus_write_byte(uint8_t addr, uint8_t val, void *priv) +{ + lm75_t *dev = (lm75_t *) priv; + dev->addr_register = val; +} + + +static void +lm75_smbus_write_byte_cmd(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_smbus_write_word_cmd(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 */ + lm75_write(dev, 0x0, valhi); + lm75_write(dev, 0x1, vallo); + break; + case 0x1: /* configuration */ + lm75_write(dev, 0x2, vallo); + break; + case 0x2: /* Thyst */ + lm75_write(dev, 0x3, valhi); + lm75_write(dev, 0x4, vallo); + break; + case 0x3: /* Tos */ + lm75_write(dev, 0x5, valhi); + lm75_write(dev, 0x6, vallo); + break; + break; + } +} + + +uint8_t +lm75_write(lm75_t *dev, uint8_t reg, uint8_t val) +{ + lm75_log("LM75: write(%x, %02x)\n", reg, val); + + /* 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 SMBus call, if necessary. */ + if ((reg >= 0x80) && (dev->as99127f_smbus_addr)) { + smbus_write_byte_cmd(dev->as99127f_smbus_addr, reg, val); + return 1; + } + + uint8_t reg_idx = (reg & 0x7); + + if ((reg_idx <= 0x1) || (reg_idx == 0x7)) + return 0; /* read-only registers */ + + dev->regs[reg_idx] = val; + + return 1; +} + + +static void +lm75_reset(lm75_t *dev) +{ + uint16_t temp = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]); + dev->regs[0x0] = (temp >> 8); + dev->regs[0x1] = temp; + dev->regs[0x3] = 0x4b; + dev->regs[0x5] = 0x50; + + lm75_remap(dev); +} + + +static void +lm75_close(void *priv) +{ + lm75_t *dev = (lm75_t *) priv; + free(dev); +} + + +static void * +lm75_init(const device_t *info) +{ + lm75_t *dev = (lm75_t *) malloc(sizeof(lm75_t)); + memset(dev, 0, sizeof(lm75_t)); + + dev->local = info->local; + dev->values = hwm_get_values(); + + dev->smbus_addr = dev->local; + dev->as99127f_smbus_addr = 0x00; + + lm75_reset(dev); + + return dev; +} + + +/* LM75 on SMBus address 4Ah, reporting temperatures[1]. */ +const device_t lm75_1_4a_device = { + "National Semiconductor LM75 Temperature Sensor", + DEVICE_AT, + 0x14a, + lm75_init, lm75_close, NULL, + NULL, NULL, NULL, + NULL +}; + + +/* LM75 secondary/tertiary temperature sensors built into + the Winbond W83781D family. Not to be used stand-alone. */ +const device_t lm75_w83781d_device = { + "Winbond W83781D Secondary Temperature Sensor", + DEVICE_AT, + 0, + lm75_init, lm75_close, NULL, + NULL, NULL, NULL, + NULL +}; diff --git a/src/hwm_lm78.c b/src/hwm_lm78.c index 27c15fe8f..2ecc36f14 100644 --- a/src/hwm_lm78.c +++ b/src/hwm_lm78.c @@ -39,23 +39,19 @@ #define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a))) #define LM78_RPM_TO_REG(r, d) ((r) ? CLAMP(1350000 / (r * d), 1, 255) : 0) -#define LM78_TEMP_TO_REG(t) ((t) << 8) #define LM78_VOLTAGE_TO_REG(v) ((v) >> 4) typedef struct { uint32_t local; - hwm_values_t* values; + hwm_values_t *values; + device_t *lm75[2]; uint8_t regs[256]; - uint8_t regs_bank1[7]; - uint8_t regs_bank2[7]; uint8_t addr_register; uint8_t data_register; - uint8_t smbus_addr_main; - uint8_t smbus_addr_temp2; - uint8_t smbus_addr_temp3; + uint8_t smbus_addr; uint8_t hbacs; uint8_t active_bank; } lm78_t; @@ -97,29 +93,31 @@ lm78_log(const char *fmt, ...) static void lm78_remap(lm78_t *dev) { + lm75_t *lm75; + if (!(dev->local & LM78_SMBUS)) return; - lm78_log("LM78: SMBus remap: main = %02Xh; temp2 = %02Xh; temp3 = %02Xh\n", dev->smbus_addr_main, dev->smbus_addr_temp2, dev->smbus_addr_temp3); + lm78_log("LM78: remapping to SMBus %02Xh\n", dev->smbus_addr); - smbus_removehandler(0x00, 0x80, + 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); - if (dev->smbus_addr_main) smbus_sethandler(dev->smbus_addr_main, 1, + if (dev->smbus_addr) smbus_sethandler(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); - if (dev->smbus_addr_temp2) smbus_sethandler(dev->smbus_addr_temp2, 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 (dev->smbus_addr_temp3) smbus_sethandler(dev->smbus_addr_temp3, 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 (dev->local & LM78_AS99127F) { + /* Store the main SMBus 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; + } + } } @@ -127,9 +125,9 @@ static uint8_t lm78_isa_read(uint16_t port, void *priv) { lm78_t *dev = (lm78_t *) priv; - uint8_t ret = 0xFF; + uint8_t ret = 0xff; - switch (port & 0xf) { + switch (port & 0x7) { case 0x5: ret = (dev->addr_register & 0x7f); break; @@ -143,6 +141,9 @@ lm78_isa_read(uint16_t port, void *priv) dev->addr_register++; } break; + default: + lm78_log("LM78: Read from unknown ISA port %x\n", port & 0x7); + break; } return ret; @@ -153,7 +154,7 @@ static uint8_t lm78_smbus_read_byte(uint8_t addr, void *priv) { lm78_t *dev = (lm78_t *) priv; - return lm78_smbus_read_byte_cmd(addr, dev->addr_register, priv); + return lm78_read(dev, dev->addr_register, dev->active_bank); } @@ -161,14 +162,7 @@ static uint8_t lm78_smbus_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv) { lm78_t *dev = (lm78_t *) priv; - - uint8_t bank = 0; - if (addr == dev->smbus_addr_temp2) - bank = 1; - else if (addr == dev->smbus_addr_temp3) - bank = 2; - - return lm78_read(dev, cmd, bank); + return lm78_read(dev, cmd, dev->active_bank); } @@ -176,38 +170,7 @@ static uint16_t lm78_smbus_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv) { lm78_t *dev = (lm78_t *) priv; - uint8_t rethi = 0; - uint8_t retlo = 0; - uint8_t bank = 0; - - if ((dev->local & LM78_WINBOND) && ((addr == dev->smbus_addr_temp2) || (addr == dev->smbus_addr_temp3))) { - if (addr == dev->smbus_addr_temp2) - bank = 2; - else - bank = 3; - - switch (cmd & 0x3) { - case 0x0: /* temperature */ - rethi = lm78_read(dev, 0x50, bank); - retlo = lm78_read(dev, 0x51, bank); - break; - case 0x1: /* configuration */ - rethi = retlo = lm78_read(dev, 0x52, bank); - break; - case 0x2: /* Thyst */ - rethi = lm78_read(dev, 0x53, bank); - retlo = lm78_read(dev, 0x54, bank); - break; - case 0x3: /* Tos */ - rethi = lm78_read(dev, 0x55, bank); - retlo = lm78_read(dev, 0x56, bank); - break; - } - } else { - rethi = retlo = lm78_read(dev, cmd, bank); - } - - return (retlo << 8) | rethi; /* byte-swapped for some reason */ + return (lm78_read(dev, cmd, dev->active_bank) << 8) | lm78_read(dev, cmd, dev->active_bank); } @@ -215,20 +178,20 @@ static uint8_t lm78_read(lm78_t *dev, uint8_t reg, uint8_t bank) { uint8_t ret = 0; + lm75_t *lm75; - if ((dev->local & LM78_WINBOND) && ((reg >> 4) == 0x5) && (bank != 0)) { - /* bank-switched temperature registers */ - if (bank == 1) - ret = dev->regs_bank1[reg & 0x7]; - else - ret = dev->regs_bank2[reg & 0x7]; + if (((reg >> 4) == 0x5) && (bank != 0)) { + /* LM75 registers */ + lm75 = device_get_priv(dev->lm75[bank - 1]); + if (lm75) + ret = lm75_read(lm75, reg & 0x7); } else { /* regular registers */ if ((reg == 0x4f) && (dev->local & LM78_WINBOND)) /* special case for two-byte vendor ID register */ ret = (dev->hbacs ? (LM78_WINBOND_VENDOR_ID >> 8) : LM78_WINBOND_VENDOR_ID); else if ((reg >= 0x60) && (reg <= 0x7f)) /* read auto-increment value RAM registers from their non-auto-increment locations */ ret = dev->regs[reg & 0x3f]; - else if ((reg >= 0x80) && (reg <= 0x92)) /* AS99127F mirrors POST RAM to 80-92 */ + else if ((reg >= 0x80) && (reg <= 0x92)) /* AS99127F mirrors [0x00:0x12] to [0x80:0x92] */ ret = dev->regs[reg - 0x7f]; else ret = dev->regs[reg]; @@ -245,7 +208,7 @@ lm78_isa_write(uint16_t port, uint8_t val, void *priv) { lm78_t *dev = (lm78_t *) priv; - switch (port & 0xf) { + switch (port & 0x7) { case 0x5: dev->addr_register = (val & 0x7f); break; @@ -259,6 +222,9 @@ lm78_isa_write(uint16_t port, uint8_t val, void *priv) dev->addr_register++; } break; + default: + lm78_log("LM78: Write %02x to unknown ISA port %x\n", val, port & 0x7); + break; } } @@ -267,7 +233,6 @@ static void lm78_smbus_write_byte(uint8_t addr, uint8_t val, void *priv) { lm78_t *dev = (lm78_t *) priv; - dev->addr_register = val; } @@ -276,8 +241,7 @@ static void lm78_smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv) { lm78_t *dev = (lm78_t *) priv; - - lm78_write(dev, cmd, val, 0); + lm78_write(dev, cmd, val, dev->active_bank); } @@ -285,60 +249,23 @@ static void lm78_smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv) { lm78_t *dev = (lm78_t *) priv; - uint8_t valhi = (val >> 8); - uint8_t vallo = (val & 0xff); - uint8_t bank = 0; - - if ((dev->local & LM78_WINBOND) && ((addr == dev->smbus_addr_temp2) || (addr == dev->smbus_addr_temp3))) { - if (addr == dev->smbus_addr_temp2) - bank = 2; - else - bank = 3; - - switch (cmd & 0x3) { - case 0x0: /* temperature */ - lm78_write(dev, 0x50, valhi, bank); - lm78_write(dev, 0x51, vallo, bank); - break; - case 0x1: /* configuration */ - lm78_write(dev, 0x52, vallo, bank); - break; - case 0x2: /* Thyst */ - lm78_write(dev, 0x53, valhi, bank); - lm78_write(dev, 0x54, vallo, bank); - break; - case 0x3: /* Tos */ - lm78_write(dev, 0x55, valhi, bank); - lm78_write(dev, 0x56, vallo, bank); - break; - break; - } - return; - } - - lm78_write(dev, cmd, vallo, bank); + lm78_write(dev, cmd, val, dev->active_bank); } static uint8_t lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank) { - uint8_t remap = 0; + lm75_t *lm75; - if ((dev->local & LM78_WINBOND) && ((reg >> 4) == 0x5) && (bank != 0)) { - /* bank-switched temperature registers */ - switch (reg) { - case 0x50: case 0x51: - /* read-only registers */ - return 0; - } + lm78_log("LM78: write(%02x, %d, %02x)\n", reg, bank, val); - if (bank == 1) - dev->regs_bank1[reg & 0x7] = val; - else - dev->regs_bank2[reg & 0x7] = val; - - goto end; + if (((reg >> 4) == 0x5) && (bank != 0)) { + /* LM75 registers */ + lm75 = device_get_priv(dev->lm75[bank - 1]); + if (lm75) + lm75_write(lm75, reg & 0x7, val); + return 1; } /* regular registers */ @@ -357,7 +284,7 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank) if ((reg >= 0x60) && (reg <= 0x7f)) /* write auto-increment value RAM registers to their non-auto-increment locations */ dev->regs[reg & 0x3f] = val; - else if ((reg >= 0x80) && (reg <= 0x92)) /* AS99127F mirrors POST RAM to 80-92 */ + else if ((reg >= 0x80) && (reg <= 0x92)) /* AS99127F mirrors [0x00:0x12] to [0x80:0x92] */ dev->regs[reg & 0x7f] = val; else dev->regs[reg] = val; @@ -377,8 +304,8 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank) case 0x48: /* set main SMBus address */ if (dev->local & LM78_SMBUS) { - dev->smbus_addr_main = (dev->regs[0x48] & 0x7f); - remap = 1; + dev->smbus_addr = (dev->regs[0x48] & 0x7f); + lm78_remap(dev); } break; case 0x49: @@ -394,18 +321,16 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank) } break; case 0x4a: - /* set TEMP2 and TEMP3 SMBus addresses (Winbond only) */ + /* set LM75 SMBus addresses (Winbond only) */ if (dev->local & LM78_SMBUS) { - /* DIS_T2 and DIS_T3 bit disable those interfaces */ - if (dev->regs[0x4a] & 0x08) - dev->smbus_addr_temp2 = 0x00; - else - dev->smbus_addr_temp2 = (0x48 + (dev->regs[0x4a] & 0x7)); - if (dev->regs[0x4a] & 0x80) - dev->smbus_addr_temp3 = 0x00; - else - dev->smbus_addr_temp3 = (0x48 + ((dev->regs[0x4a] >> 4) & 0x7)); - remap = 1; + for (uint8_t i = 0; i <= 1; i++) { + lm75 = device_get_priv(dev->lm75[i]); + if (dev->regs[0x4a] & (0x08 * (0x10 * i))) /* DIS_T2 and DIS_T3 bit disable those interfaces */ + lm75->smbus_addr = 0x00; + else + lm75->smbus_addr = (0x48 + ((dev->regs[0x4a] >> (i * 4)) & 0x7)); + lm75_remap(lm75); + } } break; case 0x4b: @@ -426,12 +351,6 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank) break; } - if (remap) - lm78_remap(dev); - -end: - lm78_log("LM78: write(%02x, %d) = %02x\n", reg, bank, val); - return 1; } @@ -441,8 +360,6 @@ lm78_reset(lm78_t *dev, uint8_t initialization) { memset(dev->regs, 0, 256); memset(dev->regs + 0xc0, 0xff, 32); /* C0-DF are 0xFF at least on the AS99127F */ - memset(dev->regs_bank1, 0, 6); - memset(dev->regs_bank2, 0, 6); uint8_t i; for (i = 0; i <= 6; i++) @@ -455,20 +372,14 @@ lm78_reset(lm78_t *dev, uint8_t initialization) 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_main = 0x2d; - dev->regs[0x48] = dev->smbus_addr_main; - if (dev->local & LM78_WINBOND) { + dev->smbus_addr = 0x2d; + dev->regs[0x48] = dev->smbus_addr; + if (dev->local & LM78_WINBOND) dev->regs[0x4a] = 0x01; - dev->smbus_addr_temp2 = (0x48 + (dev->regs[0x4a] & 0x7)); - dev->smbus_addr_temp3 = (0x48 + ((dev->regs[0x4a] >> 4) & 0x7)); - } else { - dev->smbus_addr_temp2 = dev->smbus_addr_temp3 = 0x00; - } } else { dev->regs[0x48] = 0x00; if (dev->local & LM78_WINBOND) dev->regs[0x4a] = 0x88; - dev->smbus_addr_temp2 = dev->smbus_addr_temp3 = 0x00; } if (dev->local & LM78_WINBOND) { dev->regs[0x49] = 0x02; @@ -480,17 +391,15 @@ lm78_reset(lm78_t *dev, uint8_t initialization) dev->regs[0x4f] = (LM78_WINBOND_VENDOR_ID >> 8); dev->regs[0x57] = 0x80; - /* - * Initialize proprietary registers on the AS99127F. The BIOS accesses some - * of these on boot through read_byte_cmd on the TEMP2 address, hanging on - * POST code C1 if they're set to 0. There's no documentation on what these - * are for. The following values were dumped from a live, initialized - * AS99127F Rev. 2 on a P4B motherboard, and they seem to work well enough. - */ + /* Initialize proprietary registers on the AS99127F. The BIOS accesses some + of these on boot through read_byte_cmd on the TEMP2 address, hanging on + POST code C1 if they're defaulted to 0. There's no documentation on what + these are for. The following values were dumped from a live, initialized + AS99127F Rev. 2 on a P4B motherboard, and they seem to work well enough. */ if (dev->local & LM78_AS99127F) { /* 0x00 appears to mirror IN2 Low Limit */ dev->regs[0x01] = dev->regs[0x23]; /* appears to mirror IN3 */ - dev->regs[0x02] = LM78_VOLTAGE_TO_REG(2800); /* appears to be a "maximum VCORE" of some kind; mirrors VCORE on the P4 board, but the P3 boards require this to read 2.8V */ + dev->regs[0x02] = LM78_VOLTAGE_TO_REG(2800); /* appears to be a "maximum VCORE" of some kind; must read 2.8V on P3 boards */ dev->regs[0x03] = 0x60; dev->regs[0x04] = dev->regs[0x23]; /* appears to mirror IN3 */ dev->regs[0x05] = dev->regs[0x22]; /* appears to mirror IN2 */ @@ -513,19 +422,6 @@ lm78_reset(lm78_t *dev, uint8_t initialization) } else { dev->regs[0x58] = 0x10; } - - /* WARNING: Array elements are register - 0x50. */ - uint16_t temp; - temp = LM78_TEMP_TO_REG(dev->values->temperatures[1]); - dev->regs_bank1[0x0] = (temp >> 8); - dev->regs_bank1[0x1] = (temp & 0xff); - dev->regs_bank1[0x3] = 0x4b; - dev->regs_bank1[0x5] = 0x50; - temp = LM78_TEMP_TO_REG(dev->values->temperatures[2]); - dev->regs_bank2[0x0] = (temp >> 8); - dev->regs_bank2[0x1] = (temp & 0xff); - dev->regs_bank2[0x3] = 0x4b; - dev->regs_bank2[0x5] = 0x50; } else { dev->regs[0x49] = 0x40; } @@ -541,7 +437,7 @@ lm78_close(void *priv) uint16_t isa_io = (dev->local & 0xffff); if (isa_io) - io_removehandler(isa_io, 2, lm78_isa_read, NULL, NULL, lm78_isa_write, NULL, NULL, dev); + io_removehandler(isa_io, 8, lm78_isa_read, NULL, NULL, lm78_isa_write, NULL, NULL, dev); free(dev); } @@ -555,11 +451,26 @@ lm78_init(const device_t *info) dev->local = info->local; dev->values = hwm_get_values(); + + /* initialize secondary/tertiary LM75 sensors on Winbond */ + for (uint8_t i = 0; i <= 1; i++) { + if (dev->local & LM78_WINBOND) { + 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) + dev->lm75[i]->local |= (0x48 + i); + device_add(dev->lm75[i]); + } else { + dev->lm75[i] = NULL; + } + } + lm78_reset(dev, 0); uint16_t isa_io = (dev->local & 0xffff); if (isa_io) - io_sethandler(isa_io, 2, lm78_isa_read, NULL, NULL, lm78_isa_write, NULL, NULL, dev); + io_sethandler(isa_io, 8, lm78_isa_read, NULL, NULL, lm78_isa_write, NULL, NULL, dev); return dev; } @@ -569,7 +480,7 @@ lm78_init(const device_t *info) const device_t lm78_device = { "National Semiconductor LM78 Hardware Monitor", DEVICE_ISA, - 0x295 | LM78_SMBUS, + 0x290 | LM78_SMBUS, lm78_init, lm78_close, NULL, NULL, NULL, NULL, NULL @@ -580,7 +491,7 @@ const device_t lm78_device = { const device_t w83781d_device = { "Winbond W83781D Hardware Monitor", DEVICE_ISA, - 0x295 | LM78_SMBUS | LM78_W83781D, + 0x290 | LM78_SMBUS | LM78_W83781D, lm78_init, lm78_close, NULL, NULL, NULL, NULL, NULL diff --git a/src/include/86box/hwm.h b/src/include/86box/hwm.h index efde01767..0cae77dbb 100644 --- a/src/include/86box/hwm.h +++ b/src/include/86box/hwm.h @@ -27,10 +27,29 @@ typedef struct _hwm_values_ { uint16_t voltages[8]; } hwm_values_t; +typedef struct { + uint32_t local; + hwm_values_t *values; + + uint8_t regs[8]; + uint8_t addr_register; + uint8_t temp_idx; + uint8_t smbus_addr; + + uint8_t as99127f_smbus_addr; +} lm75_t; + extern void hwm_set_values(hwm_values_t new_values); extern hwm_values_t* hwm_get_values(); +extern void lm75_remap(lm75_t *dev); +extern uint8_t lm75_read(lm75_t *dev, uint8_t reg); +extern uint8_t lm75_write(lm75_t *dev, uint8_t reg, uint8_t val); + + +extern const device_t lm75_1_4a_device; +extern const device_t lm75_w83781d_device; extern const device_t lm78_device; extern const device_t w83781d_device; diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 65838fd21..436a522f5 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -214,7 +214,7 @@ machine_at_p3bf_init(const machine_t *model) 3000 /* Power */ }, { /* temperatures */ 30, /* MB */ - 0, /* unused */ + 30, /* JTPWR */ 30 /* CPU */ }, { /* voltages */ 2050, /* VCORE (2.05V by default) */ diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index b0c75f80a..8852ee804 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -135,7 +135,7 @@ machine_at_cubx_init(const machine_t *model) 3000 /* Power */ }, { /* temperatures */ 30, /* MB */ - 0, /* unused */ + 30, /* JTPWR */ 30 /* CPU */ }, { /* voltages */ 2050, /* VCORE (2.05V by default) */ diff --git a/src/machine/m_at_socket7_s7.c b/src/machine/m_at_socket7_s7.c index c38fecbd4..c4792518c 100644 --- a/src/machine/m_at_socket7_s7.c +++ b/src/machine/m_at_socket7_s7.c @@ -847,7 +847,8 @@ machine_at_p5mms98_init(const machine_t *model) 3000, /* CPU */ 3000 /* Chassis */ }, { /* temperatures */ - 28 /* CPU (locked at 28?) */ + 0, /* unused */ + 30 /* CPU */ }, { /* voltages */ 3300, /* VCORE (3.3V by default) */ 3300, /* VIO (3.3V) */ @@ -873,6 +874,7 @@ machine_at_p5mms98_init(const machine_t *model) } hwm_set_values(machine_hwm); device_add(&lm78_device); + device_add(&lm75_1_4a_device); return ret; } diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 9ef6f013f..9e2ad81d9 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -535,7 +535,7 @@ MCHOBJ := machine.o machine_table.o \ m_at_socket4_5.o m_at_socket7_s7.o m_at_super7_ss7.o \ m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o -DEVOBJ := bugger.o hwm.o hwm_lm78.o ibm_5161.o isamem.o isartc.o lpt.o postcard.o $(SERIAL) \ +DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o ibm_5161.o isamem.o isartc.o lpt.o postcard.o $(SERIAL) \ sio_detect.o sio_acc3221.o \ sio_f82c710.o \ sio_fdc37c66x.o sio_fdc37c669.o \ diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw index f454ce035..29ff11093 100644 --- a/src/win/Makefile_ndr.mingw +++ b/src/win/Makefile_ndr.mingw @@ -539,7 +539,7 @@ MCHOBJ := machine.o machine_table.o \ m_at_socket4_5.o m_at_socket7_s7.o m_at_super7_ss7.o \ m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o -DEVOBJ := bugger.o hwm.o hwm_lm78.o ibm_5161.o isamem.o isartc.o lpt.o postcard.o $(SERIAL) \ +DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o ibm_5161.o isamem.o isartc.o lpt.o postcard.o $(SERIAL) \ sio_acc3221.o \ sio_f82c710.o \ sio_fdc37c66x.o sio_fdc37c669.o \ From 0eead95b5206508c655101ee353b13f3c1d33fcc Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 18 May 2020 23:00:05 -0300 Subject: [PATCH 3/4] Convert permanent log lines to uppercase hexadecimal --- src/hwm_lm75.c | 4 ++-- src/hwm_lm78.c | 10 +++++----- src/spd.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/hwm_lm75.c b/src/hwm_lm75.c index 1b6431395..0d937c194 100644 --- a/src/hwm_lm75.c +++ b/src/hwm_lm75.c @@ -133,7 +133,7 @@ lm75_read(lm75_t *dev, uint8_t reg) else ret = dev->regs[reg & 0x7]; - lm75_log("LM75: read(%x) = %02x\n", reg, ret); + lm75_log("LM75: read(%02X) = %02X\n", reg, ret); return ret; } @@ -186,7 +186,7 @@ lm75_smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv) uint8_t lm75_write(lm75_t *dev, uint8_t reg, uint8_t val) { - lm75_log("LM75: write(%x, %02x)\n", reg, val); + lm75_log("LM75: write(%02X, %02X)\n", reg, val); /* The AS99127F hardware monitor uses the addresses of its LM75 devices to access some of its proprietary registers. Pass this operation on to diff --git a/src/hwm_lm78.c b/src/hwm_lm78.c index 2ecc36f14..2cac22881 100644 --- a/src/hwm_lm78.c +++ b/src/hwm_lm78.c @@ -142,7 +142,7 @@ lm78_isa_read(uint16_t port, void *priv) } break; default: - lm78_log("LM78: Read from unknown ISA port %x\n", port & 0x7); + lm78_log("LM78: Read from unknown ISA port %d\n", port & 0x7); break; } @@ -197,7 +197,7 @@ lm78_read(lm78_t *dev, uint8_t reg, uint8_t bank) ret = dev->regs[reg]; } - lm78_log("LM78: read(%02x, %d) = %02x\n", reg, bank, ret); + lm78_log("LM78: read(%02X, %d) = %02X\n", reg, bank, ret); return ret; } @@ -223,7 +223,7 @@ lm78_isa_write(uint16_t port, uint8_t val, void *priv) } break; default: - lm78_log("LM78: Write %02x to unknown ISA port %x\n", val, port & 0x7); + lm78_log("LM78: Write %02X to unknown ISA port %d\n", val, port & 0x7); break; } } @@ -258,7 +258,7 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank) { lm75_t *lm75; - lm78_log("LM78: write(%02x, %d, %02x)\n", reg, bank, val); + lm78_log("LM78: write(%02X, %d, %02X)\n", reg, bank, val); if (((reg >> 4) == 0x5) && (bank != 0)) { /* LM75 registers */ @@ -343,7 +343,7 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank) dev->active_bank = (dev->regs[0x4e] & 0x07); break; case 0x87: - /* fixes AS99127F boards hanging after save & exit, probably a reset register */ + /* fixes AS99127F boards hanging after BIOS save & exit, probably a reset register */ if ((dev->local & LM78_AS99127F) && (val == 0x01)) { lm78_log("LM78: Reset requested through AS99127F\n"); resetx86(); diff --git a/src/spd.c b/src/spd.c index 4b63c6d2c..84ba3eb84 100644 --- a/src/spd.c +++ b/src/spd.c @@ -73,7 +73,7 @@ spd_read_byte_cmd(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); + spd_log("SPD: read(%02X, %02X) = %02X\n", addr, cmd, ret); return ret; } @@ -195,7 +195,7 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size) /* populate slot */ vslots[vslot] = (1 << log2_ui16(MIN(total_size, max_module_size))); if (total_size >= vslots[vslot]) { - spd_log("SPD: vslot %d = %d MB\n", vslot, vslots[vslot]); + spd_log("SPD: initial vslot %d = %d MB\n", vslot, vslots[vslot]); total_size -= vslots[vslot]; } else { vslots[vslot] = 0; From f236a44b0879b396071ffca4391db578cd10e63d Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 18 May 2020 23:02:42 -0300 Subject: [PATCH 4/4] Change 370SLM name again to be consistent with other Supermicro boards --- src/machine/machine_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index f9f4c5dce..cce8106a9 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -320,7 +320,7 @@ const machine_t machines[] = { /* PGA370 machines */ /* 440LX */ #if defined(DEV_BRANCH) && defined(NO_SIO) - { "[Socket 370 LX] Supermicro SUPER 370SLM","s370slm", {{"Intel", cpus_Celeron}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 255, machine_at_s370slm_init, NULL }, + { "[Socket 370 LX] Supermicro 370SLM", "s370slm", {{"Intel", cpus_Celeron}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 255, machine_at_s370slm_init, NULL }, #endif /* 440BX */ { "[Socket 370 BX] ASUS CUBX", "cubx", {{"Intel", cpus_Celeron}, {"VIA", cpus_Cyrix3}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_cubx_init, NULL },