Finished the ALADDiN-PRO II, implemented the Contaq/Cypress 82C596(A) and 82C597 chipsets, added the ASUS P5A, Gigabyte GA-5AX, PC CHIPS M729, and Green-B, removed the "Virtual PC 2007" device as it turns out it was actually SMBus all along, did some fixes to the ALi SMBUS, fixed start LM75 SMBus address and enabled it by default, and added a ASUS P5A-specific version of the Winbond W83781D hardware monitor.

This commit is contained in:
OBattler
2021-07-12 05:56:06 +02:00
parent b674372248
commit dbddb3e309
24 changed files with 1007 additions and 489 deletions

View File

@@ -15,7 +15,7 @@
add_library(dev OBJECT bugger.c hasp.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c
hwm_vt82c686.c ibm_5161.c isamem.c isartc.c ../lpt.c pci_bridge.c
postcard.c serial.c vpc2007.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c
postcard.c serial.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c
smbus_piix4.c smbus_ali7101.c keyboard.c keyboard_xt.c keyboard_at.c
mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c phoenix_486_jumper.c)

View File

@@ -232,6 +232,9 @@ lm75_init(const device_t *info)
hwm_values.temperatures[dev->local >> 8] = 30;
dev->values = &hwm_values;
dev->i2c_addr = dev->local & 0x7f;
dev->i2c_enabled = 1;
lm75_reset(dev);
return dev;

View File

@@ -37,6 +37,7 @@
#define LM78_AS99127F_REV1 0x040000
#define LM78_AS99127F_REV2 0x080000
#define LM78_W83782D 0x100000
#define LM78_P5A 0x200000
#define LM78_AS99127F (LM78_AS99127F_REV1 | LM78_AS99127F_REV2) /* special mask covering both _REV1 and _REV2 */
#define LM78_WINBOND (LM78_W83781D | LM78_AS99127F | LM78_W83782D) /* special mask covering all Winbond variants */
#define LM78_WINBOND_VENDOR_ID ((dev->local & LM78_AS99127F_REV1) ? 0x12c3 : 0x5ca3)
@@ -258,8 +259,13 @@ lm78_reset(void *priv)
dev->regs[0x46] = 0x40;
dev->regs[0x47] = 0x50;
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;
if (!initialization) { /* don't reset main I2C address if the reset was triggered by the INITIALIZATION bit */
if (dev->local & LM78_P5A)
dev->i2c_addr = 0x77;
else
dev->i2c_addr = 0x2d;
dev->i2c_enabled = 1;
}
dev->regs[0x48] = dev->i2c_addr;
if (dev->local & LM78_WINBOND)
dev->regs[0x4a] = 0x01;
@@ -797,6 +803,17 @@ const device_t w83781d_device = {
};
/* Winbond W83781D on ISA and SMBus. */
const device_t w83781d_p5a_device = {
"Winbond W83781D Hardware Monitor (ASUS P5A)",
DEVICE_ISA,
0x290 | LM78_I2C | LM78_W83781D | LM78_P5A,
lm78_init, lm78_close, lm78_reset,
{ NULL }, NULL, NULL,
NULL
};
/* The AS99127F is an ASIC manufactured by Holtek for ASUS, containing an
I2C-only W83781D clone with additional voltages, GPIOs and fan control. */
const device_t as99127f_device = {

View File

@@ -34,6 +34,7 @@
#define PCI_BRIDGE_DEC_21150 0x10110022
#define AGP_BRIDGE_ALI_M5243 0x10b95243
#define AGP_BRIDGE_ALI_M5247 0x10b95247
#define AGP_BRIDGE_INTEL_440LX 0x80867181
#define AGP_BRIDGE_INTEL_440BX 0x80867191
#define AGP_BRIDGE_INTEL_440GX 0x808671a1
@@ -98,6 +99,9 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
if (func > 0)
return;
if ((dev->local == AGP_BRIDGE_ALI_M5247) && (addr >= 0x40))
return;
switch (addr) {
case 0x00: case 0x01: case 0x02: case 0x03:
case 0x06: case 0x08: case 0x09: case 0x0a:
@@ -112,8 +116,10 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
if (AGP_BRIDGE_INTEL(dev->local)) {
if (dev->local == AGP_BRIDGE_INTEL_440BX)
val &= 0x1f;
} else if (AGP_BRIDGE_ALI(dev->local))
} else if (dev->local == AGP_BRIDGE_ALI_M5243)
val |= 0x02;
else if (dev->local == AGP_BRIDGE_ALI_M5247)
val &= 0xc3;
else
val &= 0x67;
break;
@@ -130,8 +136,10 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
case 0x07:
if (dev->local == AGP_BRIDGE_INTEL_440LX)
dev->regs[addr] &= ~(val & 0x40);
else if (AGP_BRIDGE_ALI(dev->local))
else if (dev->local == AGP_BRIDGE_ALI_M5243)
dev->regs[addr] &= ~(val & 0xf8);
else if (dev->local == AGP_BRIDGE_ALI_M5247)
dev->regs[addr] &= ~(val & 0xc0);
return;
case 0x0c: case 0x18:
@@ -179,6 +187,10 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
case 0x3e:
if (AGP_BRIDGE_VIA(dev->local))
val &= 0x0c;
else if (dev->local == AGP_BRIDGE_ALI_M5247)
val &= 0x0f;
else if (dev->local == AGP_BRIDGE_ALI_M5243)
return;
else if (AGP_BRIDGE(dev->local)) {
if ((dev->local == AGP_BRIDGE_INTEL_440BX) ||
(dev->local == AGP_BRIDGE_INTEL_440GX))
@@ -194,7 +206,9 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
if (dev->local == AGP_BRIDGE_INTEL_440LX) {
dev->regs[addr] = ((dev->regs[addr] & 0x04) | (val & 0x02)) & ~(val & 0x04);
return;
} else if (AGP_BRIDGE_ALI(dev->local))
} else if (dev->local == AGP_BRIDGE_ALI_M5247)
return;
else if (dev->local == AGP_BRIDGE_ALI_M5243)
val &= 0x06;
else if (AGP_BRIDGE(dev->local))
return;
@@ -380,6 +394,11 @@ pci_bridge_reset(void *priv)
pci_remap_bus(dev->bus_index, 0x01);
break;
case AGP_BRIDGE_ALI_M5247:
dev->regs[0x04] = 0x03;
dev->regs[0x08] = 0x01;
break;
case AGP_BRIDGE_INTEL_440LX:
dev->regs[0x06] = 0xa0;
dev->regs[0x07] = 0x02;
@@ -395,7 +414,7 @@ pci_bridge_reset(void *priv)
case AGP_BRIDGE_VIA_597:
case AGP_BRIDGE_VIA_598:
case AGP_BRIDGE_VIA_691:
case AGP_BRIDGE_VIA_8601:
case AGP_BRIDGE_VIA_8601:
dev->regs[0x04] = 0x07;
dev->regs[0x06] = 0x20;
dev->regs[0x07] = 0x02;
@@ -413,7 +432,9 @@ pci_bridge_reset(void *priv)
else
dev->regs[0x1c] = dev->regs[0x1d] = 0x01;
if (!AGP_BRIDGE_VIA(dev->local)) {
if (dev->local == AGP_BRIDGE_ALI_M5247)
dev->regs[0x1e] = 0x20;
else if (!AGP_BRIDGE_VIA(dev->local)) {
dev->regs[0x1e] = AGP_BRIDGE(dev->local) ? 0xa0 : 0x80;
dev->regs[0x1f] = 0x02;
}
@@ -507,6 +528,21 @@ const device_t ali5243_agp_device =
NULL
};
/* AGP bridges */
const device_t ali5247_agp_device =
{
"ALi M5247 AGP Bridge",
DEVICE_PCI,
AGP_BRIDGE_ALI_M5247,
pci_bridge_init,
NULL,
pci_bridge_reset,
{ NULL },
NULL,
NULL,
NULL
};
const device_t i440lx_agp_device =
{
"Intel 82443LX/EX AGP Bridge",

View File

@@ -103,7 +103,7 @@ smbus_ali7101_write(uint16_t addr, uint8_t val, void *priv)
dev->next_stat = 0x04;
switch (addr - dev->io_base) {
case 0x00:
dev->stat &= ~(val & 0xe2);
dev->stat &= ~(val & 0xf2);
/* Make sure IDLE is set if we're not busy or errored. */
if (dev->stat == 0x00)
dev->stat = 0x04;
@@ -139,7 +139,7 @@ smbus_ali7101_write(uint16_t addr, uint8_t val, void *priv)
/* Raise DEV_ERR if no device is at this address, or if the device returned NAK when starting the transfer. */
if (!i2c_start(i2c_smbus, smbus_addr, read)) {
dev->next_stat = 0x20;
dev->next_stat = 0x40;
break;
}

View File

@@ -1,186 +0,0 @@
/*
* 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.
*
* Implementation of the port 440h device from Virtual PC 2007.
*
*
*
* Author: RichardG, <richardg867@gmail.com>
*
* Copyright 2020 RichardG.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/machine.h>
#include <86box/plat.h>
#include <86box/ui.h>
#include <86box/mem.h>
#include "cpu.h"
typedef struct {
uint8_t port440, port440read, port442, port443, port444;
} vpc2007_t;
#ifdef ENABLE_VPC2007_LOG
int vpc2007_do_log = ENABLE_VPC2007_LOG;
static void
vpc2007_log(const char *fmt, ...)
{
va_list ap;
if (vpc2007_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
int vpc2007_do_log = 0;
#define vpc2007_log(fmt, ...)
#endif
static uint8_t
vpc2007_read(uint16_t port, void *priv)
{
vpc2007_t *dev = (vpc2007_t *) priv;
uint8_t ret = 0xff;
switch (port) {
case 0x440:
ret = dev->port440read;
dev->port440read = 0x02;
break;
case 0x445:
if ((dev->port440 == 0x1e) && (dev->port442 == 0x48) && (dev->port444 == 0xa7)) {
switch (dev->port443) {
case 0x0b:
ret = 0x00;
break;
case 0x1b: case 0x05:
ret = 0x01;
break;
case 0x02:
ret = 0x02;
break;
case 0x11:
ret = 0x04;
break;
case 0x12:
ret = 0x06;
break;
case 0x04: case 0x0d:
ret = 0x08;
break;
case 0x03: case 0x09:
ret = 0x0b;
break;
case 0x15:
ret = 0x12;
break;
case 0x17:
ret = 0x40;
break;
}
}
if (ret == 0xff)
vpc2007_log("VPC2007: unknown combination %02X %02X %02X %02X\n", dev->port440, dev->port442, dev->port443, dev->port444);
break;
default:
vpc2007_log("VPC2007: read from unknown port %02X\n", port);
break;
}
return ret;
}
static void
vpc2007_write(uint16_t port, uint8_t val, void *priv)
{
vpc2007_t *dev = (vpc2007_t *) priv;
switch (port) {
case 0x440:
dev->port440 = val;
dev->port440read = 0x03;
break;
case 0x442:
dev->port442 = val;
break;
case 0x443:
dev->port443 = val;
break;
case 0x444:
dev->port444 = val;
break;
}
}
static void *
vpc2007_init(const device_t *info)
{
vpc2007_t *dev = (vpc2007_t *) malloc(sizeof(vpc2007_t));
memset(dev, 0, sizeof(vpc2007_t));
io_sethandler(0x440, 6,
vpc2007_read, NULL, NULL, vpc2007_write, NULL, NULL, dev);
return dev;
}
static void
vpc2007_close(void *priv)
{
vpc2007_t *dev = (vpc2007_t *) priv;
io_removehandler(0x440, 6,
vpc2007_read, NULL, NULL, vpc2007_write, NULL, NULL, dev);
free(dev);
}
const device_t vpc2007_device = {
"Virtual PC 2007 Port 440h Device",
DEVICE_ISA,
0,
vpc2007_init, vpc2007_close, NULL,
{ NULL }, NULL, NULL,
NULL
};