Merge pull request #766 from richardg867/master

Hardware monitor refactoring, part 2
This commit is contained in:
OBattler
2020-05-19 07:04:41 +02:00
committed by GitHub
12 changed files with 403 additions and 215 deletions

View File

@@ -11,6 +11,7 @@
* *
* *
* Author: RichardG, <richardg867@gmail.com> * Author: RichardG, <richardg867@gmail.com>
*
* Copyright 2020 RichardG. * Copyright 2020 RichardG.
*/ */

269
src/hwm_lm75.c Normal file
View File

@@ -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, <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/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(%02X) = %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(%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
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
};

View File

@@ -39,23 +39,19 @@
#define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a))) #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_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) #define LM78_VOLTAGE_TO_REG(v) ((v) >> 4)
typedef struct { typedef struct {
uint32_t local; uint32_t local;
hwm_values_t* values; hwm_values_t *values;
device_t *lm75[2];
uint8_t regs[256]; uint8_t regs[256];
uint8_t regs_bank1[7];
uint8_t regs_bank2[7];
uint8_t addr_register; uint8_t addr_register;
uint8_t data_register; uint8_t data_register;
uint8_t smbus_addr_main; uint8_t smbus_addr;
uint8_t smbus_addr_temp2;
uint8_t smbus_addr_temp3;
uint8_t hbacs; uint8_t hbacs;
uint8_t active_bank; uint8_t active_bank;
} lm78_t; } lm78_t;
@@ -97,29 +93,31 @@ lm78_log(const char *fmt, ...)
static void static void
lm78_remap(lm78_t *dev) lm78_remap(lm78_t *dev)
{ {
lm75_t *lm75;
if (!(dev->local & LM78_SMBUS)) return; 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_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, lm78_smbus_write_byte, lm78_smbus_write_byte_cmd, lm78_smbus_write_word_cmd, NULL,
dev); 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_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, lm78_smbus_write_byte, lm78_smbus_write_byte_cmd, lm78_smbus_write_word_cmd, NULL,
dev); dev);
if (dev->smbus_addr_temp2) smbus_sethandler(dev->smbus_addr_temp2, 1, if (dev->local & LM78_AS99127F) {
lm78_smbus_read_byte, lm78_smbus_read_byte_cmd, lm78_smbus_read_word_cmd, NULL, /* Store the main SMBus address on the LM75 devices to ensure reads/writes
lm78_smbus_write_byte, lm78_smbus_write_byte_cmd, lm78_smbus_write_word_cmd, NULL, to the AS99127F's proprietary registers are passed through to this side. */
dev); for (uint8_t i = 0; i <= 1; i++) {
lm75 = device_get_priv(dev->lm75[i]);
if (dev->smbus_addr_temp3) smbus_sethandler(dev->smbus_addr_temp3, 1, if (lm75)
lm78_smbus_read_byte, lm78_smbus_read_byte_cmd, lm78_smbus_read_word_cmd, NULL, lm75->as99127f_smbus_addr = dev->smbus_addr;
lm78_smbus_write_byte, lm78_smbus_write_byte_cmd, lm78_smbus_write_word_cmd, NULL, }
dev); }
} }
@@ -127,9 +125,9 @@ static uint8_t
lm78_isa_read(uint16_t port, void *priv) lm78_isa_read(uint16_t port, void *priv)
{ {
lm78_t *dev = (lm78_t *) priv; lm78_t *dev = (lm78_t *) priv;
uint8_t ret = 0xFF; uint8_t ret = 0xff;
switch (port & 0xf) { switch (port & 0x7) {
case 0x5: case 0x5:
ret = (dev->addr_register & 0x7f); ret = (dev->addr_register & 0x7f);
break; break;
@@ -143,6 +141,9 @@ lm78_isa_read(uint16_t port, void *priv)
dev->addr_register++; dev->addr_register++;
} }
break; break;
default:
lm78_log("LM78: Read from unknown ISA port %d\n", port & 0x7);
break;
} }
return ret; return ret;
@@ -153,7 +154,7 @@ static uint8_t
lm78_smbus_read_byte(uint8_t addr, void *priv) lm78_smbus_read_byte(uint8_t addr, void *priv)
{ {
lm78_t *dev = (lm78_t *) 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_smbus_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv)
{ {
lm78_t *dev = (lm78_t *) priv; lm78_t *dev = (lm78_t *) priv;
return lm78_read(dev, cmd, dev->active_bank);
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);
} }
@@ -176,38 +170,7 @@ static uint16_t
lm78_smbus_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv) lm78_smbus_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv)
{ {
lm78_t *dev = (lm78_t *) priv; lm78_t *dev = (lm78_t *) priv;
uint8_t rethi = 0; return (lm78_read(dev, cmd, dev->active_bank) << 8) | lm78_read(dev, cmd, dev->active_bank);
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 */
} }
@@ -215,26 +178,26 @@ static uint8_t
lm78_read(lm78_t *dev, uint8_t reg, uint8_t bank) lm78_read(lm78_t *dev, uint8_t reg, uint8_t bank)
{ {
uint8_t ret = 0; uint8_t ret = 0;
lm75_t *lm75;
if ((dev->local & LM78_WINBOND) && ((reg >> 4) == 0x5) && (bank != 0)) { if (((reg >> 4) == 0x5) && (bank != 0)) {
/* bank-switched temperature registers */ /* LM75 registers */
if (bank == 1) lm75 = device_get_priv(dev->lm75[bank - 1]);
ret = dev->regs_bank1[reg & 0x7]; if (lm75)
else ret = lm75_read(lm75, reg & 0x7);
ret = dev->regs_bank2[reg & 0x7];
} else { } else {
/* regular registers */ /* regular registers */
if ((reg == 0x4f) && (dev->local & LM78_WINBOND)) /* special case for two-byte vendor ID register */ 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); 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 */ else if ((reg >= 0x60) && (reg <= 0x7f)) /* read auto-increment value RAM registers from their non-auto-increment locations */
ret = dev->regs[reg & 0x3f]; 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]; ret = dev->regs[reg - 0x7f];
else else
ret = dev->regs[reg]; 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; return ret;
} }
@@ -245,7 +208,7 @@ lm78_isa_write(uint16_t port, uint8_t val, void *priv)
{ {
lm78_t *dev = (lm78_t *) priv; lm78_t *dev = (lm78_t *) priv;
switch (port & 0xf) { switch (port & 0x7) {
case 0x5: case 0x5:
dev->addr_register = (val & 0x7f); dev->addr_register = (val & 0x7f);
break; break;
@@ -259,6 +222,9 @@ lm78_isa_write(uint16_t port, uint8_t val, void *priv)
dev->addr_register++; dev->addr_register++;
} }
break; break;
default:
lm78_log("LM78: Write %02X to unknown ISA port %d\n", val, port & 0x7);
break;
} }
} }
@@ -267,7 +233,6 @@ static void
lm78_smbus_write_byte(uint8_t addr, uint8_t val, void *priv) lm78_smbus_write_byte(uint8_t addr, uint8_t val, void *priv)
{ {
lm78_t *dev = (lm78_t *) priv; lm78_t *dev = (lm78_t *) priv;
dev->addr_register = val; 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_smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv)
{ {
lm78_t *dev = (lm78_t *) priv; lm78_t *dev = (lm78_t *) priv;
lm78_write(dev, cmd, val, dev->active_bank);
lm78_write(dev, cmd, val, 0);
} }
@@ -285,60 +249,23 @@ static void
lm78_smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv) lm78_smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv)
{ {
lm78_t *dev = (lm78_t *) priv; lm78_t *dev = (lm78_t *) priv;
uint8_t valhi = (val >> 8); lm78_write(dev, cmd, val, dev->active_bank);
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);
} }
static uint8_t static uint8_t
lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank) 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)) { lm78_log("LM78: write(%02X, %d, %02X)\n", reg, bank, val);
/* bank-switched temperature registers */
switch (reg) {
case 0x50: case 0x51:
/* read-only registers */
return 0;
}
if (bank == 1) if (((reg >> 4) == 0x5) && (bank != 0)) {
dev->regs_bank1[reg & 0x7] = val; /* LM75 registers */
else lm75 = device_get_priv(dev->lm75[bank - 1]);
dev->regs_bank2[reg & 0x7] = val; if (lm75)
lm75_write(lm75, reg & 0x7, val);
goto end; return 1;
} }
/* regular registers */ /* 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 */ if ((reg >= 0x60) && (reg <= 0x7f)) /* write auto-increment value RAM registers to their non-auto-increment locations */
dev->regs[reg & 0x3f] = val; 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; dev->regs[reg & 0x7f] = val;
else else
dev->regs[reg] = val; dev->regs[reg] = val;
@@ -377,8 +304,8 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank)
case 0x48: case 0x48:
/* set main SMBus address */ /* set main SMBus address */
if (dev->local & LM78_SMBUS) { if (dev->local & LM78_SMBUS) {
dev->smbus_addr_main = (dev->regs[0x48] & 0x7f); dev->smbus_addr = (dev->regs[0x48] & 0x7f);
remap = 1; lm78_remap(dev);
} }
break; break;
case 0x49: case 0x49:
@@ -394,18 +321,16 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank)
} }
break; break;
case 0x4a: case 0x4a:
/* set TEMP2 and TEMP3 SMBus addresses (Winbond only) */ /* set LM75 SMBus addresses (Winbond only) */
if (dev->local & LM78_SMBUS) { if (dev->local & LM78_SMBUS) {
/* DIS_T2 and DIS_T3 bit disable those interfaces */ for (uint8_t i = 0; i <= 1; i++) {
if (dev->regs[0x4a] & 0x08) lm75 = device_get_priv(dev->lm75[i]);
dev->smbus_addr_temp2 = 0x00; if (dev->regs[0x4a] & (0x08 * (0x10 * i))) /* DIS_T2 and DIS_T3 bit disable those interfaces */
else lm75->smbus_addr = 0x00;
dev->smbus_addr_temp2 = (0x48 + (dev->regs[0x4a] & 0x7)); else
if (dev->regs[0x4a] & 0x80) lm75->smbus_addr = (0x48 + ((dev->regs[0x4a] >> (i * 4)) & 0x7));
dev->smbus_addr_temp3 = 0x00; lm75_remap(lm75);
else }
dev->smbus_addr_temp3 = (0x48 + ((dev->regs[0x4a] >> 4) & 0x7));
remap = 1;
} }
break; break;
case 0x4b: case 0x4b:
@@ -418,7 +343,7 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank)
dev->active_bank = (dev->regs[0x4e] & 0x07); dev->active_bank = (dev->regs[0x4e] & 0x07);
break; break;
case 0x87: 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)) { if ((dev->local & LM78_AS99127F) && (val == 0x01)) {
lm78_log("LM78: Reset requested through AS99127F\n"); lm78_log("LM78: Reset requested through AS99127F\n");
resetx86(); resetx86();
@@ -426,12 +351,6 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank)
break; break;
} }
if (remap)
lm78_remap(dev);
end:
lm78_log("LM78: write(%02x, %d) = %02x\n", reg, bank, val);
return 1; return 1;
} }
@@ -441,8 +360,6 @@ lm78_reset(lm78_t *dev, uint8_t initialization)
{ {
memset(dev->regs, 0, 256); memset(dev->regs, 0, 256);
memset(dev->regs + 0xc0, 0xff, 32); /* C0-DF are 0xFF at least on the AS99127F */ 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; uint8_t i;
for (i = 0; i <= 6; i++) for (i = 0; i <= 6; i++)
@@ -455,20 +372,14 @@ lm78_reset(lm78_t *dev, uint8_t initialization)
dev->regs[0x47] = 0x50; dev->regs[0x47] = 0x50;
if (dev->local & LM78_SMBUS) { if (dev->local & LM78_SMBUS) {
if (!initialization) /* don't reset main SMBus address if the reset was triggered by the INITIALIZATION bit */ if (!initialization) /* don't reset main SMBus address if the reset was triggered by the INITIALIZATION bit */
dev->smbus_addr_main = 0x2d; dev->smbus_addr = 0x2d;
dev->regs[0x48] = dev->smbus_addr_main; dev->regs[0x48] = dev->smbus_addr;
if (dev->local & LM78_WINBOND) { if (dev->local & LM78_WINBOND)
dev->regs[0x4a] = 0x01; 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 { } else {
dev->regs[0x48] = 0x00; dev->regs[0x48] = 0x00;
if (dev->local & LM78_WINBOND) if (dev->local & LM78_WINBOND)
dev->regs[0x4a] = 0x88; dev->regs[0x4a] = 0x88;
dev->smbus_addr_temp2 = dev->smbus_addr_temp3 = 0x00;
} }
if (dev->local & LM78_WINBOND) { if (dev->local & LM78_WINBOND) {
dev->regs[0x49] = 0x02; 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[0x4f] = (LM78_WINBOND_VENDOR_ID >> 8);
dev->regs[0x57] = 0x80; dev->regs[0x57] = 0x80;
/* /* Initialize proprietary registers on the AS99127F. The BIOS accesses some
* Initialize proprietary registers on the AS99127F. The BIOS accesses some of these on boot through read_byte_cmd on the TEMP2 address, hanging on
* 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
* POST code C1 if they're set to 0. There's no documentation on what these these are for. The following values were dumped from a live, initialized
* 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. */
* AS99127F Rev. 2 on a P4B motherboard, and they seem to work well enough.
*/
if (dev->local & LM78_AS99127F) { if (dev->local & LM78_AS99127F) {
/* 0x00 appears to mirror IN2 Low Limit */ /* 0x00 appears to mirror IN2 Low Limit */
dev->regs[0x01] = dev->regs[0x23]; /* appears to mirror IN3 */ 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[0x03] = 0x60;
dev->regs[0x04] = dev->regs[0x23]; /* appears to mirror IN3 */ dev->regs[0x04] = dev->regs[0x23]; /* appears to mirror IN3 */
dev->regs[0x05] = dev->regs[0x22]; /* appears to mirror IN2 */ dev->regs[0x05] = dev->regs[0x22]; /* appears to mirror IN2 */
@@ -513,19 +422,6 @@ lm78_reset(lm78_t *dev, uint8_t initialization)
} else { } else {
dev->regs[0x58] = 0x10; 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 { } else {
dev->regs[0x49] = 0x40; dev->regs[0x49] = 0x40;
} }
@@ -541,7 +437,7 @@ lm78_close(void *priv)
uint16_t isa_io = (dev->local & 0xffff); uint16_t isa_io = (dev->local & 0xffff);
if (isa_io) 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); free(dev);
} }
@@ -555,11 +451,26 @@ lm78_init(const device_t *info)
dev->local = info->local; dev->local = info->local;
dev->values = hwm_get_values(); 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); lm78_reset(dev, 0);
uint16_t isa_io = (dev->local & 0xffff); uint16_t isa_io = (dev->local & 0xffff);
if (isa_io) 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; return dev;
} }
@@ -569,7 +480,7 @@ lm78_init(const device_t *info)
const device_t lm78_device = { const device_t lm78_device = {
"National Semiconductor LM78 Hardware Monitor", "National Semiconductor LM78 Hardware Monitor",
DEVICE_ISA, DEVICE_ISA,
0x295 | LM78_SMBUS, 0x290 | LM78_SMBUS,
lm78_init, lm78_close, NULL, lm78_init, lm78_close, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL NULL
@@ -580,7 +491,7 @@ const device_t lm78_device = {
const device_t w83781d_device = { const device_t w83781d_device = {
"Winbond W83781D Hardware Monitor", "Winbond W83781D Hardware Monitor",
DEVICE_ISA, DEVICE_ISA,
0x295 | LM78_SMBUS | LM78_W83781D, 0x290 | LM78_SMBUS | LM78_W83781D,
lm78_init, lm78_close, NULL, lm78_init, lm78_close, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL NULL

View File

@@ -27,10 +27,29 @@ typedef struct _hwm_values_ {
uint16_t voltages[8]; uint16_t voltages[8];
} hwm_values_t; } 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 void hwm_set_values(hwm_values_t new_values);
extern hwm_values_t* hwm_get_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 lm78_device;
extern const device_t w83781d_device; extern const device_t w83781d_device;

View File

@@ -214,7 +214,7 @@ machine_at_p3bf_init(const machine_t *model)
3000 /* Power */ 3000 /* Power */
}, { /* temperatures */ }, { /* temperatures */
30, /* MB */ 30, /* MB */
0, /* unused */ 30, /* JTPWR */
30 /* CPU */ 30 /* CPU */
}, { /* voltages */ }, { /* voltages */
2050, /* VCORE (2.05V by default) */ 2050, /* VCORE (2.05V by default) */

View File

@@ -135,7 +135,7 @@ machine_at_cubx_init(const machine_t *model)
3000 /* Power */ 3000 /* Power */
}, { /* temperatures */ }, { /* temperatures */
30, /* MB */ 30, /* MB */
0, /* unused */ 30, /* JTPWR */
30 /* CPU */ 30 /* CPU */
}, { /* voltages */ }, { /* voltages */
2050, /* VCORE (2.05V by default) */ 2050, /* VCORE (2.05V by default) */

View File

@@ -847,7 +847,8 @@ machine_at_p5mms98_init(const machine_t *model)
3000, /* CPU */ 3000, /* CPU */
3000 /* Chassis */ 3000 /* Chassis */
}, { /* temperatures */ }, { /* temperatures */
28 /* CPU (locked at 28?) */ 0, /* unused */
30 /* CPU */
}, { /* voltages */ }, { /* voltages */
3300, /* VCORE (3.3V by default) */ 3300, /* VCORE (3.3V by default) */
3300, /* VIO (3.3V) */ 3300, /* VIO (3.3V) */
@@ -873,6 +874,7 @@ machine_at_p5mms98_init(const machine_t *model)
} }
hwm_set_values(machine_hwm); hwm_set_values(machine_hwm);
device_add(&lm78_device); device_add(&lm78_device);
device_add(&lm75_1_4a_device);
return ret; return ret;
} }

View File

@@ -320,7 +320,7 @@ const machine_t machines[] = {
/* PGA370 machines */ /* PGA370 machines */
/* 440LX */ /* 440LX */
#if defined(DEV_BRANCH) && defined(NO_SIO) #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 #endif
/* 440BX */ /* 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 }, { "[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 },

View File

@@ -69,18 +69,6 @@ smbus_log(const char *fmt, ...)
#endif #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 void
smbus_init(void) smbus_init(void)
{ {
@@ -106,26 +94,8 @@ smbus_init(void)
p = NULL; 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] should be NULL. */
smbus[c] = smbus_last[c] = 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); 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); 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); 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); 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; 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; 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; 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; return;
} }

View File

@@ -73,7 +73,7 @@ spd_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv)
{ {
spd_t *dev = (spd_t *) priv; spd_t *dev = (spd_t *) priv;
uint8_t ret = *(spd_data[dev->slot] + cmd); 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; return ret;
} }
@@ -195,7 +195,7 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
/* populate slot */ /* populate slot */
vslots[vslot] = (1 << log2_ui16(MIN(total_size, max_module_size))); vslots[vslot] = (1 << log2_ui16(MIN(total_size, max_module_size)));
if (total_size >= vslots[vslot]) { 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]; total_size -= vslots[vslot];
} else { } else {
vslots[vslot] = 0; vslots[vslot] = 0;

View File

@@ -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_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 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_detect.o sio_acc3221.o \
sio_f82c710.o \ sio_f82c710.o \
sio_fdc37c66x.o sio_fdc37c669.o \ sio_fdc37c66x.o sio_fdc37c669.o \

View File

@@ -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_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 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_acc3221.o \
sio_f82c710.o \ sio_f82c710.o \
sio_fdc37c66x.o sio_fdc37c669.o \ sio_fdc37c66x.o sio_fdc37c669.o \