mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 18:08:20 -07:00
Move ICH2 to it's own branch
This commit is contained in:
216
src/acpi.c
216
src/acpi.c
@@ -35,6 +35,7 @@
|
||||
#include <86box/nvr.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/apm.h>
|
||||
#include <86box/tco.h>
|
||||
#include <86box/acpi.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/i2c.h>
|
||||
@@ -160,6 +161,8 @@ acpi_raise_smi(void *priv, int do_smi)
|
||||
smi_raise();
|
||||
}
|
||||
}
|
||||
else if ((dev->vendor == VEN_INTEL_ICH2) && do_smi && (dev->regs.smi_en & 1))
|
||||
smi_line = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -346,6 +349,83 @@ acpi_reg_read_intel(int size, uint16_t addr, void *p)
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
acpi_reg_read_intel_ich2(int size, uint16_t addr, void *p)
|
||||
{
|
||||
acpi_t *dev = (acpi_t *) p;
|
||||
uint32_t ret = 0x00000000;
|
||||
int shift16, shift32;
|
||||
|
||||
addr &= 0x7f;
|
||||
shift16 = (addr & 1) << 3;
|
||||
shift32 = (addr & 3) << 3;
|
||||
|
||||
switch (addr) {
|
||||
case 0x10: case 0x11: case 0x12: case 0x13:
|
||||
/* PROC_CNT—Processor Control Register */
|
||||
ret = (dev->regs.pcntrl >> shift32) & 0xff;
|
||||
break;
|
||||
case 0x28: case 0x29:
|
||||
/* GPE0_STS—General Purpose Event 0 Status Register */
|
||||
ret = (dev->regs.gpsts >> shift16) & 0xff;
|
||||
break;
|
||||
case 0x2a: case 0x2b:
|
||||
/* GPE0_EN—General Purpose Event 0 Enables Register */
|
||||
ret = (dev->regs.gpen >> shift16) & 0xff;
|
||||
break;
|
||||
case 0x2c: case 0x2d:
|
||||
/* GPE1_STS—General Purpose Event 1 Status Register */
|
||||
ret = (dev->regs.gpsts1 >> shift16) & 0xff;
|
||||
break;
|
||||
case 0x2e: case 0x2f:
|
||||
/* GPE1_EN—General Purpose Event 1 Enable Register */
|
||||
ret = (dev->regs.gpen1 >> shift16) & 0xff;
|
||||
break;
|
||||
case 0x30: case 0x31: case 0x32: case 0x33:
|
||||
/* SMI_EN—SMI Control and Enable Register */
|
||||
ret = (dev->regs.smi_en >> shift32) & 0xff;
|
||||
break;
|
||||
case 0x34: case 0x35: case 0x36: case 0x37:
|
||||
/* SMI_STS—SMI Status Register */
|
||||
ret = (dev->regs.smi_sts >> shift32) & 0xff;
|
||||
break;
|
||||
case 0x40: case 0x41:
|
||||
/* MON_SMI—Device Monitor SMI Status and Enable Register */
|
||||
ret = (dev->regs.mon_smi >> shift16) & 0xff;
|
||||
break;
|
||||
case 0x44: case 0x45:
|
||||
/* DEVACT_STS—Device Activity Status Register */
|
||||
ret = (dev->regs.devact_sts >> shift16) & 0xff;
|
||||
break;
|
||||
case 0x48: case 0x49:
|
||||
/* DEVTRAP_EN—Device Trap Enable Register */
|
||||
ret = (dev->regs.devtrap_en >> shift16) & 0xff;
|
||||
break;
|
||||
case 0x4c ... 0x4d:
|
||||
/* BUS_ADDR_TRACK—Bus Address Tracker Register */
|
||||
ret = (dev->regs.bus_addr_track >> shift16) & 0xff;
|
||||
break;
|
||||
case 0x4e:
|
||||
/* BUS_CYC_TRACK—Bus Cycle Tracker Register */
|
||||
ret = dev->regs.bus_cyc_track;
|
||||
break;
|
||||
case 0x60 ... 0x70:
|
||||
/* TCO Registers */
|
||||
ret = tco_read(addr, dev->tco);
|
||||
break;
|
||||
default:
|
||||
ret = acpi_reg_read_common_regs(size, addr, p);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ACPI_LOG
|
||||
// if (size != 1)
|
||||
// acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
acpi_reg_read_via_common(int size, uint16_t addr, void *p)
|
||||
{
|
||||
@@ -605,7 +685,11 @@ acpi_reg_write_common_regs(int size, uint16_t addr, uint8_t val, void *p)
|
||||
break;
|
||||
case 0x04: case 0x05:
|
||||
/* PMCNTRL - Power Management Control Register (IO) */
|
||||
if ((addr == 0x05) && (val & 0x20)) {
|
||||
if((addr == 0x05) && !!(val & 0x20) && !!(val & 4) && !!(dev->regs.smi_en & 0x00000010) && (dev->vendor == VEN_INTEL_ICH2)) {
|
||||
dev->regs.smi_sts |= 0x00000010; /* ICH2 Specific. Trigger an SMI if SLP_SMI_EN bit is set instead of transistioning to a Sleep State. */
|
||||
acpi_raise_smi(dev, 1);
|
||||
}
|
||||
else if ((addr == 0x05) && (val & 0x20)) {
|
||||
sus_typ = dev->suspend_types[(val >> 2) & 7];
|
||||
|
||||
if (sus_typ & SUS_POWER_OFF) {
|
||||
@@ -796,6 +880,99 @@ acpi_reg_write_intel(int size, uint16_t addr, uint8_t val, void *p)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
acpi_reg_write_intel_ich2(int size, uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
acpi_t *dev = (acpi_t *) p;
|
||||
int shift16, shift32;
|
||||
|
||||
addr &= 0x7f;
|
||||
#ifdef ENABLE_ACPI_LOG
|
||||
if (size != 1)
|
||||
acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val);
|
||||
#endif
|
||||
shift16 = (addr & 1) << 3;
|
||||
shift32 = (addr & 3) << 3;
|
||||
|
||||
switch (addr) {
|
||||
case 0x10: case 0x11: case 0x12: case 0x13:
|
||||
/* PROC_CNT—Processor Control Register */
|
||||
dev->regs.pcntrl = ((dev->regs.pcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x000201fe;
|
||||
break;
|
||||
case 0x28: case 0x29:
|
||||
/* GPE0_STS—General Purpose Event 0 Status Register */
|
||||
dev->regs.gpsts &= ~((val << shift16) & 0x09fb);
|
||||
break;
|
||||
case 0x2a: case 0x2b:
|
||||
/* GPE0_EN—General Purpose Event 0 Enables Register */
|
||||
dev->regs.gpen = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x097d;
|
||||
break;
|
||||
case 0x2c: case 0x2d:
|
||||
/* GPE1_STS—General Purpose Event 1 Status Register */
|
||||
dev->regs.gpsts1 &= ~((val << shift16) & 0x09fb);
|
||||
break;
|
||||
case 0x2e: case 0x2f:
|
||||
/* GPE1_EN—General Purpose Event 1 Enable Register */
|
||||
dev->regs.gpen1 = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x097d;
|
||||
break;
|
||||
case 0x30: case 0x31: case 0x32: case 0x33:
|
||||
/* SMI_EN—SMI Control and Enable Register */
|
||||
dev->regs.smi_en = ((dev->regs.smi_en & ~(0xff << shift32)) | (val << shift32)) & 0x0000867f;
|
||||
|
||||
if(addr == 0x30) {
|
||||
apm_set_do_smi(dev->apm, !!(val & 0x20));
|
||||
|
||||
if(val & 0x80) {
|
||||
dev->regs.glbsts |= 0x0020;
|
||||
acpi_update_irq(dev);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x34: case 0x35: case 0x36: case 0x37:
|
||||
/* SMI_STS—SMI Status Register */
|
||||
dev->regs.smi_sts &= ~((val << shift32) & 0x0001ff7c);
|
||||
break;
|
||||
case 0x40: case 0x41:
|
||||
/* MON_SMI—Device Monitor SMI Status and Enable Register */
|
||||
dev->regs.mon_smi = ((dev->regs.mon_smi & ~(0xff << shift16)) | (val << shift16)) & 0x097d;
|
||||
break;
|
||||
case 0x44: case 0x45:
|
||||
/* DEVACT_STS—Device Activity Status Register */
|
||||
dev->regs.devact_sts &= ~((val << shift16) & 0x3fef);
|
||||
break;
|
||||
case 0x48: case 0x49:
|
||||
/* DEVTRAP_EN—Device Trap Enable Register */
|
||||
dev->regs.devtrap_en = ((dev->regs.devtrap_en & ~(0xff << shift16)) | (val << shift16)) & 0x3c2f;
|
||||
if (dev->trap_update)
|
||||
dev->trap_update(dev->trap_priv);
|
||||
break;
|
||||
case 0x4c ... 0x4d:
|
||||
/* BUS_ADDR_TRACK—Bus Address Tracker Register */
|
||||
dev->regs.bus_addr_track = ((dev->regs.bus_addr_track & ~(0xff << shift16)) | (val << shift16)) & 0x097d;
|
||||
break;
|
||||
case 0x4e:
|
||||
/* BUS_CYC_TRACK—Bus Cycle Tracker Register */
|
||||
dev->regs.bus_cyc_track = val;
|
||||
break;
|
||||
case 0x60 ... 0x70:
|
||||
/* TCO Registers */
|
||||
tco_write(addr, val, dev->tco);
|
||||
break;
|
||||
default:
|
||||
acpi_reg_write_common_regs(size, addr, val, p);
|
||||
if((addr == 0x04) && !!(val & 4) && !!(dev->regs.smi_en & 4)) {
|
||||
dev->regs.smi_sts = 0x00000004;
|
||||
acpi_raise_smi(dev, 1);
|
||||
}
|
||||
|
||||
if((addr == 0x02) || !!(val & 0x20) || !!(dev->regs.glbsts & 0x0020))
|
||||
acpi_update_irq(dev);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
acpi_reg_write_via_common(int size, uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
@@ -1063,6 +1240,8 @@ acpi_reg_read_common(int size, uint16_t addr, void *p)
|
||||
ret = acpi_reg_read_via_596b(size, addr, p);
|
||||
else if (dev->vendor == VEN_INTEL)
|
||||
ret = acpi_reg_read_intel(size, addr, p);
|
||||
else if (dev->vendor == VEN_INTEL_ICH2)
|
||||
ret = acpi_reg_read_intel_ich2(size, addr, p);
|
||||
else if (dev->vendor == VEN_SMC)
|
||||
ret = acpi_reg_read_smc(size, addr, p);
|
||||
|
||||
@@ -1083,6 +1262,8 @@ acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *p)
|
||||
acpi_reg_write_via_596b(size, addr, val, p);
|
||||
else if (dev->vendor == VEN_INTEL)
|
||||
acpi_reg_write_intel(size, addr, val, p);
|
||||
else if (dev->vendor == VEN_INTEL_ICH2)
|
||||
acpi_reg_write_intel_ich2(size, addr, val, p);
|
||||
else if (dev->vendor == VEN_SMC)
|
||||
acpi_reg_write_smc(size, addr, val, p);
|
||||
}
|
||||
@@ -1276,6 +1457,7 @@ acpi_update_io_mapping(acpi_t *dev, uint32_t base, int chipset_en)
|
||||
case VEN_VIA:
|
||||
size = 0x100;
|
||||
break;
|
||||
case VEN_INTEL_ICH2:
|
||||
case VEN_VIA_596B:
|
||||
size = 0x080;
|
||||
break;
|
||||
@@ -1412,6 +1594,13 @@ acpi_set_nvr(acpi_t *dev, nvr_t *nvr)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
acpi_set_tco(acpi_t *dev, tco_t *tco)
|
||||
{
|
||||
dev->tco = tco;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
acpi_set_trap_update(acpi_t *dev, void (*update)(void *priv), void *priv)
|
||||
{
|
||||
@@ -1458,6 +1647,8 @@ acpi_apm_out(uint16_t port, uint8_t val, void *p)
|
||||
dev->apm->cmd = val;
|
||||
if (dev->vendor == VEN_INTEL)
|
||||
dev->regs.glbsts |= 0x20;
|
||||
else if (dev->vendor == VEN_INTEL_ICH2)
|
||||
dev->regs.smi_sts |= 0x00000020;
|
||||
acpi_raise_smi(dev, dev->apm->do_smi);
|
||||
} else
|
||||
dev->apm->stat = val;
|
||||
@@ -1582,7 +1773,7 @@ acpi_init(const device_t *info)
|
||||
|
||||
dev->irq_line = 9;
|
||||
|
||||
if ((dev->vendor == VEN_INTEL) || (dev->vendor == VEN_ALI)) {
|
||||
if ((dev->vendor == VEN_INTEL) || (dev->vendor == VEN_ALI) || (dev->vendor == VEN_INTEL_ICH2)) {
|
||||
if (dev->vendor == VEN_ALI)
|
||||
dev->irq_mode = 2;
|
||||
dev->apm = device_add(&apm_pci_acpi_device);
|
||||
@@ -1624,6 +1815,13 @@ acpi_init(const device_t *info)
|
||||
dev->suspend_types[3] = SUS_SUSPEND | SUS_RESET_CACHE;
|
||||
dev->suspend_types[4] = SUS_SUSPEND;
|
||||
break;
|
||||
|
||||
case VEN_INTEL_ICH2:
|
||||
dev->suspend_types[1] = SUS_SUSPEND | SUS_RESET_CPU;
|
||||
dev->suspend_types[5] = SUS_SUSPEND | SUS_NVR | SUS_RESET_CPU | SUS_RESET_PCI;
|
||||
dev->suspend_types[6] = SUS_POWER_OFF;
|
||||
dev->suspend_types[7] = SUS_POWER_OFF;
|
||||
break;
|
||||
}
|
||||
|
||||
timer_add(&dev->timer, acpi_timer_overflow, dev, 0);
|
||||
@@ -1662,6 +1860,20 @@ const device_t acpi_intel_device = {
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t acpi_intel_ich2_device = {
|
||||
.name = "Intel ICH2 ACPI",
|
||||
.internal_name = "acpi_intel_ich2",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = VEN_INTEL_ICH2,
|
||||
.init = acpi_init,
|
||||
.close = acpi_close,
|
||||
.reset = acpi_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = acpi_speed_changed,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t acpi_via_device = {
|
||||
.name = "VIA ACPI",
|
||||
.internal_name = "acpi_via",
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
|
||||
add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1489.c ali1531.c ali1541.c ali1543.c
|
||||
ali1621.c ali6117.c headland.c ims8848.c intel_82335.c contaq_82c59x.c cs4031.c intel_420ex.c
|
||||
intel_4x0.c intel_i450kx.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c
|
||||
opti495.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c
|
||||
sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c via_vt82c49x.c via_vt82c505.c sis_85c310.c
|
||||
intel_4x0.c intel_i450kx.c intel_sio.c intel_piix.c intel_815ep.c intel_ich2.c ../ioapic.c neat.c
|
||||
opti283.c opti291.c opti391.c opti495.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c
|
||||
sis_85c4xx.c sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c via_vt82c49x.c via_vt82c505.c sis_85c310.c
|
||||
sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c umc_8886.c umc_hb4.c via_apollo.c
|
||||
via_pipc.c vl82c480.c wd76c10.c)
|
||||
|
||||
|
||||
369
src/chipset/intel_815ep.c
Normal file
369
src/chipset/intel_815ep.c
Normal file
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Intel 815EP MCH Bridge
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2022 Tiseno100.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include "x86.h"
|
||||
#include <86box/timer.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/device.h>
|
||||
|
||||
#include <86box/mem.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/smram.h>
|
||||
#include <86box/spd.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
#ifdef ENABLE_INTEL_815EP_LOG
|
||||
int intel_815ep_do_log = ENABLE_INTEL_815EP_LOG;
|
||||
static void
|
||||
intel_815ep_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (intel_815ep_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define intel_815ep_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
typedef struct intel_815ep_t
|
||||
{
|
||||
uint8_t pci_conf[256];
|
||||
smram_t *lsmm_segment, *h_segment, *usmm_segment;
|
||||
} intel_815ep_t;
|
||||
|
||||
static void
|
||||
intel_usmm_segment_recalc(intel_815ep_t *dev, uint8_t val)
|
||||
{
|
||||
intel_815ep_log("Intel 815EP MCH: USMM update to status %d\n", val); /* Check the 815EP datasheet for status */
|
||||
|
||||
smram_disable(dev->h_segment);
|
||||
smram_disable(dev->usmm_segment);
|
||||
|
||||
if(val != 0)
|
||||
smram_enable(dev->h_segment, 0xfeea0000, 0x000a0000, 0x20000, 0, 1);
|
||||
|
||||
if(val >= 2) { /* TOM recalc based on intel_4x0.c by OBattler */
|
||||
uint32_t tom = (mem_size << 10);
|
||||
mem_set_mem_state_smm(tom, 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
uint32_t size = (val != 3) ? 0x100000 : 0x80000;
|
||||
smram_enable(dev->usmm_segment, tom + 0x10000000, tom, size, 0, 1);
|
||||
mem_set_mem_state_smm(tom, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
intel_lsmm_segment_recalc(intel_815ep_t *dev, uint8_t val)
|
||||
{
|
||||
intel_815ep_log("Intel 815EP MCH: LSMM update to status %d\n", val); /* Check the 815EP datasheet for status */
|
||||
|
||||
smram_disable(dev->lsmm_segment);
|
||||
|
||||
switch(val)
|
||||
{
|
||||
case 1:
|
||||
smram_enable(dev->lsmm_segment, 0x000a0000, 0x000a0000, 0x20000, 1, 0);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
smram_enable(dev->lsmm_segment, 0x000a0000, 0x000a0000, 0x20000, 0, 0);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
smram_enable(dev->lsmm_segment, 0x000a0000, 0x000a0000, 0x20000, 0, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
intel_pam_recalc(int addr, uint8_t val)
|
||||
{
|
||||
int region = 0xc0000 + ((addr - 0x5a) << 15);
|
||||
|
||||
if(addr == 0x59)
|
||||
mem_set_mem_state_both(0xf0000, 0x10000, ((val & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
|
||||
else
|
||||
{
|
||||
mem_set_mem_state_both(region, 0x4000, ((val & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((val & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
|
||||
mem_set_mem_state_both(region + 0x4000, 0x4000, ((val & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
intel_815ep_write(int func, int addr, uint8_t val, void *priv)
|
||||
{
|
||||
intel_815ep_t *dev = (intel_815ep_t *)priv;
|
||||
|
||||
intel_815ep_log("Intel 815EP MCH: dev->regs[%02x] = %02x\n", addr, val);
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case 0x05:
|
||||
dev->pci_conf[addr] = val & 3;
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
dev->pci_conf[addr] &= val & 0x70;
|
||||
break;
|
||||
|
||||
case 0x2c ... 0x2f:
|
||||
if(dev->pci_conf[addr] != 0)
|
||||
dev->pci_conf[addr] = val;
|
||||
break;
|
||||
|
||||
case 0x13:
|
||||
dev->pci_conf[addr] = val & 0xfe;
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
dev->pci_conf[addr] = val & 0xdc;
|
||||
break;
|
||||
|
||||
case 0x51:
|
||||
dev->pci_conf[addr] = val & 2; // Brute force to AGP Mode
|
||||
break;
|
||||
|
||||
case 0x52:
|
||||
case 0x54:
|
||||
if (!(dev->pci_conf[0x70] & 2)) {
|
||||
dev->pci_conf[addr] = val & ((addr & 4) ? 0x0f : 0xff);
|
||||
spd_write_drbs_intel_815ep(dev->pci_conf);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x53:
|
||||
dev->pci_conf[addr] = val;
|
||||
break;
|
||||
|
||||
case 0x58:
|
||||
dev->pci_conf[addr] = val & 0x80;
|
||||
break;
|
||||
|
||||
case 0x59 ... 0x5f:
|
||||
dev->pci_conf[addr] = val;
|
||||
intel_pam_recalc(addr, val);
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
if(!(dev->pci_conf[0x70] & 2)) {
|
||||
dev->pci_conf[addr] = val & 0xfe;
|
||||
intel_usmm_segment_recalc(dev, (val >> 4) & 3);
|
||||
}
|
||||
else {
|
||||
dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfa) | (val & 4);
|
||||
}
|
||||
|
||||
intel_lsmm_segment_recalc(dev, (val >> 2) & 3);
|
||||
break;
|
||||
|
||||
case 0x72:
|
||||
dev->pci_conf[addr] = val & 0xfb;
|
||||
break;
|
||||
|
||||
case 0x73:
|
||||
dev->pci_conf[addr] = val & 0xa8;
|
||||
break;
|
||||
|
||||
case 0x92 ... 0x93:
|
||||
dev->pci_conf[addr] = val;
|
||||
break;
|
||||
|
||||
case 0x94:
|
||||
dev->pci_conf[addr] = val & 0x3f;
|
||||
break;
|
||||
|
||||
case 0x98:
|
||||
dev->pci_conf[addr] = val & 0x77;
|
||||
break;
|
||||
|
||||
case 0x99:
|
||||
dev->pci_conf[addr] = val & 0x80;
|
||||
break;
|
||||
|
||||
case 0x9a:
|
||||
dev->pci_conf[addr] = val & 0xef;
|
||||
break;
|
||||
|
||||
case 0x9b:
|
||||
case 0x9d:
|
||||
dev->pci_conf[addr] = val & 0x80;
|
||||
break;
|
||||
|
||||
case 0xa4:
|
||||
dev->pci_conf[addr] = val & 7;
|
||||
break;
|
||||
|
||||
case 0xa8:
|
||||
dev->pci_conf[addr] = val & 0x37;
|
||||
break;
|
||||
|
||||
case 0xa9:
|
||||
dev->pci_conf[addr] = (val & 2) | 1;
|
||||
break;
|
||||
|
||||
case 0xb0:
|
||||
dev->pci_conf[addr] = val & 0x81;
|
||||
break;
|
||||
|
||||
case 0xb4:
|
||||
dev->pci_conf[addr] = val & 8;
|
||||
break;
|
||||
|
||||
case 0xb9:
|
||||
dev->pci_conf[addr] = val & 0xf0;
|
||||
break;
|
||||
|
||||
case 0xba:
|
||||
dev->pci_conf[addr] = val;
|
||||
break;
|
||||
|
||||
case 0xbb:
|
||||
dev->pci_conf[addr] = val & 0x1f;
|
||||
break;
|
||||
|
||||
case 0xbc ... 0xbd:
|
||||
dev->pci_conf[addr] = val & 0xf8;
|
||||
break;
|
||||
|
||||
case 0xbe:
|
||||
dev->pci_conf[addr] = val & 0x28;
|
||||
break;
|
||||
|
||||
case 0xcb:
|
||||
dev->pci_conf[addr] = val & 0x3f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
intel_815ep_read(int func, int addr, void *priv)
|
||||
{
|
||||
intel_815ep_t *dev = (intel_815ep_t *)priv;
|
||||
|
||||
intel_815ep_log("Intel 815EP MCH: dev->regs[%02x] (%02x)\n", addr, dev->pci_conf[addr]);
|
||||
|
||||
if(addr == 0x51) // Bit 2 is Write Only. It cannot be read.
|
||||
return dev->pci_conf[addr] & 3;
|
||||
else
|
||||
return dev->pci_conf[addr];
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
intel_815ep_reset(void *priv)
|
||||
{
|
||||
intel_815ep_t *dev = (intel_815ep_t *)priv;
|
||||
memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf)); /* Wash out the registers */
|
||||
|
||||
dev->pci_conf[0x00] = 0x86; /* Intel */
|
||||
dev->pci_conf[0x01] = 0x80;
|
||||
|
||||
dev->pci_conf[0x02] = 0x30; /* 815EP */
|
||||
dev->pci_conf[0x03] = 0x11;
|
||||
|
||||
dev->pci_conf[0x04] = 0x06;
|
||||
|
||||
dev->pci_conf[0x06] = 0x90;
|
||||
dev->pci_conf[0x08] = 0x02;
|
||||
dev->pci_conf[0x0b] = 0x06;
|
||||
dev->pci_conf[0x10] = 0x03;
|
||||
dev->pci_conf[0x34] = 0xa0;
|
||||
dev->pci_conf[0x50] = 0x40;
|
||||
|
||||
dev->pci_conf[0x88] = 0x09;
|
||||
dev->pci_conf[0x89] = 0xa0;
|
||||
dev->pci_conf[0x8a] = 0x04;
|
||||
dev->pci_conf[0x8b] = 0xf1;
|
||||
|
||||
dev->pci_conf[0x92] = 0xff;
|
||||
dev->pci_conf[0x93] = 0xff;
|
||||
dev->pci_conf[0x94] = 0xff;
|
||||
dev->pci_conf[0x95] = 0xff;
|
||||
|
||||
dev->pci_conf[0xa0] = 0x02;
|
||||
dev->pci_conf[0xa2] = 0x20;
|
||||
|
||||
dev->pci_conf[0xa4] = 0x07;
|
||||
dev->pci_conf[0xa5] = 0x02;
|
||||
dev->pci_conf[0xa7] = 0x1f;
|
||||
|
||||
dev->pci_conf[0xa9] = 0x01; /* Hack: Brute Force AGP Enabled */
|
||||
|
||||
for(int i = 0x58; i <= 0x5f; i++) /* Reset PAM to defaults */
|
||||
intel_pam_recalc(i, 0);
|
||||
|
||||
intel_lsmm_segment_recalc(dev, 0); /* Reset LSMM SMRAM to defaults */
|
||||
intel_usmm_segment_recalc(dev, 0); /* Reset USMM SMRAM to defaults */
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
intel_815ep_close(void *priv)
|
||||
{
|
||||
intel_815ep_t *dev = (intel_815ep_t *)priv;
|
||||
|
||||
smram_del(dev->lsmm_segment);
|
||||
smram_del(dev->h_segment);
|
||||
smram_del(dev->usmm_segment);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
intel_815ep_init(const device_t *info)
|
||||
{
|
||||
intel_815ep_t *dev = (intel_815ep_t *)malloc(sizeof(intel_815ep_t));
|
||||
memset(dev, 0, sizeof(intel_815ep_t));
|
||||
|
||||
/* Device */
|
||||
pci_add_card(PCI_ADD_NORTHBRIDGE, intel_815ep_read, intel_815ep_write, dev); /* Device 0: Intel 815EP MCH */
|
||||
|
||||
/* AGP Bridge */
|
||||
device_add(&intel_815ep_agp_device);
|
||||
|
||||
/* L1 & L2 Cache */
|
||||
cpu_cache_int_enabled = 1;
|
||||
cpu_cache_ext_enabled = 1;
|
||||
cpu_update_waitstates();
|
||||
|
||||
/* SMRAM Segments */
|
||||
dev->lsmm_segment = smram_add();
|
||||
dev->h_segment = smram_add();
|
||||
dev->usmm_segment = smram_add();
|
||||
|
||||
intel_815ep_reset(dev);
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t intel_815ep_device = {
|
||||
.name = "Intel 815EP MCH Bridge",
|
||||
.internal_name = "intel_815ep",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = 0,
|
||||
.init = intel_815ep_init,
|
||||
.close = intel_815ep_close,
|
||||
.reset = intel_815ep_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
903
src/chipset/intel_ich2.c
Normal file
903
src/chipset/intel_ich2.c
Normal file
@@ -0,0 +1,903 @@
|
||||
/*
|
||||
* Intel ICH2
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2022 Tiseno100.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include "x86.h"
|
||||
#include <86box/timer.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/device.h>
|
||||
|
||||
#include <86box/apm.h>
|
||||
#include <86box/nvr.h>
|
||||
|
||||
#include <86box/acpi.h>
|
||||
#include <86box/dma.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/hdc_ide.h>
|
||||
#include <86box/hdc_ide_sff8038i.h>
|
||||
#include <86box/intel_ich2_gpio.h>
|
||||
#include <86box/intel_ich2_trap.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/pic.h>
|
||||
#include <86box/port_92.h>
|
||||
#include <86box/smbus.h>
|
||||
#include <86box/tco.h>
|
||||
#include <86box/usb.h>
|
||||
|
||||
#include <86box/chipset.h>
|
||||
|
||||
#ifdef ENABLE_INTEL_ICH2_LOG
|
||||
int intel_ich2_do_log = ENABLE_INTEL_ICH2_LOG;
|
||||
static void
|
||||
intel_ich2_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (intel_ich2_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define intel_ich2_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
typedef struct intel_ich2_t
|
||||
{
|
||||
uint8_t pci_conf[5][256];
|
||||
|
||||
acpi_t *acpi;
|
||||
intel_ich2_gpio_t *gpio;
|
||||
intel_ich2_trap_t *trap_device[10];
|
||||
nvr_t *nvr;
|
||||
sff8038i_t *ide_drive[2];
|
||||
smbus_piix4_t *smbus;
|
||||
tco_t *tco;
|
||||
usb_t *usb_hub[2];
|
||||
|
||||
} intel_ich2_t;
|
||||
|
||||
/* LPC Bridge functions */
|
||||
static void
|
||||
intel_ich2_acpi_setup(intel_ich2_t *dev)
|
||||
{
|
||||
uint32_t base = (dev->pci_conf[0][0x41] << 8) | (dev->pci_conf[0][0x40] & 0x80);
|
||||
int acpi_irq = ((dev->pci_conf[0][0x44] & 7) < 3) ? (9 + (dev->pci_conf[0][0x44] & 7)) : 9; /* Under APIC you can set this even higher but */
|
||||
int enable = !!(dev->pci_conf[0][0x44] & 0x10); /* as we lack it we are restricted with low. */
|
||||
|
||||
acpi_update_io_mapping(dev->acpi, base, enable);
|
||||
acpi_set_irq_line(dev->acpi, acpi_irq);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_ich2_trap_update(void *priv)
|
||||
{
|
||||
intel_ich2_t *dev = (intel_ich2_t *) priv;
|
||||
uint16_t temp_addr = 0;
|
||||
|
||||
/* Hard Drives */
|
||||
intel_ich2_device_trap_setup(1, 0x48, 0x01, 0x1f0, 8, 1, dev->trap_device[0]); // HDD's don't have a decode bit
|
||||
intel_ich2_device_trap_setup(1, 0x48, 0x01, 0x3f6, 1, 1, dev->trap_device[0]);
|
||||
|
||||
intel_ich2_device_trap_setup(1, 0x48, 0x02, 0x170, 8, 1, dev->trap_device[1]);
|
||||
intel_ich2_device_trap_setup(1, 0x48, 0x02, 0x376, 1, 1, dev->trap_device[1]);
|
||||
|
||||
/* COM A */
|
||||
switch(dev->pci_conf[0][0xe0] & 7)
|
||||
{
|
||||
case 0:
|
||||
temp_addr = 0x3f8;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
temp_addr = 0x2f8;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
temp_addr = 0x220;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
temp_addr = 0x228;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
temp_addr = 0x238;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
temp_addr = 0x2e8;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
temp_addr = 0x338;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
temp_addr = 0x3e8;
|
||||
break;
|
||||
}
|
||||
intel_ich2_device_trap_setup(!!(dev->pci_conf[0][0xe6] & 1), 0x48, 0x10, temp_addr, 8, 0, dev->trap_device[2]);
|
||||
|
||||
/* COM B */
|
||||
switch((dev->pci_conf[0][0xe0] >> 4) & 7)
|
||||
{
|
||||
case 0:
|
||||
temp_addr = 0x3f8;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
temp_addr = 0x2f8;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
temp_addr = 0x220;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
temp_addr = 0x228;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
temp_addr = 0x238;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
temp_addr = 0x2e8;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
temp_addr = 0x338;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
temp_addr = 0x3e8;
|
||||
break;
|
||||
}
|
||||
intel_ich2_device_trap_setup(!!(dev->pci_conf[0][0xe6] & 2), 0x48, 0x10, temp_addr, 8, 0, dev->trap_device[3]);
|
||||
|
||||
/* LPT */
|
||||
switch(dev->pci_conf[0][0xe1] & 3)
|
||||
{
|
||||
case 0:
|
||||
temp_addr = 0x378;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
temp_addr = 0x278;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
temp_addr = 0x3bc;
|
||||
break;
|
||||
}
|
||||
intel_ich2_device_trap_setup(!!(dev->pci_conf[0][0xe6] & 4), 0x48, 0x10, temp_addr, 8, 0, dev->trap_device[4]);
|
||||
|
||||
/* FDC */
|
||||
temp_addr = (dev->pci_conf[0][0xe1] & 0x10) ? 0x3f0 : 0x370;
|
||||
intel_ich2_device_trap_setup(!!(dev->pci_conf[0][0xe6] & 8), 0x48, 0x10, temp_addr, 8, 0, dev->trap_device[5]);
|
||||
|
||||
/* MSS */
|
||||
switch((dev->pci_conf[0][0xe2] >> 4) & 3)
|
||||
{
|
||||
case 0:
|
||||
temp_addr = 0x530;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
temp_addr = 0x604;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
temp_addr = 0xe80;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
temp_addr = 0xf40;
|
||||
break;
|
||||
}
|
||||
intel_ich2_device_trap_setup(!!(dev->pci_conf[0][0xe6] & 0x40), 0x49, 0x04, 0x170, 8, 0, dev->trap_device[6]);
|
||||
|
||||
/* MIDI */
|
||||
temp_addr = (dev->pci_conf[0][0xe2] & 8) ? 0x300 : 0x330;
|
||||
intel_ich2_device_trap_setup(!!(dev->pci_conf[0][0xe6] & 0x20), 0x49, 0x08, temp_addr, 2, 0, dev->trap_device[7]);
|
||||
|
||||
/* KBC */
|
||||
intel_ich2_device_trap_setup(1, 0x49, 0x10, 0x60, 4, 0, dev->trap_device[8]); // KBC doesn't have a decode bit
|
||||
|
||||
/* Adlib */
|
||||
intel_ich2_device_trap_setup(!!(dev->pci_conf[0][0xe6] & 0x80), 0x49, 0x20, 0x388, 4, 0, dev->trap_device[9]);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_ich2_tco_interrupt(intel_ich2_t *dev)
|
||||
{
|
||||
uint16_t tco_irq = ((dev->pci_conf[0][0x54] & 7) < 3) ? (9 + (dev->pci_conf[0][0x45] & 7)) : 9; /* Under APIC you can set this even higher but */
|
||||
/* as we lack it we are restricted with low. */
|
||||
tco_irq_update(dev->tco, tco_irq);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_ich2_gpio_setup(intel_ich2_t *dev)
|
||||
{
|
||||
uint16_t base = (dev->pci_conf[0][0x59] << 8) | (dev->pci_conf[0][0x58] & 0xc0);
|
||||
int enable = !!(dev->pci_conf[0][0x5c] & 0x10);
|
||||
|
||||
intel_ich2_gpio_base(enable, base, dev->gpio);
|
||||
}
|
||||
|
||||
static int
|
||||
intel_ich2_pirq_table(uint8_t val)
|
||||
{
|
||||
switch(val)
|
||||
{
|
||||
case 0 ... 2:
|
||||
case 8:
|
||||
case 13:
|
||||
return PCI_IRQ_DISABLED;
|
||||
|
||||
default:
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
intel_ich2_pirq_update(int reset, int addr, uint8_t val)
|
||||
{
|
||||
int pirq = (addr >= 0x68) ? (addr - 0x63) : (addr - 0x5f);
|
||||
|
||||
if(((val & 0x80) != 0x80) && !reset) { /* 86Box doesn't have an APIC yet. */
|
||||
intel_ich2_log("Intel ICH2 LPC: Update PIRQ %c to IRQ %d\n", '@' + pirq, val); /* Under normal circumstances on an APIC enabled motherboard*/
|
||||
pci_set_irq_routing(pirq, intel_ich2_pirq_table(val)); /* this remains disabled and the IRQ are handed by the APIC */
|
||||
} /* itself. */
|
||||
else if(reset)
|
||||
for(int i = 1; i <= 8; i++)
|
||||
pci_set_irq_routing(i, PCI_IRQ_DISABLED);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_ich2_nvr_handler(intel_ich2_t *dev)
|
||||
{
|
||||
intel_ich2_log("Intel ICH2 LPC: Extended NVR Aliases %s\n", (dev->pci_conf[0][0xd8] & 4) ? "Enabled" : "Disabled");
|
||||
|
||||
nvr_at_handler(!!(dev->pci_conf[0][0xd8] & 4), 0x74, dev->nvr);
|
||||
nvr_at_handler(!!(dev->pci_conf[0][0xd8] & 4), 0x76, dev->nvr);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_ich2_function_disable(intel_ich2_t *dev)
|
||||
{
|
||||
uint16_t smbus_addr = (dev->pci_conf[3][0x21] << 8) | (dev->pci_conf[3][0x20] & 0xf0); // Hold the SMBus Base Address value
|
||||
|
||||
/* Disable IDE */
|
||||
if(dev->pci_conf[0][0xf2] & 2) {
|
||||
ide_pri_disable();
|
||||
ide_sec_disable();
|
||||
}
|
||||
|
||||
/* Disable USB Hub 1 */
|
||||
if(dev->pci_conf[0][0xf2] & 4) {
|
||||
uhci_update_io_mapping(dev->usb_hub[0], dev->pci_conf[2][0x20] & 0xe0, dev->pci_conf[0][0x21], 0);
|
||||
}
|
||||
|
||||
/* Disable SMBus */
|
||||
if(dev->pci_conf[0][0xf2] & 8) { //ICH2 Supports the ability of the SMBus Controller to be active even if it's PCI device is disabled
|
||||
smbus_piix4_remap(dev->smbus, smbus_addr, dev->pci_conf[0][0xf3] & 1);
|
||||
}
|
||||
|
||||
/* Disable USB Hub 2 */
|
||||
if(dev->pci_conf[0][0xf2] & 0x10) {
|
||||
uhci_update_io_mapping(dev->usb_hub[1], 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* IDE Controller functions */
|
||||
static void
|
||||
intel_ich2_ide_setup(intel_ich2_t *dev)
|
||||
{
|
||||
ide_pri_disable();
|
||||
ide_sec_disable();
|
||||
|
||||
intel_ich2_log("Intel ICH2 IDE: Primary Channel is %s.\n", !!(dev->pci_conf[1][0x41] & 0x80) ? "Enabled" : "Disabled");
|
||||
if(dev->pci_conf[1][0x41] & 0x80) {
|
||||
ide_pri_enable();
|
||||
}
|
||||
|
||||
intel_ich2_log("Intel ICH2 IDE: Secondary Channel is %s.\n", !!(dev->pci_conf[1][0x43] & 0x80) ? "Enabled" : "Disabled");
|
||||
if(dev->pci_conf[1][0x43] & 0x80) {
|
||||
ide_sec_enable();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
intel_ich2_bus_master_setup(intel_ich2_t *dev)
|
||||
{
|
||||
uint16_t bm_base = ((dev->pci_conf[1][0x21] & 0xf0) << 8) | (dev->pci_conf[1][0x20] & 0xf0);
|
||||
intel_ich2_log("Intel ICH2 IDE: IDE Bus Master address is 0x%04x.\n", bm_base);
|
||||
sff_bus_master_handler(dev->ide_drive[0], dev->pci_conf[1][0x04] & 1, bm_base);
|
||||
sff_bus_master_handler(dev->ide_drive[1], dev->pci_conf[1][0x04] & 1, bm_base + 8);
|
||||
}
|
||||
/* USB Controller functions */
|
||||
static void
|
||||
intel_ich2_usb_setup(int func, intel_ich2_t* dev)
|
||||
{
|
||||
int current_hub = (func == 4) ? 4 : 2;
|
||||
int hub_num = (func == 4);
|
||||
uhci_update_io_mapping(dev->usb_hub[hub_num], dev->pci_conf[current_hub][0x20] & 0xe0, dev->pci_conf[current_hub][0x21], !!(dev->pci_conf[current_hub][0x04] & 1));
|
||||
}
|
||||
|
||||
/* SMBus Controller functions */
|
||||
static void
|
||||
intel_ich2_smbus_setup(intel_ich2_t *dev)
|
||||
{
|
||||
uint16_t base = (dev->pci_conf[3][0x21] << 8) | (dev->pci_conf[3][0x20] & 0xf0);
|
||||
|
||||
if((dev->pci_conf[3][0x40] & 1) && (dev->pci_conf[3][0x04] & 1))
|
||||
intel_ich2_log("Intel ICH2 SMBus: SMBus is enabled.\n");
|
||||
|
||||
smbus_piix4_remap(dev->smbus, base, (dev->pci_conf[3][0x40] & 1) && (dev->pci_conf[3][0x04] & 1));
|
||||
}
|
||||
|
||||
/* ICH2 Registers */
|
||||
static void
|
||||
intel_ich2_write(int func, int addr, uint8_t val, void *priv)
|
||||
{
|
||||
intel_ich2_t *dev = (intel_ich2_t *)priv;
|
||||
|
||||
if(func == 0) {
|
||||
intel_ich2_log("Intel ICH2 LPC: dev->regs[%02x] = %02x\n", addr, val);
|
||||
switch(addr)
|
||||
{
|
||||
case 0x04:
|
||||
dev->pci_conf[func][addr] = (val & 0x40) | 0x0f;
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
dev->pci_conf[func][addr] = val & 0x01;
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
dev->pci_conf[func][addr] &= val & 0xf9;
|
||||
break;
|
||||
|
||||
case 0x40 ... 0x41:
|
||||
dev->pci_conf[func][addr] = val & ((addr & 1) ? 0xff : (0x80 | 1));
|
||||
intel_ich2_acpi_setup(dev);
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
dev->pci_conf[func][addr] = val & 0x17;
|
||||
intel_ich2_acpi_setup(dev);
|
||||
break;
|
||||
|
||||
case 0x4e:
|
||||
dev->pci_conf[func][addr] = val & 0x03;
|
||||
if((val & 0x01) && ((val & 0x02) == 0x02))
|
||||
smi_line = 1;
|
||||
break;
|
||||
|
||||
case 0x54:
|
||||
dev->pci_conf[func][addr] = val & 0x0f;
|
||||
intel_ich2_tco_interrupt(dev);
|
||||
break;
|
||||
|
||||
case 0x58 ... 0x59:
|
||||
dev->pci_conf[func][addr] = val & ((addr & 1) ? 0xff : (0xc0 | 1));
|
||||
intel_ich2_gpio_setup(dev);
|
||||
break;
|
||||
|
||||
case 0x5c:
|
||||
dev->pci_conf[func][addr] = val & 0x10;
|
||||
intel_ich2_gpio_setup(dev);
|
||||
break;
|
||||
|
||||
case 0x60 ... 0x63:
|
||||
case 0x68 ... 0x6b:
|
||||
dev->pci_conf[func][addr] = val & 0x8f;
|
||||
intel_ich2_pirq_update(0, addr, val);
|
||||
break;
|
||||
|
||||
case 0x64:
|
||||
dev->pci_conf[func][addr] = val;
|
||||
break;
|
||||
|
||||
case 0x88:
|
||||
dev->pci_conf[func][addr] = val & 6;
|
||||
break;
|
||||
|
||||
case 0x8a:
|
||||
dev->pci_conf[func][addr] &= val & 6;
|
||||
break;
|
||||
|
||||
case 0x90:
|
||||
dev->pci_conf[func][addr] = val;
|
||||
break;
|
||||
|
||||
case 0x91:
|
||||
dev->pci_conf[func][addr] = val & 0xfc;
|
||||
break;
|
||||
|
||||
case 0xd0:
|
||||
dev->pci_conf[func][addr] = val & 0x4f; /* Brute force APIC support as disabled */
|
||||
break;
|
||||
|
||||
case 0xd1:
|
||||
dev->pci_conf[func][addr] = val & 0x38; /* Brute force APIC support as disabled */
|
||||
break;
|
||||
|
||||
case 0xd3:
|
||||
dev->pci_conf[func][addr] = val & 0x03;
|
||||
break;
|
||||
|
||||
case 0xd4:
|
||||
dev->pci_conf[func][addr] = val & 0x02;
|
||||
break;
|
||||
|
||||
case 0xd5:
|
||||
dev->pci_conf[func][addr] = val & 0x3f;
|
||||
break;
|
||||
|
||||
case 0xd8:
|
||||
dev->pci_conf[func][addr] = val & 0x1c;
|
||||
intel_ich2_nvr_handler(dev);
|
||||
break;
|
||||
|
||||
case 0xe0:
|
||||
dev->pci_conf[func][addr] = val & 0x77;
|
||||
break;
|
||||
|
||||
case 0xe1:
|
||||
dev->pci_conf[func][addr] = val & 0x13;
|
||||
intel_ich2_trap_update(dev);
|
||||
break;
|
||||
|
||||
case 0xe2:
|
||||
dev->pci_conf[func][addr] = val & 0x3b;
|
||||
intel_ich2_trap_update(dev);
|
||||
break;
|
||||
|
||||
case 0xe3:
|
||||
dev->pci_conf[func][addr] = val;
|
||||
break;
|
||||
|
||||
case 0xe4:
|
||||
dev->pci_conf[func][addr] = val & 0x81;
|
||||
break;
|
||||
|
||||
case 0xe5 ... 0xe6:
|
||||
dev->pci_conf[func][addr] = val;
|
||||
|
||||
if(addr == 0xe6)
|
||||
intel_ich2_trap_update(dev);
|
||||
break;
|
||||
|
||||
case 0xe7:
|
||||
dev->pci_conf[func][addr] = val & 0x3f;
|
||||
break;
|
||||
|
||||
case 0xe8 ... 0xeb:
|
||||
dev->pci_conf[func][addr] = val;
|
||||
break;
|
||||
|
||||
case 0xec:
|
||||
dev->pci_conf[func][addr] = val & 0xf1;
|
||||
break;
|
||||
|
||||
case 0xed:
|
||||
dev->pci_conf[func][addr] = val;
|
||||
break;
|
||||
|
||||
case 0xee ... 0xef:
|
||||
dev->pci_conf[func][addr] = val;
|
||||
break;
|
||||
|
||||
case 0xf0:
|
||||
dev->pci_conf[func][addr] = val & 0x0f;
|
||||
break;
|
||||
|
||||
case 0xf2 ... 0xf3:
|
||||
dev->pci_conf[func][addr] = val & ((addr & 1) ? 0x01 : 0xfe);
|
||||
intel_ich2_function_disable(dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if((func == 1) && !(dev->pci_conf[0][0xf2] & 2)) {
|
||||
intel_ich2_log("Intel ICH2 IDE: dev->regs[%02x] = %02x\n", addr, val);
|
||||
switch(addr)
|
||||
{
|
||||
case 0x04:
|
||||
dev->pci_conf[func][addr] = val & 5;
|
||||
intel_ich2_ide_setup(dev);
|
||||
intel_ich2_bus_master_setup(dev);
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
dev->pci_conf[func][addr] &= val & 0x2e;
|
||||
break;
|
||||
|
||||
case 0x20 ... 0x21:
|
||||
dev->pci_conf[func][addr] = val & ((addr & 1) ? 0xff : (0xf0 | 1));
|
||||
intel_ich2_bus_master_setup(dev);
|
||||
break;
|
||||
|
||||
case 0x2c ... 0x2f:
|
||||
if(dev->pci_conf[func][addr] != 0)
|
||||
dev->pci_conf[func][addr] = val;
|
||||
break;
|
||||
|
||||
case 0x40 ... 0x43:
|
||||
dev->pci_conf[func][addr] = val & ((addr & 1) ? 0xf3 : 0xff);
|
||||
intel_ich2_ide_setup(dev);
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
dev->pci_conf[func][addr] = val;
|
||||
break;
|
||||
|
||||
case 0x48:
|
||||
dev->pci_conf[func][addr] = val & 0x0f;
|
||||
break;
|
||||
|
||||
case 0x4a ... 0x4b:
|
||||
dev->pci_conf[func][addr] = val & 0x33;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(((func == 2) && !(dev->pci_conf[0][0xf2] & 4)) || ((func == 4) && !(dev->pci_conf[0][0xf2] & 0x10))) {
|
||||
intel_ich2_log("Intel ICH2 USB Hub %d: dev->regs[%02x] = %02x\n", (func == 4), addr, val);
|
||||
switch(addr)
|
||||
{
|
||||
case 0x04:
|
||||
dev->pci_conf[func][addr] = val & 5;
|
||||
intel_ich2_usb_setup(func, dev);
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
dev->pci_conf[func][addr] &= val & 0x2e;
|
||||
break;
|
||||
|
||||
case 0x20 ... 0x21:
|
||||
dev->pci_conf[func][addr] = val & ((addr & 1) ? 0xff : (0xf0 | 1));
|
||||
intel_ich2_usb_setup(func, dev);
|
||||
break;
|
||||
|
||||
case 0xc0:
|
||||
dev->pci_conf[func][addr] = val & 0xbf;
|
||||
break;
|
||||
|
||||
case 0xc1:
|
||||
dev->pci_conf[func][addr] &= val & 0xaf;
|
||||
break;
|
||||
|
||||
case 0xc4:
|
||||
dev->pci_conf[func][addr] = val & 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if((func == 3) && !(dev->pci_conf[0][0xf2] & 8)) {
|
||||
intel_ich2_log("Intel ICH2 SMBus: dev->regs[%02x] = %02x\n", addr, val);
|
||||
switch(addr)
|
||||
{
|
||||
case 0x04:
|
||||
dev->pci_conf[func][addr] = val & 1;
|
||||
intel_ich2_smbus_setup(dev);
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
dev->pci_conf[func][addr] &= val & 0x0e;
|
||||
break;
|
||||
|
||||
case 0x20 ... 0x21:
|
||||
dev->pci_conf[func][addr] = val & ((addr & 1) ? 0xff : (0xf0 | 1));
|
||||
intel_ich2_smbus_setup(dev);
|
||||
break;
|
||||
|
||||
case 0x3c:
|
||||
dev->pci_conf[func][addr] = val;
|
||||
smbus_piix4_get_irq(val, dev->smbus);
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
dev->pci_conf[func][addr] = val & 7;
|
||||
intel_ich2_smbus_setup(dev);
|
||||
smbus_piix4_smi_en(!!(val & 2), dev->smbus);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
intel_ich2_read(int func, int addr, void *priv)
|
||||
{
|
||||
intel_ich2_t *dev = (intel_ich2_t *)priv;
|
||||
|
||||
if(func == 0) {
|
||||
intel_ich2_log("Intel ICH2 LPC: dev->regs[%02x] (%02x)\n", addr, dev->pci_conf[func][addr]);
|
||||
return dev->pci_conf[func][addr];
|
||||
}
|
||||
else if((func == 1) && !(dev->pci_conf[0][0xf2] & 2)) {
|
||||
intel_ich2_log("Intel ICH2 IDE: dev->regs[%02x] (%02x)\n", addr, dev->pci_conf[func][addr]);
|
||||
return dev->pci_conf[func][addr];
|
||||
}
|
||||
else if(((func == 2) && !(dev->pci_conf[0][0xf2] & 4)) || ((func == 4) && !(dev->pci_conf[0][0xf2] & 0x10))) {
|
||||
intel_ich2_log("Intel ICH2 USB Hub %d: dev->regs[%02x] (%02x)\n", (func == 4), addr, dev->pci_conf[func][addr]);
|
||||
|
||||
if((addr >= 0x2c) && (addr <= 0x2f)) /* USB shares the same subsystem vendor info as the IDE */
|
||||
return dev->pci_conf[1][addr];
|
||||
|
||||
return dev->pci_conf[func][addr];
|
||||
}
|
||||
else if((func == 3) && !(dev->pci_conf[0][0xf2] & 8)) {
|
||||
intel_ich2_log("Intel ICH2 SMBus: dev->regs[%02x] (%02x)\n", addr, dev->pci_conf[func][addr]);
|
||||
|
||||
if((addr >= 0x2c) && (addr <= 0x2f)) /* SMBus shares the same subsystem vendor info as the IDE */
|
||||
return dev->pci_conf[1][addr];
|
||||
|
||||
return dev->pci_conf[func][addr];
|
||||
}
|
||||
else return 0xff;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
intel_ich2_reset(void *priv)
|
||||
{
|
||||
intel_ich2_t *dev = (intel_ich2_t *)priv;
|
||||
memset(dev->pci_conf, 0, sizeof(dev->pci_conf)); /* Wash out the Registers */
|
||||
|
||||
/* Function 0: LPC Bridge */
|
||||
dev->pci_conf[0][0x00] = 0x86;
|
||||
dev->pci_conf[0][0x01] = 0x80;
|
||||
|
||||
dev->pci_conf[0][0x02] = 0x40;
|
||||
dev->pci_conf[0][0x03] = 0x24;
|
||||
|
||||
dev->pci_conf[0][0x04] = 0x0f;
|
||||
|
||||
dev->pci_conf[0][0x06] = 0x80;
|
||||
dev->pci_conf[0][0x07] = 0x02;
|
||||
|
||||
dev->pci_conf[0][0x08] = 0x02;
|
||||
|
||||
dev->pci_conf[0][0x0a] = 0x01;
|
||||
dev->pci_conf[0][0x0b] = 0x06;
|
||||
|
||||
dev->pci_conf[0][0x0e] = 0x80;
|
||||
|
||||
dev->pci_conf[0][0x40] = 0x01;
|
||||
|
||||
dev->pci_conf[0][0x58] = 0x01;
|
||||
|
||||
dev->pci_conf[0][0x60] = 0x80;
|
||||
dev->pci_conf[0][0x61] = 0x80;
|
||||
dev->pci_conf[0][0x62] = 0x80;
|
||||
dev->pci_conf[0][0x63] = 0x80;
|
||||
|
||||
dev->pci_conf[0][0x64] = 0x10;
|
||||
|
||||
dev->pci_conf[0][0x68] = 0x80;
|
||||
dev->pci_conf[0][0x69] = 0x80;
|
||||
dev->pci_conf[0][0x6a] = 0x80;
|
||||
dev->pci_conf[0][0x6b] = 0x80;
|
||||
|
||||
dev->pci_conf[0][0xd5] = 0x0f;
|
||||
|
||||
dev->pci_conf[0][0xe3] = 0xff;
|
||||
|
||||
dev->pci_conf[0][0xe8] = 0x33;
|
||||
dev->pci_conf[0][0xe9] = 0x22;
|
||||
dev->pci_conf[0][0xea] = 0x11;
|
||||
dev->pci_conf[0][0xeb] = 0x00;
|
||||
|
||||
dev->pci_conf[0][0xee] = 0x78;
|
||||
dev->pci_conf[0][0xef] = 0x56;
|
||||
|
||||
dev->pci_conf[0][0xf0] = 0x0f;
|
||||
|
||||
intel_ich2_acpi_setup(dev); /* Setup the ACPI Interface */
|
||||
intel_ich2_tco_interrupt(dev); /* Configure the TCO Interrupt */
|
||||
intel_ich2_gpio_setup(dev); /* Setup the GPIO */
|
||||
intel_ich2_pirq_update(1, 0, 0); /* Reset the PIRQ interrupts */
|
||||
intel_ich2_nvr_handler(dev); /* Set the NVR aliases */
|
||||
|
||||
/* Function 1: IDE Controller */
|
||||
dev->pci_conf[1][0x00] = 0x86;
|
||||
dev->pci_conf[1][0x01] = 0x80;
|
||||
|
||||
dev->pci_conf[1][0x02] = 0x4b;
|
||||
dev->pci_conf[1][0x03] = 0x24;
|
||||
|
||||
dev->pci_conf[1][0x06] = 0x80;
|
||||
dev->pci_conf[1][0x07] = 0x02;
|
||||
|
||||
dev->pci_conf[1][0x08] = 0x02;
|
||||
|
||||
dev->pci_conf[1][0x09] = 0x80;
|
||||
dev->pci_conf[1][0x0a] = 0x01;
|
||||
dev->pci_conf[1][0x0b] = 0x01;
|
||||
|
||||
dev->pci_conf[1][0x20] = 0x01;
|
||||
|
||||
dev->pci_conf[1][0x54] = 0xff; /* Hack: Fake Cable Conductor & UltraDMA details */
|
||||
|
||||
if(cpu_busspeed >= 100000000) /* Go UltraDMA 100 if CPU is up for it. Not that it actually matters */
|
||||
dev->pci_conf[1][0x55] = 0xf0;
|
||||
|
||||
sff_bus_master_reset(dev->ide_drive[0], 0); /* Setup the IDE */
|
||||
sff_bus_master_reset(dev->ide_drive[1], 8);
|
||||
intel_ich2_ide_setup(dev);
|
||||
|
||||
/* Function 2: USB Hub 0 */
|
||||
dev->pci_conf[2][0x00] = 0x86;
|
||||
dev->pci_conf[2][0x01] = 0x80;
|
||||
|
||||
dev->pci_conf[2][0x02] = 0x42;
|
||||
dev->pci_conf[2][0x03] = 0x24;
|
||||
|
||||
dev->pci_conf[2][0x06] = 0x80;
|
||||
dev->pci_conf[2][0x07] = 0x02;
|
||||
|
||||
dev->pci_conf[2][0x08] = 0x02;
|
||||
|
||||
dev->pci_conf[2][0x0a] = 0x03;
|
||||
dev->pci_conf[2][0x0b] = 0x0c;
|
||||
|
||||
dev->pci_conf[2][0x20] = 0x01;
|
||||
|
||||
dev->pci_conf[2][0x3d] = 0x03;
|
||||
|
||||
dev->pci_conf[2][0x60] = 0x10;
|
||||
|
||||
dev->pci_conf[2][0xc1] = 0x20;
|
||||
|
||||
intel_ich2_usb_setup(2, dev);
|
||||
|
||||
/* Function 3: SMBus Controller */
|
||||
dev->pci_conf[3][0x00] = 0x86;
|
||||
dev->pci_conf[3][0x01] = 0x80;
|
||||
|
||||
dev->pci_conf[3][0x02] = 0x43;
|
||||
dev->pci_conf[3][0x03] = 0x24;
|
||||
|
||||
dev->pci_conf[3][0x06] = 0x80;
|
||||
dev->pci_conf[3][0x07] = 0x02;
|
||||
|
||||
dev->pci_conf[3][0x08] = 0x02;
|
||||
|
||||
dev->pci_conf[3][0x09] = 0x80;
|
||||
dev->pci_conf[3][0x0a] = 0x05;
|
||||
dev->pci_conf[3][0x0b] = 0x0c;
|
||||
|
||||
dev->pci_conf[3][0x20] = 0x01;
|
||||
|
||||
dev->pci_conf[3][0x3d] = 0x02;
|
||||
|
||||
intel_ich2_smbus_setup(dev); /* Setup the SMBus */
|
||||
|
||||
/* Function 4: USB Hub 1*/
|
||||
dev->pci_conf[4][0x00] = 0x86;
|
||||
dev->pci_conf[4][0x01] = 0x80;
|
||||
|
||||
dev->pci_conf[4][0x02] = 0x44;
|
||||
dev->pci_conf[4][0x03] = 0x24;
|
||||
|
||||
dev->pci_conf[4][0x06] = 0x80;
|
||||
dev->pci_conf[4][0x07] = 0x02;
|
||||
|
||||
dev->pci_conf[4][0x08] = 0x02;
|
||||
|
||||
dev->pci_conf[4][0x0a] = 0x03;
|
||||
dev->pci_conf[4][0x0b] = 0x0c;
|
||||
|
||||
dev->pci_conf[4][0x20] = 0x01;
|
||||
|
||||
dev->pci_conf[4][0x3d] = 0x03;
|
||||
|
||||
dev->pci_conf[4][0x60] = 0x10;
|
||||
|
||||
dev->pci_conf[4][0xc1] = 0x20;
|
||||
|
||||
intel_ich2_usb_setup(4, dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
intel_ich2_close(void *priv)
|
||||
{
|
||||
intel_ich2_t *dev = (intel_ich2_t *)priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
intel_ich2_init(const device_t *info)
|
||||
{
|
||||
intel_ich2_t *dev = (intel_ich2_t *)malloc(sizeof(intel_ich2_t));
|
||||
memset(dev, 0, sizeof(intel_ich2_t));
|
||||
int slot;
|
||||
|
||||
/* Device */
|
||||
slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, intel_ich2_read, intel_ich2_write, dev); /* Device 31: Intel ICH2 */
|
||||
|
||||
/* ACPI Interface */
|
||||
dev->acpi = device_add(&acpi_intel_ich2_device);
|
||||
acpi_set_slot(dev->acpi, slot);
|
||||
|
||||
/* DMA */
|
||||
dma_alias_set_piix();
|
||||
dma_lpc_init();
|
||||
|
||||
/* GPIO */
|
||||
dev->gpio = device_add(&intel_ich2_gpio_device);
|
||||
|
||||
/* NVR Handler */
|
||||
dev->nvr = device_add(&piix4_nvr_device);
|
||||
acpi_set_nvr(dev->acpi, dev->nvr);
|
||||
|
||||
/* Intel ICH2 Hub */
|
||||
device_add(&intel_ich2_hub_device);
|
||||
|
||||
/* PIC */
|
||||
pic_set_pci();
|
||||
|
||||
/* SMBus */
|
||||
dev->smbus = device_add(&intel_ich2_smbus_device);
|
||||
smbus_piix4_get_acpi(dev->smbus, dev->acpi);
|
||||
|
||||
/* SFF Compatible IDE Drives */
|
||||
dev->ide_drive[0] = device_add_inst(&sff8038i_device, 1);
|
||||
dev->ide_drive[1] = device_add_inst(&sff8038i_device, 2);
|
||||
sff_set_slot(dev->ide_drive[0], slot);
|
||||
sff_set_slot(dev->ide_drive[1], slot);
|
||||
|
||||
/* TCO */
|
||||
dev->tco = device_add(&tco_device);
|
||||
acpi_set_tco(dev->acpi, dev->tco);
|
||||
|
||||
/* I/O Traps */
|
||||
acpi_set_trap_update(dev->acpi, intel_ich2_trap_update, dev);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
dev->trap_device[i] = device_add_inst(&intel_ich2_trap_device, i + 1);
|
||||
intel_ich2_trap_set_acpi(dev->trap_device[i], dev->acpi);
|
||||
}
|
||||
|
||||
/* USB */
|
||||
dev->usb_hub[0] = device_add_inst(&usb_device, 1);
|
||||
dev->usb_hub[1] = device_add_inst(&usb_device, 2);
|
||||
|
||||
intel_ich2_reset(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t intel_ich2_device = {
|
||||
.name = "Intel ICH2",
|
||||
.internal_name = "intel_ich2",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = 0,
|
||||
.init = intel_ich2_init,
|
||||
.close = intel_ich2_close,
|
||||
.reset = intel_ich2_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
@@ -2439,6 +2439,22 @@ amd_k_invalid_rdmsr:
|
||||
EAX = msr.ecx187 & 0xffffffff;
|
||||
EDX = msr.ecx187 >> 32;
|
||||
break;
|
||||
case 0x198:
|
||||
EAX = msr.ecx198 & 0xffffffff;
|
||||
EDX = msr.ecx198 >> 32;
|
||||
break;
|
||||
case 0x19a:
|
||||
EAX = msr.ecx19a & 0xffffffff;
|
||||
EDX = msr.ecx19a >> 32;
|
||||
break;
|
||||
case 0x19d:
|
||||
EAX = msr.ecx19d & 0xffffffff;
|
||||
EDX = msr.ecx19d >> 32;
|
||||
break;
|
||||
case 0x1a0:
|
||||
EAX = msr.ecx1a0 & 0xffffffff;
|
||||
EDX = msr.ecx1a0 >> 32;
|
||||
break;
|
||||
case 0x1e0:
|
||||
EAX = msr.ecx1e0 & 0xffffffff;
|
||||
EDX = msr.ecx1e0 >> 32;
|
||||
@@ -2814,6 +2830,18 @@ amd_k_invalid_wrmsr:
|
||||
case 0x187:
|
||||
msr.ecx187 = EAX | ((uint64_t)EDX << 32);
|
||||
break;
|
||||
case 0x198:
|
||||
msr.ecx198 = EAX | ((uint64_t)EDX << 32);
|
||||
break;
|
||||
case 0x19a:
|
||||
msr.ecx19a = EAX | ((uint64_t)EDX << 32);
|
||||
break;
|
||||
case 0x19d:
|
||||
msr.ecx19d = EAX | ((uint64_t)EDX << 32);
|
||||
break;
|
||||
case 0x1a0:
|
||||
msr.ecx1a0 = EAX | ((uint64_t)EDX << 32);
|
||||
break;
|
||||
case 0x1e0:
|
||||
msr.ecx1e0 = EAX | ((uint64_t)EDX << 32);
|
||||
break;
|
||||
|
||||
@@ -284,6 +284,12 @@ typedef struct {
|
||||
on the VIA Cyrix III */
|
||||
uint64_t mtrr_deftype; /* 0x000002ff */
|
||||
|
||||
/* Pentium II/III/IV MSR's needed for late BIOS */
|
||||
uint64_t ecx1a0; /* 0x000001a0 */
|
||||
uint64_t ecx198; /* 0x00000198 */
|
||||
uint64_t ecx19a; /* 0x0000019a */
|
||||
uint64_t ecx19d; /* 0x0000019d */
|
||||
|
||||
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
|
||||
uint64_t mca_ctl[5]; /* 0x00000400, 0x00000404, 0x00000408, 0x0000040c, 0x00000410 - Machine Check Architecture */
|
||||
uint64_t ecx570; /* 0x00000570 */
|
||||
|
||||
@@ -13,11 +13,12 @@
|
||||
# Copyright 2020,2021 David Hrdlička.
|
||||
#
|
||||
|
||||
add_library(dev OBJECT bugger.c cassette.c cartridge.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
|
||||
add_library(dev OBJECT bugger.c cassette.c cartridge.c hasp.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c hwm_nsc366.c
|
||||
hwm_vt82c686.c ibm_5161.c intel_ich2_gpio.c intel_ich2_trap.c isamem.c isartc.c ../lpt.c pci_bridge.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)
|
||||
mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c phoenix_486_jumper.c
|
||||
tco.c)
|
||||
|
||||
if(ISAMEM_RAMPAGE)
|
||||
target_compile_definitions(dev PRIVATE USE_ISAMEM_RAMPAGE)
|
||||
|
||||
399
src/device/hwm_nsc366.c
Normal file
399
src/device/hwm_nsc366.c
Normal file
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
* National Semiconductor PC87366(NSC366) Hardware Monitor
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2022 Tiseno100.
|
||||
*/
|
||||
|
||||
/* The conversion algorithms were taken by the pc87360.c driver of the Linux kernel.
|
||||
Respective credits goes to the authors. */
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/device.h>
|
||||
|
||||
#include <86box/hwm.h>
|
||||
#include <86box/nsc366.h>
|
||||
|
||||
#define FAN_TO_REG(val, div) ((val) <= 100 ? 0 : 480000 / ((val) * (div)))
|
||||
#define FAN_DIV_FROM_REG(val) (1 << (((val) >> 5) & 0x03))
|
||||
#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : 480000 / ((val) * (div)))
|
||||
|
||||
#define IN_TO_REG(val, ref) ((val) < 0 ? 0 : (val) * 256 >= (ref) * 255 ? 255 : ((val) * 256 + (ref) / 2) / (ref))
|
||||
#define IN_FROM_REG(val, ref) (((val) * (ref) + 128) / 256)
|
||||
#define VREF (dev->vlm_config_global[0x08] & 2) ? 3025 : 2966 //VREF taken from pc87360.c
|
||||
#define VLM_BANK dev->vlm_config_global[0x09]
|
||||
|
||||
#define TEMP_TO_REG(val) ((val) < -55000 ? -55 : (val) > 127000 ? 127 : (val) < 0 ? ((val) - 500) / 1000 : ((val) + 500) / 1000)
|
||||
#define TEMP_FROM_REG(val) ((val) * 1000)
|
||||
#define TMS_BANK dev->tms_config_global[0x09]
|
||||
|
||||
#ifdef ENABLE_NSC366_HWM_LOG
|
||||
int nsc366_hwm_do_log = ENABLE_NSC366_HWM_LOG;
|
||||
void
|
||||
nsc366_hwm_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (nsc366_hwm_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define nsc366_hwm_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
/* Fans */
|
||||
static void
|
||||
nsc366_fscm_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
nsc366_hwm_t *dev = (nsc366_hwm_t *)priv;
|
||||
|
||||
addr &= 0x0f;
|
||||
|
||||
nsc366_hwm_log("NSC366 Fan Control: Write 0x%02x to register 0x%02x\n", val, addr);
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x02:
|
||||
case 0x04:
|
||||
dev->fscm_config[addr] = val;
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
case 0x03:
|
||||
case 0x05:
|
||||
dev->fscm_config[addr] = val;
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
case 0x09:
|
||||
case 0x0c:
|
||||
dev->fscm_config[addr] = val;
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
case 0x0b:
|
||||
case 0x0d:
|
||||
dev->fscm_config[addr] = (val & 0x78) | 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
nsc366_fscm_read(uint16_t addr, void *priv)
|
||||
{
|
||||
nsc366_hwm_t *dev = (nsc366_hwm_t *)priv;
|
||||
|
||||
addr &= 0x0f;
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case 0x00 ... 0x06:
|
||||
case 0x08 ... 0x09:
|
||||
case 0x0b ... 0x0c:
|
||||
return dev->fscm_config[addr];
|
||||
|
||||
case 0x07:
|
||||
case 0x0a:
|
||||
case 0x0d:
|
||||
nsc366_hwm_log("NSC366 Fan Control: Reading %d RPM's from Bank %d\n", FAN_FROM_REG(dev->fscm_config[addr], FAN_DIV_FROM_REG(dev->fscm_config[0x06])), (addr - 7) / 3);
|
||||
return dev->fscm_config[addr];
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsc366_update_fscm_io(int enable, uint16_t addr, nsc366_hwm_t *dev)
|
||||
{
|
||||
if(dev->fscm_addr != 0)
|
||||
io_removehandler(dev->fscm_addr, 15, nsc366_fscm_read, NULL, NULL, nsc366_fscm_write, NULL, NULL, dev);
|
||||
|
||||
dev->fscm_addr = addr;
|
||||
|
||||
if((addr != 0) && enable)
|
||||
io_sethandler(addr, 15, nsc366_fscm_read, NULL, NULL, nsc366_fscm_write, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
/* Voltage */
|
||||
static void
|
||||
nsc366_vlm_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
nsc366_hwm_t *dev = (nsc366_hwm_t *)priv;
|
||||
|
||||
addr &= 0x0f;
|
||||
|
||||
if(addr <= 9)
|
||||
nsc366_hwm_log("NSC366 Voltage Monitor: Write 0x%02x to register 0x%02x\n", val, addr);
|
||||
else
|
||||
nsc366_hwm_log("NSC366 Voltage Monitor: Write 0x%02x to register 0x%02x of bank %d\n", val, addr, VLM_BANK);
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case 0x02 ... 0x04:
|
||||
dev->vlm_config_global[addr] = val;
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
dev->vlm_config_global[addr] = val & 0x3f;
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
dev->vlm_config_global[addr] = val & 0xc0;
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
dev->vlm_config_global[addr] = val & 0x3f;
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
dev->vlm_config_global[addr] = val & 3;
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
dev->vlm_config_global[addr] = val & 0x1f;
|
||||
break;
|
||||
|
||||
case 0x0a:
|
||||
if(VLM_BANK < 13)
|
||||
dev->vlm_config_bank[VLM_BANK][addr - 0x0a] = val & 1;
|
||||
break;
|
||||
|
||||
case 0x0c ... 0x0e:
|
||||
if(VLM_BANK < 13)
|
||||
dev->vlm_config_bank[VLM_BANK][addr - 0x0a] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
nsc366_vlm_read(uint16_t addr, void *priv)
|
||||
{
|
||||
nsc366_hwm_t *dev = (nsc366_hwm_t *)priv;
|
||||
|
||||
addr &= 0x0f;
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case 0x00 ... 0x09:
|
||||
return dev->vlm_config_global[addr];
|
||||
|
||||
case 0x0a:
|
||||
case 0x0c ... 0x0e:
|
||||
if(VLM_BANK < 13)
|
||||
return dev->vlm_config_bank[VLM_BANK][addr - 0x0a];
|
||||
else
|
||||
return 0;
|
||||
|
||||
case 0x0b:
|
||||
if (VLM_BANK < 13) {
|
||||
nsc366_hwm_log("NSC366 Voltage Monitor: Reading %d Volts from Bank %d\n", IN_FROM_REG(dev->vlm_config_bank[VLM_BANK][1], VREF), VLM_BANK);
|
||||
return dev->vlm_config_bank[VLM_BANK][1];
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsc366_update_vlm_io(int enable, uint16_t addr, nsc366_hwm_t *dev)
|
||||
{
|
||||
if(dev->vlm_addr != 0)
|
||||
io_removehandler(dev->vlm_addr, 15, nsc366_vlm_read, NULL, NULL, nsc366_vlm_write, NULL, NULL, dev);
|
||||
|
||||
dev->vlm_addr = addr;
|
||||
|
||||
if((addr != 0) && enable)
|
||||
io_sethandler(addr, 15, nsc366_vlm_read, NULL, NULL, nsc366_vlm_write, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
/* Temperature */
|
||||
static void
|
||||
nsc366_tms_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
nsc366_hwm_t *dev = (nsc366_hwm_t *)priv;
|
||||
|
||||
addr &= 0x0f;
|
||||
|
||||
if(addr <= 9)
|
||||
nsc366_hwm_log("NSC366 Temperature Monitor: Write 0x%02x to register 0x%02x\n", val, addr);
|
||||
else
|
||||
nsc366_hwm_log("NSC366 Temperature Monitor: Write 0x%02x to register 0x%02x of bank %d\n", val, addr, TMS_BANK);
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case 0x02:
|
||||
dev->tms_config_global[addr] = val & 0x3f;
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
dev->tms_config_global[addr] = val & 0x3f;
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
dev->tms_config_global[addr] = val & 3;
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
dev->tms_config_global[addr] = val & 3;
|
||||
break;
|
||||
|
||||
case 0x0a:
|
||||
if(TMS_BANK < 3)
|
||||
dev->tms_config_bank[TMS_BANK][addr - 0x0a] = val & 1;
|
||||
break;
|
||||
|
||||
case 0x0c ... 0x0e:
|
||||
if(TMS_BANK < 13)
|
||||
dev->tms_config_bank[TMS_BANK][addr - 0x0a] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
nsc366_tms_read(uint16_t addr, void *priv)
|
||||
{
|
||||
nsc366_hwm_t *dev = (nsc366_hwm_t *)priv;
|
||||
|
||||
addr &= 0x0f;
|
||||
addr++;
|
||||
pclog("Reading %02x\n", addr);
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case 0x00 ... 0x09:
|
||||
return dev->tms_config_global[addr];
|
||||
|
||||
case 0x0a:
|
||||
case 0x0c ... 0x0e:
|
||||
//return dev->tms_config_bank[TMS_BANK][addr - 0x0a];
|
||||
return 1;
|
||||
|
||||
case 0x0b:
|
||||
nsc366_hwm_log("NSC366 Temperature Monitor: Reading %d Degrees Celsius from Bank %d\n", TEMP_FROM_REG(dev->tms_config_bank[TMS_BANK][1]), TMS_BANK);
|
||||
return dev->tms_config_bank[TMS_BANK][1];
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsc366_update_tms_io(int enable, uint16_t addr, nsc366_hwm_t *dev)
|
||||
{
|
||||
if(dev->vlm_addr != 0)
|
||||
io_removehandler(dev->tms_addr, 15, nsc366_tms_read, NULL, NULL, nsc366_tms_write, NULL, NULL, dev);
|
||||
|
||||
dev->tms_addr = addr;
|
||||
|
||||
if((addr != 0) && enable)
|
||||
io_sethandler(addr, 15, nsc366_tms_read, NULL, NULL, nsc366_tms_write, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
#define TEMP_FROM_REG(val) ((val) * 1000)
|
||||
|
||||
static void
|
||||
nsc366_hwm_reset(void *priv)
|
||||
{
|
||||
nsc366_hwm_t *dev = (nsc366_hwm_t *)priv;
|
||||
memset(dev->fscm_config, 0, sizeof(dev->fscm_config));
|
||||
dev->fscm_addr = 0;
|
||||
|
||||
/* Get fan reports from defaults */
|
||||
dev->fscm_config[0x07] = FAN_TO_REG(dev->values->fans[0], FAN_DIV_FROM_REG(dev->fscm_config[0x06]));
|
||||
dev->fscm_config[0x0a] = FAN_TO_REG(dev->values->fans[1], FAN_DIV_FROM_REG(dev->fscm_config[0x06]));
|
||||
dev->fscm_config[0x0d] = FAN_TO_REG(dev->values->fans[2], FAN_DIV_FROM_REG(dev->fscm_config[0x06]));
|
||||
|
||||
memset(dev->vlm_config_global, 0, sizeof(dev->vlm_config_global));
|
||||
memset(dev->vlm_config_bank, 0, sizeof(dev->vlm_config_bank));
|
||||
dev->vlm_addr = 0;
|
||||
dev->vlm_config_global[0x08] = 3;
|
||||
|
||||
/* Get voltage reports from defaults */
|
||||
for(int i = 0; i < 13; i++) {
|
||||
dev->vlm_config_bank[i][1] = IN_TO_REG(dev->values->voltages[i], VREF);
|
||||
}
|
||||
|
||||
memset(dev->tms_config_global, 0, sizeof(dev->tms_config_global));
|
||||
memset(dev->tms_config_bank, 0, sizeof(dev->tms_config_bank));
|
||||
dev->tms_addr = 0;
|
||||
dev->tms_config_global[0x08] = 3;
|
||||
|
||||
/* Get temperature reports from defaults */
|
||||
for(int i = 0; i < 4; i++)
|
||||
dev->tms_config_bank[i][1] = TEMP_TO_REG(dev->values->temperatures[i]);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nsc366_hwm_close(void *priv)
|
||||
{
|
||||
nsc366_hwm_t *dev = (nsc366_hwm_t *)priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
nsc366_hwm_init(const device_t *info)
|
||||
{
|
||||
nsc366_hwm_t *dev = (nsc366_hwm_t *)malloc(sizeof(nsc366_hwm_t));
|
||||
memset(dev, 0, sizeof(nsc366_hwm_t));
|
||||
|
||||
/* Initialize the default values */
|
||||
hwm_values_t defaults = {
|
||||
{
|
||||
3000, /* FAN 0 */
|
||||
3000, /* FAN 1 */
|
||||
3000 /* FAN 2 */
|
||||
},
|
||||
{
|
||||
255, /* Temperature 0 */
|
||||
255,
|
||||
255,
|
||||
155
|
||||
},
|
||||
{
|
||||
65535,
|
||||
65535,
|
||||
65535,
|
||||
}
|
||||
};
|
||||
hwm_values = defaults;
|
||||
dev->values = &hwm_values;
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t nsc366_hwm_device = {
|
||||
.name = "National Semiconductor NSC366 Hardware Monitor",
|
||||
.internal_name = "nsc366_hwm",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = nsc366_hwm_init,
|
||||
.close = nsc366_hwm_close,
|
||||
.reset = nsc366_hwm_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
180
src/device/intel_ich2_gpio.c
Normal file
180
src/device/intel_ich2_gpio.c
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Intel ICH2 GPIO
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2022 Tiseno100.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/intel_ich2_gpio.h>
|
||||
|
||||
#ifdef ENABLE_INTEL_ICH2_GPIO_LOG
|
||||
int intel_ich2_gpio_do_log = ENABLE_INTEL_ICH2_GPIO_LOG;
|
||||
static void
|
||||
intel_ich2_gpio_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (intel_ich2_gpio_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define intel_ich2_gpio_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
intel_ich2_gpio_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
intel_ich2_gpio_t *dev = (intel_ich2_gpio_t *) priv;
|
||||
|
||||
addr -= dev->gpio_addr;
|
||||
|
||||
intel_ich2_gpio_log("Intel ICH2 GPIO: Write 0x%02x on GPIO Register 0x%02x\n", val, addr);
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
/* GPIO Use Enable */
|
||||
case 0x00:
|
||||
dev->gpio_regs[addr] = val & 0x3f;
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
dev->gpio_regs[addr] = val & 8;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
dev->gpio_regs[addr] = val & 0x20;
|
||||
break;
|
||||
|
||||
/* GPIO I/O Select */
|
||||
case 0x07:
|
||||
dev->gpio_regs[addr] = val & 0x1b;
|
||||
break;
|
||||
|
||||
/* GPIO Level */
|
||||
case 0x0e:
|
||||
dev->gpio_regs[addr] = val;
|
||||
break;
|
||||
|
||||
case 0x0f:
|
||||
dev->gpio_regs[addr] = val & 0x1b;
|
||||
dev->gpio_regs[addr] &= dev->gpio_regs[0x1b]; // Mask out whatever change if the bits aren't programmed as outputs.
|
||||
break;
|
||||
|
||||
/* GPIO Blink which is not Utilized */
|
||||
case 0x1a:
|
||||
dev->gpio_regs[addr] = val & 6;
|
||||
break;
|
||||
|
||||
case 0x1b:
|
||||
dev->gpio_regs[addr] = val & 0x1a;
|
||||
break;
|
||||
|
||||
/* GPIO Signal Inverter */
|
||||
case 0x2d:
|
||||
dev->gpio_regs[addr] = val & 0x39;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
intel_ich2_gpio_read(uint16_t addr, void *priv)
|
||||
{
|
||||
intel_ich2_gpio_t *dev = (intel_ich2_gpio_t *) priv;
|
||||
|
||||
addr -= dev->gpio_addr;
|
||||
|
||||
intel_ich2_gpio_log("Intel ICH2 GPIO: Reading 0x%02x from Register 0x%02x\n", dev->gpio_regs[addr], addr);
|
||||
|
||||
if(addr <= 0x2f)
|
||||
return dev->gpio_regs[addr];
|
||||
else
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void
|
||||
intel_ich2_gpio_base(int enable, uint16_t addr, intel_ich2_gpio_t *dev)
|
||||
{
|
||||
if(dev->gpio_addr != 0)
|
||||
io_removehandler(dev->gpio_addr, 15, intel_ich2_gpio_read, NULL, NULL, intel_ich2_gpio_write, NULL, NULL, dev);
|
||||
|
||||
dev->gpio_addr = addr;
|
||||
|
||||
if((addr != 0) && enable)
|
||||
io_sethandler(addr, 15, intel_ich2_gpio_read, NULL, NULL, intel_ich2_gpio_write, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_ich2_gpio_reset(void *priv)
|
||||
{
|
||||
intel_ich2_gpio_t *dev = (intel_ich2_gpio_t *) priv;
|
||||
dev->gpio_addr = 0;
|
||||
|
||||
/* Enabled GPIO's */
|
||||
dev->gpio_regs[0x00] = 0x80;
|
||||
dev->gpio_regs[0x01] = 0x31;
|
||||
dev->gpio_regs[0x03] = 0x1a;
|
||||
|
||||
/* GPIO Drives (Input or Output) */
|
||||
dev->gpio_regs[0x04] = 0xff;
|
||||
dev->gpio_regs[0x05] = 0xff;
|
||||
|
||||
dev->gpio_regs[0x0e] = 0x3f;
|
||||
dev->gpio_regs[0x0f] = 0x1b;
|
||||
|
||||
dev->gpio_regs[0x16] = 0x63;
|
||||
dev->gpio_regs[0x17] = 0x06;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
intel_ich2_gpio_close(void *priv)
|
||||
{
|
||||
intel_ich2_gpio_t *dev = (intel_ich2_gpio_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
intel_ich2_gpio_init(const device_t *info)
|
||||
{
|
||||
intel_ich2_gpio_t *dev = (intel_ich2_gpio_t *) malloc(sizeof(intel_ich2_gpio_t));
|
||||
memset(dev, 0, sizeof(intel_ich2_gpio_t));
|
||||
|
||||
intel_ich2_gpio_reset(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t intel_ich2_gpio_device = {
|
||||
.name = "Intel ICH2 GPIO",
|
||||
.internal_name = "intel_ich2_gpio",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = intel_ich2_gpio_init,
|
||||
.close = intel_ich2_gpio_close,
|
||||
.reset = intel_ich2_gpio_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
107
src/device/intel_ich2_trap.c
Normal file
107
src/device/intel_ich2_trap.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Intel ICH2 Trap Handler
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2022 Tiseno100.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/device.h>
|
||||
|
||||
#include <86box/apm.h>
|
||||
#include <86box/nvr.h>
|
||||
#include <86box/acpi.h>
|
||||
|
||||
#include <86box/intel_ich2_trap.h>
|
||||
|
||||
#ifdef ENABLE_INTEL_ICH2_TRAP_LOG
|
||||
int intel_ich2_trap_do_log = ENABLE_INTEL_ICH2_TRAP_LOG;
|
||||
static void
|
||||
intel_ich2_trap_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (intel_ich2_trap_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define intel_ich2_trap_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
void
|
||||
intel_ich2_trap_set_acpi(intel_ich2_trap_t *trap, acpi_t *acpi)
|
||||
{
|
||||
trap->acpi = acpi;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_ich2_trap_kick(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv)
|
||||
{
|
||||
intel_ich2_trap_t *trap = (intel_ich2_trap_t *) priv;
|
||||
intel_ich2_trap_log("Intel ICH2 Trap: Entered an I/O Trap. Provoking an SMI.\n");
|
||||
acpi_raise_smi(trap->acpi, 1);
|
||||
}
|
||||
|
||||
void
|
||||
intel_ich2_device_trap_setup(int enable, uint8_t acpi_reg, uint8_t acpi_reg_val, uint16_t addr, uint16_t size, int is_hdd, intel_ich2_trap_t *trap)
|
||||
{
|
||||
uint8_t acpi_trap_recieve = ((acpi_reg == 0x49) ? (trap->acpi->regs.devtrap_en >> 8) : (trap->acpi->regs.devtrap_en)) & 0xff; // Check if the decoded range is enabled on ACPIS
|
||||
int acpi_enable = !!(acpi_trap_recieve & acpi_reg_val);
|
||||
int trap_enabled = acpi_enable && enable;
|
||||
|
||||
if(trap_enabled)
|
||||
{
|
||||
intel_ich2_trap_log("Intel ICH2 Trap: An I/O has been enabled on range 0x%x\n", addr);
|
||||
io_trap_add(intel_ich2_trap_kick, trap->trap);
|
||||
}
|
||||
|
||||
io_trap_remap(trap->trap, trap_enabled, addr, size);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_ich2_trap_close(void *priv)
|
||||
{
|
||||
intel_ich2_trap_t *trap = (intel_ich2_trap_t *) priv;
|
||||
|
||||
io_trap_remove(trap->trap); // Remove the I/O Trap
|
||||
free(trap);
|
||||
}
|
||||
|
||||
static void *
|
||||
intel_ich2_trap_init(const device_t *info)
|
||||
{
|
||||
intel_ich2_trap_t *trap = (intel_ich2_trap_t *) malloc(sizeof(intel_ich2_trap_t));
|
||||
memset(trap, 0, sizeof(intel_ich2_trap_t));
|
||||
|
||||
intel_ich2_trap_log("Intel ICH2 Trap: Starting a new Trap handler.");
|
||||
|
||||
return trap;
|
||||
}
|
||||
|
||||
const device_t intel_ich2_trap_device = {
|
||||
.name = "Intel ICH2 Trap Hander",
|
||||
.internal_name = "intel_ich2_trap",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = intel_ich2_trap_init,
|
||||
.close = intel_ich2_trap_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
@@ -33,20 +33,22 @@
|
||||
|
||||
|
||||
#define PCI_BRIDGE_DEC_21150 0x10110022
|
||||
#define PCI_BRIDGE_INTEL_ICH2 0x8086244e
|
||||
#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
|
||||
#define AGP_BRIDGE_INTEL_815EP 0x80861131
|
||||
#define AGP_BRIDGE_VIA_597 0x11068597
|
||||
#define AGP_BRIDGE_VIA_598 0x11068598
|
||||
#define AGP_BRIDGE_VIA_691 0x11068691
|
||||
#define AGP_BRIDGE_VIA_8601 0x11068601
|
||||
|
||||
#define AGP_BRIDGE_ALI(x) (((x) >> 16) == 0x10b9)
|
||||
#define AGP_BRIDGE_INTEL(x) (((x) >> 16) == 0x8086)
|
||||
#define AGP_BRIDGE_INTEL(x) ((((x) >> 16) == 0x8086) && ((x) != PCI_BRIDGE_INTEL_ICH2))
|
||||
#define AGP_BRIDGE_VIA(x) (((x) >> 16) == 0x1106)
|
||||
#define AGP_BRIDGE(x) ((x) >= AGP_BRIDGE_ALI_M5243)
|
||||
#define AGP_BRIDGE(x) (((x) >= AGP_BRIDGE_ALI_M5243) && ((x) != PCI_BRIDGE_INTEL_ICH2))
|
||||
|
||||
|
||||
typedef struct
|
||||
@@ -116,6 +118,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 (dev->local == AGP_BRIDGE_INTEL_815EP)
|
||||
val &= 0x17;
|
||||
else if (dev->local == PCI_BRIDGE_INTEL_ICH2)
|
||||
val &= 0x47;
|
||||
} else if (dev->local == AGP_BRIDGE_ALI_M5243)
|
||||
val |= 0x02;
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5247)
|
||||
@@ -129,13 +135,17 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
val &= 0x01;
|
||||
else if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0x01;
|
||||
else if (PCI_BRIDGE_INTEL_ICH2)
|
||||
val &= 0x01;
|
||||
else
|
||||
val &= 0x03;
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
if (dev->local == AGP_BRIDGE_INTEL_440LX)
|
||||
if ((dev->local == AGP_BRIDGE_INTEL_440LX) || (dev->local == AGP_BRIDGE_INTEL_815EP))
|
||||
dev->regs[addr] &= ~(val & 0x40);
|
||||
else if (dev->local == PCI_BRIDGE_INTEL_ICH2)
|
||||
dev->regs[addr] &= ~(val & 0xf9);
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5243)
|
||||
dev->regs[addr] &= ~(val & 0xf8);
|
||||
else if (dev->local == AGP_BRIDGE_ALI_M5247)
|
||||
@@ -165,15 +175,22 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
|
||||
case 0x1f:
|
||||
if (AGP_BRIDGE_INTEL(dev->local)) {
|
||||
if (dev->local == AGP_BRIDGE_INTEL_440LX)
|
||||
if ((dev->local == AGP_BRIDGE_INTEL_440LX) || (dev->local == PCI_BRIDGE_INTEL_ICH2))
|
||||
dev->regs[addr] &= ~(val & 0xf1);
|
||||
else if ((dev->local == AGP_BRIDGE_INTEL_440BX) ||
|
||||
(dev->local == AGP_BRIDGE_INTEL_440GX))
|
||||
dev->regs[addr] &= ~(val & 0xf0);
|
||||
else if (dev->local == AGP_BRIDGE_INTEL_815EP)
|
||||
dev->regs[addr] &= ~(val & 0xb2);
|
||||
} else if (AGP_BRIDGE_ALI(dev->local))
|
||||
dev->regs[addr] &= ~(val & 0xf0);
|
||||
return;
|
||||
|
||||
case 0x1b:
|
||||
if ((dev->local == AGP_BRIDGE_INTEL_815EP) || (dev->local == PCI_BRIDGE_INTEL_ICH2))
|
||||
val &= 0xf8;
|
||||
break;
|
||||
|
||||
case 0x1c: case 0x1d: case 0x20: case 0x22:
|
||||
case 0x24: case 0x26:
|
||||
val &= 0xf0;
|
||||
@@ -200,6 +217,8 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
}
|
||||
else if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0xef;
|
||||
else if (dev->local == PCI_BRIDGE_INTEL_ICH2)
|
||||
val &= 0x2f;
|
||||
break;
|
||||
|
||||
case 0x3f:
|
||||
@@ -219,6 +238,8 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
case 0x40:
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x32;
|
||||
else if ((dev->local == AGP_BRIDGE_INTEL_815EP) || (dev->local == PCI_BRIDGE_INTEL_ICH2))
|
||||
val &= 0x01;
|
||||
break;
|
||||
|
||||
case 0x41:
|
||||
@@ -238,6 +259,16 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
val &= 0x03;
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
if (dev->local == PCI_BRIDGE_INTEL_ICH2)
|
||||
val &= 0x06;
|
||||
break;
|
||||
|
||||
case 0x51:
|
||||
if (dev->local == PCI_BRIDGE_INTEL_ICH2)
|
||||
val &= 0x03;
|
||||
break;
|
||||
|
||||
case 0x64:
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x7e;
|
||||
@@ -248,6 +279,11 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
val &= 0x3f;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
if (dev->local == PCI_BRIDGE_INTEL_ICH2)
|
||||
val &= 0xf8;
|
||||
break;
|
||||
|
||||
case 0x86:
|
||||
if (AGP_BRIDGE_ALI(dev->local))
|
||||
val &= 0x3f;
|
||||
@@ -278,6 +314,16 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
return;
|
||||
break;
|
||||
|
||||
case 0x90:
|
||||
if (dev->local == PCI_BRIDGE_INTEL_ICH2)
|
||||
val &= 0x06;
|
||||
break;
|
||||
|
||||
case 0x91:
|
||||
if (dev->local == PCI_BRIDGE_INTEL_ICH2)
|
||||
dev->regs[addr] = ~(val & 0x06);
|
||||
break;
|
||||
|
||||
case 0xe0: case 0xe1:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (!(dev->ctl & 0x20))
|
||||
@@ -379,6 +425,11 @@ pci_bridge_reset(void *priv)
|
||||
dev->regs[0x07] = 0x02;
|
||||
break;
|
||||
|
||||
case PCI_BRIDGE_INTEL_ICH2:
|
||||
dev->regs[0x04] = 0x01;
|
||||
dev->regs[0x06] = 0x80;
|
||||
break;
|
||||
|
||||
case AGP_BRIDGE_ALI_M5243:
|
||||
dev->regs[0x04] = 0x06;
|
||||
dev->regs[0x07] = 0x04;
|
||||
@@ -411,6 +462,11 @@ pci_bridge_reset(void *priv)
|
||||
dev->regs[0x07] = dev->regs[0x08] = 0x02;
|
||||
break;
|
||||
|
||||
case AGP_BRIDGE_INTEL_815EP:
|
||||
dev->regs[0x06] = 0x20;
|
||||
dev->regs[0x08] = 0x02;
|
||||
break;
|
||||
|
||||
case AGP_BRIDGE_VIA_597:
|
||||
case AGP_BRIDGE_VIA_598:
|
||||
case AGP_BRIDGE_VIA_691:
|
||||
@@ -453,6 +509,9 @@ pci_bridge_reset(void *priv)
|
||||
dev->regs[0x43] = 0x02;
|
||||
dev->regs[0xdc] = dev->regs[0xde] = 0x01;
|
||||
}
|
||||
|
||||
if (dev->local == PCI_BRIDGE_INTEL_ICH2)
|
||||
dev->regs[0x70] = 0x20;
|
||||
}
|
||||
|
||||
|
||||
@@ -471,27 +530,32 @@ pci_bridge_init(const device_t *info)
|
||||
pci_bridge_reset(dev);
|
||||
|
||||
dev->slot = pci_add_card(AGP_BRIDGE(dev->local) ? PCI_ADD_AGPBRIDGE : PCI_ADD_BRIDGE, pci_bridge_read, pci_bridge_write, dev);
|
||||
interrupt_count = sizeof(interrupts);
|
||||
interrupt_mask = interrupt_count - 1;
|
||||
if (dev->slot < 32) {
|
||||
for (i = 0; i < interrupt_count; i++)
|
||||
interrupts[i] = pci_get_int(dev->slot, PCI_INTA + i);
|
||||
}
|
||||
pci_bridge_log("PCI Bridge %d: upstream bus %02X slot %02X interrupts %02X %02X %02X %02X\n", dev->bus_index, (dev->slot >> 5) & 0xff, dev->slot & 31, interrupts[0], interrupts[1], interrupts[2], interrupts[3]);
|
||||
|
||||
if (info->local == PCI_BRIDGE_DEC_21150)
|
||||
slot_count = 9; /* 9 bus masters */
|
||||
else
|
||||
slot_count = 1; /* AGP bridges always have 1 slot */
|
||||
if ((info->local != PCI_BRIDGE_INTEL_ICH2) && (info->local != AGP_BRIDGE_INTEL_815EP)) /* Let the machine configuration slot handle the absurd interrupt tables */
|
||||
{
|
||||
interrupt_count = sizeof(interrupts);
|
||||
interrupt_mask = interrupt_count - 1;
|
||||
if (dev->slot < 32) {
|
||||
for (i = 0; i < interrupt_count; i++)
|
||||
interrupts[i] = pci_get_int(dev->slot, PCI_INTA + i);
|
||||
}
|
||||
|
||||
for (i = 0; i < slot_count; i++) {
|
||||
/* Interrupts for bridge slots are assigned in round-robin: ABCD, BCDA, CDAB and so on. */
|
||||
pci_bridge_log("PCI Bridge %d: downstream slot %02X interrupts %02X %02X %02X %02X\n", dev->bus_index, i, interrupts[i & interrupt_mask], interrupts[(i + 1) & interrupt_mask], interrupts[(i + 2) & interrupt_mask], interrupts[(i + 3) & interrupt_mask]);
|
||||
pci_register_bus_slot(dev->bus_index, i, AGP_BRIDGE(dev->local) ? PCI_CARD_AGP : PCI_CARD_NORMAL,
|
||||
interrupts[i & interrupt_mask],
|
||||
interrupts[(i + 1) & interrupt_mask],
|
||||
interrupts[(i + 2) & interrupt_mask],
|
||||
interrupts[(i + 3) & interrupt_mask]);
|
||||
pci_bridge_log("PCI Bridge %d: upstream bus %02X slot %02X interrupts %02X %02X %02X %02X\n", dev->bus_index, (dev->slot >> 5) & 0xff, dev->slot & 31, interrupts[0], interrupts[1], interrupts[2], interrupts[3]);
|
||||
|
||||
if (info->local == PCI_BRIDGE_DEC_21150)
|
||||
slot_count = 9; /* 9 bus masters */
|
||||
else
|
||||
slot_count = 1; /* AGP bridges always have 1 slot */
|
||||
|
||||
for (i = 0; i < slot_count; i++) {
|
||||
/* Interrupts for bridge slots are assigned in round-robin: ABCD, BCDA, CDAB and so on. */
|
||||
pci_bridge_log("PCI Bridge %d: downstream slot %02X interrupts %02X %02X %02X %02X\n", dev->bus_index, i, interrupts[i & interrupt_mask], interrupts[(i + 1) & interrupt_mask], interrupts[(i + 2) & interrupt_mask], interrupts[(i + 3) & interrupt_mask]);
|
||||
pci_register_bus_slot(dev->bus_index, i, AGP_BRIDGE(dev->local) ? PCI_CARD_AGP : PCI_CARD_NORMAL,
|
||||
interrupts[i & interrupt_mask],
|
||||
interrupts[(i + 1) & interrupt_mask],
|
||||
interrupts[(i + 2) & interrupt_mask],
|
||||
interrupts[(i + 3) & interrupt_mask]);
|
||||
}
|
||||
}
|
||||
|
||||
return dev;
|
||||
@@ -584,6 +648,34 @@ const device_t i440gx_agp_device = {
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t intel_ich2_hub_device = {
|
||||
.name = "Intel ICH2 Hub Bridge",
|
||||
.internal_name = "intel_ich2_hub",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = PCI_BRIDGE_INTEL_ICH2,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t intel_815ep_agp_device = {
|
||||
.name = "Intel 815EP MCH AGP Bridge",
|
||||
.internal_name = "intel_815ep_agp",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = AGP_BRIDGE_INTEL_815EP,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t via_vp3_agp_device = {
|
||||
.name = "VIA Apollo VP3 AGP Bridge",
|
||||
.internal_name = "via_vp3_agp",
|
||||
|
||||
@@ -24,11 +24,14 @@
|
||||
#include <86box/86box.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/pic.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/i2c.h>
|
||||
#include <86box/apm.h>
|
||||
#include <86box/nvr.h>
|
||||
#include <86box/acpi.h>
|
||||
#include <86box/smbus.h>
|
||||
|
||||
|
||||
#ifdef ENABLE_SMBUS_PIIX4_LOG
|
||||
int smbus_piix4_do_log = ENABLE_SMBUS_PIIX4_LOG;
|
||||
|
||||
@@ -48,6 +51,34 @@ smbus_piix4_log(const char *fmt, ...)
|
||||
#define smbus_piix4_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
void
|
||||
smbus_piix4_get_acpi(smbus_piix4_t *dev, acpi_t *acpi)
|
||||
{
|
||||
dev->acpi = acpi;
|
||||
}
|
||||
|
||||
void
|
||||
smbus_piix4_get_irq(uint8_t irq, smbus_piix4_t *dev)
|
||||
{
|
||||
dev->irq = irq;
|
||||
}
|
||||
|
||||
void
|
||||
smbus_piix4_smi_en(uint8_t smi_en, smbus_piix4_t *dev)
|
||||
{
|
||||
dev->smi_en = smi_en;
|
||||
}
|
||||
|
||||
static void
|
||||
smbus_piix4_raise_smi(smbus_piix4_t *dev)
|
||||
{
|
||||
if (dev->smi_en) { /* Raise SMI when needed if it's enabled by the Chipset */
|
||||
dev->acpi->regs.smi_sts |= 0x00010000;
|
||||
acpi_raise_smi(dev->acpi, 1);
|
||||
}
|
||||
else
|
||||
picint(1 << dev->irq);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
smbus_piix4_read(uint16_t addr, void *priv)
|
||||
@@ -99,7 +130,7 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
smbus_piix4_t *dev = (smbus_piix4_t *) priv;
|
||||
uint8_t smbus_addr, cmd, read, block_len, prev_stat;
|
||||
uint16_t timer_bytes = 0, i;
|
||||
uint16_t timer_bytes = 0, i = 0;
|
||||
|
||||
smbus_piix4_log("SMBus PIIX4: write(%02X, %02X)\n", addr, val);
|
||||
|
||||
@@ -107,7 +138,7 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
|
||||
dev->next_stat = 0x00;
|
||||
switch (addr - dev->io_base) {
|
||||
case 0x00:
|
||||
for (smbus_addr = 0x02; smbus_addr <= 0x10; smbus_addr <<= 1) { /* handle clearable bits */
|
||||
for (smbus_addr = 0x02; smbus_addr <= ((dev->local == SMBUS_INTEL_ICH2) ? 0x40 : 0x10); smbus_addr <<= 1) { /* handle clearable bits */
|
||||
if (val & smbus_addr)
|
||||
dev->stat &= ~smbus_addr;
|
||||
}
|
||||
@@ -213,22 +244,52 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
|
||||
/* fall-through */
|
||||
|
||||
case 0xd: /* I2C block R/W */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
timer_bytes++;
|
||||
if (dev->local == SMBUS_INTEL_ICH2) {
|
||||
if (!dev->byte_rw) {
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
if(read)
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr); // For byte reads, the count is recieved and stored at the DATA0 register
|
||||
else
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
|
||||
if (read) {
|
||||
/* block read [data0] (I2C) or [first byte] (SMBus) bytes */
|
||||
if (cmd == 0x5)
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
for (i = 0; i < dev->data0; i++)
|
||||
dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK] = i2c_read(i2c_smbus, smbus_addr);
|
||||
} else {
|
||||
if (cmd == 0x5) /* send length [data0] as first byte on SMBus */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
/* block write [data0] bytes */
|
||||
for (i = 0; i < dev->data0; i++) {
|
||||
if (!i2c_write(i2c_smbus, smbus_addr, dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK]))
|
||||
break;
|
||||
dev->byte_rw = 1;
|
||||
}
|
||||
|
||||
if (read) {
|
||||
dev->block_data_byte = i2c_read(i2c_smbus, smbus_addr);
|
||||
dev->stat |= 0x80;
|
||||
smbus_piix4_raise_smi(dev);
|
||||
if(dev->ctl & 0x20) { /* Finish the Transfer */
|
||||
dev->byte_rw = 0;
|
||||
dev->stat |= 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
|
||||
if (((dev->byte_rw >> 4) & 0xff) < dev->data0) {
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->block_data_byte);
|
||||
dev->stat |= 0x80;
|
||||
dev->byte_rw += 0x10000;
|
||||
}
|
||||
else dev->byte_rw = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (read) {
|
||||
timer_bytes++;
|
||||
/* block read [data0] (I2C) or [first byte] (SMBus) bytes */
|
||||
if (cmd == 0x5)
|
||||
dev->data0 = i2c_read(i2c_smbus, smbus_addr);
|
||||
for (i = 0; i < dev->data0; i++)
|
||||
dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK] = i2c_read(i2c_smbus, smbus_addr);
|
||||
} else {
|
||||
if (cmd == 0x5) /* send length [data0] as first byte on SMBus */
|
||||
i2c_write(i2c_smbus, smbus_addr, dev->data0);
|
||||
/* block write [data0] bytes */
|
||||
for (i = 0; i < dev->data0; i++) {
|
||||
if (!i2c_write(i2c_smbus, smbus_addr, dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK]))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
timer_bytes += i;
|
||||
@@ -283,7 +344,12 @@ unknown_protocol:
|
||||
}
|
||||
|
||||
/* Finish transfer. */
|
||||
i2c_stop(i2c_smbus, smbus_addr);
|
||||
if (dev->local == SMBUS_INTEL_ICH2) {
|
||||
/* ICH2 SMBus specific. Transfer on Byte command doesn't stop till their specific points. */
|
||||
if (!dev->byte_rw)
|
||||
i2c_stop(i2c_smbus, smbus_addr);
|
||||
} else
|
||||
i2c_stop(i2c_smbus, smbus_addr);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -304,9 +370,13 @@ unknown_protocol:
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
dev->data[dev->index++] = val;
|
||||
if (dev->index >= SMBUS_PIIX4_BLOCK_DATA_SIZE)
|
||||
dev->index = 0;
|
||||
if (dev->local == SMBUS_INTEL_ICH2)
|
||||
dev->block_data_byte = val;
|
||||
else {
|
||||
dev->data[dev->index++] = val;
|
||||
if (dev->index >= SMBUS_PIIX4_BLOCK_DATA_SIZE)
|
||||
dev->index = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -362,7 +432,20 @@ smbus_piix4_init(const device_t *info)
|
||||
dev->local = info->local;
|
||||
/* We save the I2C bus handle on dev but use i2c_smbus for all operations because
|
||||
dev and therefore dev->i2c will be invalidated if a device triggers a hard reset. */
|
||||
i2c_smbus = dev->i2c = i2c_addbus((dev->local == SMBUS_VIA) ? "smbus_vt82c686b" : "smbus_piix4");
|
||||
switch(dev->local)
|
||||
{
|
||||
case SMBUS_PIIX4:
|
||||
i2c_smbus = dev->i2c = i2c_addbus("smbus_piix4");
|
||||
break;
|
||||
|
||||
case SMBUS_INTEL_ICH2:
|
||||
i2c_smbus = dev->i2c = i2c_addbus("smbus_intel_ich2");
|
||||
break;
|
||||
|
||||
case SMBUS_VIA:
|
||||
i2c_smbus = dev->i2c = i2c_addbus("smbus_vt82c686b");
|
||||
break;
|
||||
}
|
||||
|
||||
timer_add(&dev->response_timer, smbus_piix4_response, dev, 0);
|
||||
|
||||
@@ -398,6 +481,20 @@ const device_t piix4_smbus_device = {
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t intel_ich2_smbus_device = {
|
||||
.name = "Intel ICH2 SMBus Host Controller",
|
||||
.internal_name = "intel_ich2_smbus",
|
||||
.flags = DEVICE_AT,
|
||||
.local = SMBUS_INTEL_ICH2,
|
||||
.init = smbus_piix4_init,
|
||||
.close = smbus_piix4_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t via_smbus_device = {
|
||||
.name = "VIA VT82C686B SMBus Host Controller",
|
||||
.internal_name = "via_smbus",
|
||||
|
||||
198
src/device/tco.c
Normal file
198
src/device/tco.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Intel TCO Handler.
|
||||
*
|
||||
* Note: There's a TCO Timer too but for now it's of no use thus
|
||||
* not implemented
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2022 Tiseno100.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/nmi.h>
|
||||
#include <86box/pic.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/tco.h>
|
||||
|
||||
|
||||
#ifdef ENABLE_TCO_LOG
|
||||
int tco_do_log = ENABLE_TCO_LOG;
|
||||
|
||||
|
||||
static void
|
||||
tco_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (tco_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define tco_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
tco_timer_handler(void *priv)
|
||||
{
|
||||
/* TODO: Implement the TCO timer. */
|
||||
// tco_t *dev = (tco_t *) priv;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tco_irq_update(tco_t *dev, uint16_t new_irq)
|
||||
{
|
||||
tco_log("TCO: Update IRQ to %d\n", new_irq);
|
||||
dev->tco_irq = new_irq;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tco_write(uint16_t addr, uint8_t val, tco_t *dev)
|
||||
{
|
||||
addr -= 0x60;
|
||||
tco_log("TCO: Write 0x%02x to Register 0x%02x\n", val, addr);
|
||||
|
||||
switch(addr) {
|
||||
case 0x00:
|
||||
dev->regs[addr] = val;
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
dev->regs[addr] = val & 0x3f;
|
||||
break;
|
||||
|
||||
case 0x02: /* TCO Data in */
|
||||
dev->regs[addr] = val;
|
||||
dev->regs[0x04] |= 2;
|
||||
smi_line = 1;
|
||||
break;
|
||||
|
||||
case 0x03: /* TCO Data out */
|
||||
dev->regs[addr] = val;
|
||||
dev->regs[0x04] |= 4;
|
||||
picint(dev->tco_irq);
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
dev->regs[addr] &= 0x8f;
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
dev->regs[addr] &= 0x1f;
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
dev->regs[addr] &= 0x07;
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
if (val & 1) {
|
||||
if (!nmi) /* If we're already on NMI */
|
||||
nmi = 1;
|
||||
|
||||
dev->regs[addr] = (dev->regs[addr] & 1) | val;
|
||||
dev->regs[addr] &= val;
|
||||
} else
|
||||
dev->regs[addr] = 0x0f;
|
||||
break;
|
||||
|
||||
case 0x0a:
|
||||
dev->regs[addr] = val & 0x06; // Intrusion Interrupt or SMI. We never get intruded so we never control it.
|
||||
break;
|
||||
|
||||
case 0x0c ... 0x0d:
|
||||
dev->regs[addr] = val;
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
dev->regs[addr] = val & 0x03;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
tco_read(uint16_t addr, tco_t *dev)
|
||||
{
|
||||
addr -= 0x60;
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
if (addr <= 0x10) {
|
||||
tco_log("TCO: Read 0x%02x from Register 0x%02x\n", dev->regs[addr], addr);
|
||||
ret = dev->regs[addr];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
tco_reset(void *priv)
|
||||
{
|
||||
tco_t *dev = (tco_t *) priv;
|
||||
memset(dev->regs, 0, sizeof(dev->regs));
|
||||
|
||||
dev->tco_irq = 9;
|
||||
|
||||
dev->regs[0x01] = 0x04;
|
||||
dev->regs[0x10] = 0x03;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
tco_close(void *priv)
|
||||
{
|
||||
tco_t *dev = (tco_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tco_init(const device_t *info)
|
||||
{
|
||||
tco_t *dev = (tco_t *) malloc(sizeof(tco_t));
|
||||
memset(dev, 0, sizeof(tco_t));
|
||||
|
||||
tco_reset(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
const device_t tco_device = {
|
||||
.name = "Intel TCO",
|
||||
.internal_name = "tco",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = tco_init,
|
||||
.close = tco_close,
|
||||
.reset = tco_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
22
src/dma.c
22
src/dma.c
@@ -1171,6 +1171,28 @@ dma_alias_set_piix(void)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dma_lpc_init(void) /* Addresses LPC DMA uses */
|
||||
{
|
||||
io_sethandler(0x1000, 16,
|
||||
dma_read,NULL,NULL, dma_write,NULL,NULL, NULL);
|
||||
io_sethandler(0x1080, 8,
|
||||
dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL);
|
||||
io_sethandler(0x10C0, 32,
|
||||
dma16_read,NULL,NULL, dma16_write,NULL,NULL, NULL);
|
||||
io_sethandler(0x1088, 8,
|
||||
dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL);
|
||||
io_sethandler(0x1090, 1,
|
||||
dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL);
|
||||
io_sethandler(0x1094, 3,
|
||||
dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL);
|
||||
io_sethandler(0x1098, 1,
|
||||
dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL);
|
||||
io_sethandler(0x109C, 3,
|
||||
dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dma_alias_remove(void)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <86box/tco.h> /* TCO Header. Needed for Intel ICH chipsets. */
|
||||
|
||||
#define ACPI_TIMER_FREQ 3579545
|
||||
#define PM_FREQ ACPI_TIMER_FREQ
|
||||
|
||||
@@ -51,6 +53,7 @@ extern "C" {
|
||||
|
||||
#define VEN_ALI 0x010b9
|
||||
#define VEN_INTEL 0x08086
|
||||
#define VEN_INTEL_ICH2 0x18086
|
||||
#define VEN_SIS 0x01039
|
||||
#define VEN_SMC 0x01055
|
||||
#define VEN_VIA 0x01106
|
||||
@@ -59,18 +62,19 @@ extern "C" {
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t acpitst, auxen, auxsts, plvl2, plvl3,
|
||||
uint8_t acpitst, auxen, auxsts, bus_cyc_track, plvl2, plvl3,
|
||||
smicmd, gpio_dir,
|
||||
gpio_val, muxcntrl, ali_soft_smi,
|
||||
timer32, smireg,
|
||||
gpireg[3], gporeg[4],
|
||||
gpireg[3], gporeg[4], tco[17],
|
||||
extiotrapsts, extiotrapen;
|
||||
uint16_t pmsts, pmen,
|
||||
pmcntrl, gpsts, gpsts1,
|
||||
pmcntrl, bus_addr_track, devact_sts,
|
||||
devtrap_en, gpsts, gpsts1,
|
||||
gpen, gpen1, gpscien,
|
||||
gpcntrl, gplvl, gpmux,
|
||||
gpsel, gpsmien, pscntrl,
|
||||
gpscists;
|
||||
gpscists, mon_smi;
|
||||
int smi_lock, smi_active;
|
||||
uint32_t pcntrl, p2cntrl, glbsts,
|
||||
devsts, glben,
|
||||
@@ -78,7 +82,7 @@ typedef struct
|
||||
padsts, paden,
|
||||
gptren, gptimer,
|
||||
gpo_val, gpi_val,
|
||||
extsmi_val, pad0;
|
||||
extsmi_val, smi_en, smi_sts, pad0;
|
||||
} acpi_regs_t;
|
||||
|
||||
|
||||
@@ -96,6 +100,7 @@ typedef struct
|
||||
pc_timer_t timer, resume_timer;
|
||||
nvr_t *nvr;
|
||||
apm_t *apm;
|
||||
tco_t *tco;
|
||||
void *i2c,
|
||||
(*trap_update)(void *priv), *trap_priv;
|
||||
} acpi_t;
|
||||
@@ -106,6 +111,7 @@ extern int acpi_rtc_status;
|
||||
|
||||
extern const device_t acpi_ali_device;
|
||||
extern const device_t acpi_intel_device;
|
||||
extern const device_t acpi_intel_ich2_device;
|
||||
extern const device_t acpi_smc_device;
|
||||
extern const device_t acpi_via_device;
|
||||
extern const device_t acpi_via_596b_device;
|
||||
@@ -125,6 +131,7 @@ extern void acpi_set_irq_line(acpi_t *dev, int irq_line);
|
||||
extern void acpi_set_mirq_is_level(acpi_t *dev, int mirq_is_level);
|
||||
extern void acpi_set_gpireg2_default(acpi_t *dev, uint8_t gpireg2_default);
|
||||
extern void acpi_set_nvr(acpi_t *dev, nvr_t *nvr);
|
||||
extern void acpi_set_tco(acpi_t *dev, tco_t *tco);
|
||||
extern void acpi_set_trap_update(acpi_t *dev, void (*update)(void *priv), void *priv);
|
||||
extern uint8_t acpi_ali_soft_smi_status_read(acpi_t *dev);
|
||||
extern void acpi_ali_soft_smi_status_write(acpi_t *dev, uint8_t soft_smi);
|
||||
|
||||
@@ -99,6 +99,9 @@ extern const device_t slc90e66_device;
|
||||
|
||||
extern const device_t ioapic_device;
|
||||
|
||||
extern const device_t intel_815ep_device;
|
||||
extern const device_t intel_ich2_device;
|
||||
|
||||
/* OPTi */
|
||||
extern const device_t opti283_device;
|
||||
extern const device_t opti291_device;
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#define CONFIG_HEX20 8
|
||||
#define CONFIG_MAC 9
|
||||
#define CONFIG_MIDI_IN 10
|
||||
#define CONFIG_BIOS 11
|
||||
|
||||
|
||||
enum {
|
||||
@@ -77,6 +78,14 @@ typedef struct {
|
||||
int value;
|
||||
} device_config_selection_t;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *internal_name;
|
||||
int bios_type;
|
||||
int files_no;
|
||||
const char **files;
|
||||
} device_config_bios_t;
|
||||
|
||||
typedef struct {
|
||||
int16_t min;
|
||||
int16_t max;
|
||||
@@ -92,6 +101,7 @@ typedef struct {
|
||||
const char *file_filter;
|
||||
const device_config_spinner_t spinner;
|
||||
const device_config_selection_t selection[16];
|
||||
const device_config_bios_t *bios;
|
||||
} device_config_t;
|
||||
|
||||
typedef struct _device_ {
|
||||
@@ -161,6 +171,7 @@ extern void device_set_config_hex16(const char *s, int val);
|
||||
extern void device_set_config_hex20(const char *s, int val);
|
||||
extern void device_set_config_mac(const char *s, int val);
|
||||
extern const char *device_get_config_string(const char *name);
|
||||
#define device_get_config_bios device_get_config_string
|
||||
|
||||
extern char * device_get_internal_name(const device_t *d);
|
||||
|
||||
|
||||
@@ -93,6 +93,8 @@ extern void dma_alias_set_piix(void);
|
||||
extern void dma_alias_remove(void);
|
||||
extern void dma_alias_remove_piix(void);
|
||||
|
||||
extern void dma_lpc_init(void);
|
||||
|
||||
extern void dma_bm_read(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize, int TransferSize);
|
||||
extern void dma_bm_write(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize, int TransferSize);
|
||||
|
||||
|
||||
@@ -30,4 +30,7 @@ extern const device_t sst_flash_39sf010_device;
|
||||
extern const device_t sst_flash_39sf020_device;
|
||||
extern const device_t sst_flash_39sf040_device;
|
||||
|
||||
extern const device_t sst_flash_49lf002_device;
|
||||
extern const device_t sst_flash_49lf004_device;
|
||||
|
||||
#endif /*EMU_FLASH_H*/
|
||||
|
||||
@@ -55,6 +55,8 @@ extern uint8_t lm78_as99127f_write(void *priv, uint8_t reg, uint8_t val);
|
||||
/* hwm_vt82c686.c */
|
||||
extern void vt82c686_hwm_write(uint8_t addr, uint8_t val, void *priv);
|
||||
|
||||
/* sio_w83627hf.c */
|
||||
extern void w83627hf_stabilizer(int vcoreb, int fan1, int fan2, int fan3);
|
||||
|
||||
/* Refer to specific hardware monitor implementations for the meaning of hwm_values. */
|
||||
extern hwm_values_t hwm_values;
|
||||
|
||||
30
src/include/86box/intel_ich2_gpio.h
Normal file
30
src/include/86box/intel_ich2_gpio.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Intel ICH2 GPIO Header
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2022 Tiseno100.
|
||||
*/
|
||||
|
||||
#ifndef EMU_INTEL_ICH2_GPIO_H
|
||||
# define EMU_INTEL_ICH2_GPIO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct intel_ich2_gpio_t
|
||||
{
|
||||
uint16_t gpio_addr;
|
||||
uint8_t gpio_regs[48];
|
||||
} intel_ich2_gpio_t;
|
||||
|
||||
void intel_ich2_gpio_base(int enable, uint16_t addr, intel_ich2_gpio_t *dev);
|
||||
|
||||
extern const device_t intel_ich2_gpio_device;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*EMU_INTEL_ICH2_GPIO_H*/
|
||||
31
src/include/86box/intel_ich2_trap.h
Normal file
31
src/include/86box/intel_ich2_trap.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Intel ICH2 Trap Header
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2022 Tiseno100.
|
||||
*/
|
||||
|
||||
#ifndef EMU_INTEL_ICH2_TRAP_H
|
||||
# define EMU_INTEL_ICH2_TRAP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct intel_ich2_trap_t
|
||||
{
|
||||
acpi_t *acpi;
|
||||
void *trap;
|
||||
} intel_ich2_trap_t;
|
||||
|
||||
extern void intel_ich2_trap_set_acpi(intel_ich2_trap_t *trap, acpi_t *acpi);
|
||||
extern void intel_ich2_device_trap_setup(int enable, uint8_t acpi_reg, uint8_t acpi_reg_val, uint16_t addr, uint16_t size, int is_hdd, intel_ich2_trap_t *trap);
|
||||
|
||||
extern const device_t intel_ich2_trap_device;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*EMU_INTEL_ICH2_TRAP_H*/
|
||||
@@ -161,6 +161,7 @@ enum {
|
||||
MACHINE_TYPE_SLOT1_370,
|
||||
MACHINE_TYPE_SLOT2,
|
||||
MACHINE_TYPE_SOCKET370,
|
||||
MACHINE_TYPE_ICH2,
|
||||
MACHINE_TYPE_MISC,
|
||||
MACHINE_TYPE_MAX
|
||||
};
|
||||
@@ -206,6 +207,7 @@ enum {
|
||||
MACHINE_CHIPSET_INTEL_440BX,
|
||||
MACHINE_CHIPSET_INTEL_440ZX,
|
||||
MACHINE_CHIPSET_INTEL_440GX,
|
||||
MACHINE_CHIPSET_INTEL_I815EP,
|
||||
MACHINE_CHIPSET_OPTI_283,
|
||||
MACHINE_CHIPSET_OPTI_291,
|
||||
MACHINE_CHIPSET_OPTI_493,
|
||||
@@ -332,6 +334,11 @@ extern int machine_get_ram_granularity(int m);
|
||||
extern int machine_get_type(int m);
|
||||
extern void machine_close(void);
|
||||
|
||||
extern uint8_t machine_get_p1(void);
|
||||
extern void machine_load_p1(int m);
|
||||
extern uint32_t machine_get_gpi(void);
|
||||
extern void machine_load_gpi(int m);
|
||||
extern void machine_set_gpi(uint32_t gpi);
|
||||
|
||||
/* Initialization functions for boards and systems. */
|
||||
extern void machine_common_init(const machine_t *);
|
||||
@@ -696,6 +703,11 @@ extern int machine_at_p6bap_init(const machine_t *);
|
||||
/* m_at_misc.c */
|
||||
extern int machine_at_vpc2007_init(const machine_t *);
|
||||
|
||||
/* m_at_ich2.c */
|
||||
extern int machine_at_m6tsl_init(const machine_t *);
|
||||
extern int machine_at_m6tss_init(const machine_t *);
|
||||
extern int machine_at_s2080_init(const machine_t *);
|
||||
|
||||
/* m_at_t3100e.c */
|
||||
extern int machine_at_t3100e_init(const machine_t *);
|
||||
|
||||
|
||||
44
src/include/86box/nsc366.h
Normal file
44
src/include/86box/nsc366.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* National Semiconductor PC87366(NSC366) Header
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2022 Tiseno100.
|
||||
*/
|
||||
|
||||
#ifndef EMU_NSC_366_H
|
||||
# define EMU_NSC_366_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
hwm_values_t *values;
|
||||
|
||||
uint8_t fscm_enable;
|
||||
uint16_t fscm_addr;
|
||||
uint8_t fscm_config[15];
|
||||
|
||||
uint16_t vlm_addr;
|
||||
uint8_t vlm_config_global[10];
|
||||
uint8_t vlm_config_bank[13][5];
|
||||
|
||||
uint16_t tms_addr;
|
||||
uint8_t tms_config_global[10];
|
||||
uint8_t tms_config_bank[4][5];
|
||||
} nsc366_hwm_t;
|
||||
|
||||
extern void nsc366_update_fscm_io(int enable, uint16_t addr, nsc366_hwm_t *dev);
|
||||
extern void nsc366_update_vlm_io(int enable, uint16_t addr, nsc366_hwm_t *dev);
|
||||
extern void nsc366_update_tms_io(int enable, uint16_t addr, nsc366_hwm_t *dev);
|
||||
|
||||
/* The Hardware Monitor */
|
||||
extern const device_t nsc366_hwm_device;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*EMU_NSC_366_H*/
|
||||
@@ -138,11 +138,14 @@ extern void pci_pic_reset(void);
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t dec21150_device;
|
||||
|
||||
extern const device_t intel_ich2_hub_device;
|
||||
|
||||
extern const device_t ali5243_agp_device;
|
||||
extern const device_t ali5247_agp_device;
|
||||
extern const device_t i440lx_agp_device;
|
||||
extern const device_t i440bx_agp_device;
|
||||
extern const device_t i440gx_agp_device;
|
||||
extern const device_t intel_815ep_agp_device;
|
||||
extern const device_t via_vp3_agp_device;
|
||||
extern const device_t via_mvp3_agp_device;
|
||||
extern const device_t via_apro_agp_device;
|
||||
|
||||
@@ -70,7 +70,8 @@ extern uint64_t PITCONST, ISACONST,
|
||||
HERCCONST,
|
||||
VGACONST1,
|
||||
VGACONST2,
|
||||
RTCCONST;
|
||||
RTCCONST,
|
||||
TCOCONST;
|
||||
|
||||
extern int refresh_at_enable;
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ extern const device_t i82091aa_device;
|
||||
extern const device_t i82091aa_398_device;
|
||||
extern const device_t i82091aa_ide_pri_device;
|
||||
extern const device_t i82091aa_ide_device;
|
||||
extern const device_t nsc366_device;
|
||||
extern const device_t nsc366_4f_device;
|
||||
extern const device_t pc87306_device;
|
||||
extern const device_t pc87307_device;
|
||||
extern const device_t pc87307_15c_device;
|
||||
@@ -71,6 +73,8 @@ extern const device_t sio_detect_device;
|
||||
#endif
|
||||
extern const device_t um8669f_device;
|
||||
extern const device_t via_vt82c686_sio_device;
|
||||
extern const device_t w83627hf_device;
|
||||
extern const device_t w83627hf_no_hwm_device;
|
||||
extern const device_t w83787f_device;
|
||||
extern const device_t w83787f_ide_device;
|
||||
extern const device_t w83787f_ide_en_device;
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#ifndef EMU_SMBUS_PIIX4_H
|
||||
# define EMU_SMBUS_PIIX4_H
|
||||
|
||||
#include <86box/apm.h>
|
||||
#include <86box/nvr.h>
|
||||
#include <86box/acpi.h>
|
||||
|
||||
#define SMBUS_PIIX4_BLOCK_DATA_SIZE 32
|
||||
#define SMBUS_PIIX4_BLOCK_DATA_MASK (SMBUS_PIIX4_BLOCK_DATA_SIZE - 1)
|
||||
@@ -28,17 +31,20 @@
|
||||
|
||||
enum {
|
||||
SMBUS_PIIX4 = 0,
|
||||
SMBUS_INTEL_ICH2,
|
||||
SMBUS_VIA
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t local;
|
||||
uint16_t io_base;
|
||||
uint16_t io_base, byte_rw;
|
||||
int clock;
|
||||
double bit_period;
|
||||
uint8_t stat, next_stat, ctl, cmd, addr,
|
||||
data0, data1,
|
||||
index, data[SMBUS_PIIX4_BLOCK_DATA_SIZE];
|
||||
index, data[SMBUS_PIIX4_BLOCK_DATA_SIZE], block_data_byte,
|
||||
irq, smi_en;
|
||||
acpi_t *acpi;
|
||||
pc_timer_t response_timer;
|
||||
void *i2c;
|
||||
} smbus_piix4_t;
|
||||
@@ -53,6 +59,9 @@ typedef struct {
|
||||
void *i2c;
|
||||
} smbus_ali7101_t;
|
||||
|
||||
extern void smbus_piix4_get_acpi(smbus_piix4_t *dev, acpi_t *acpi);
|
||||
extern void smbus_piix4_get_irq(uint8_t irq, smbus_piix4_t *dev);
|
||||
extern void smbus_piix4_smi_en(uint8_t smi_en, smbus_piix4_t *dev);
|
||||
|
||||
extern void smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable);
|
||||
extern void smbus_piix4_setclock(smbus_piix4_t *dev, int clock);
|
||||
@@ -62,6 +71,7 @@ extern void smbus_ali7101_remap(smbus_ali7101_t *dev, uint16_t new_io_base, uint
|
||||
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t piix4_smbus_device;
|
||||
extern const device_t intel_ich2_smbus_device;
|
||||
extern const device_t via_smbus_device;
|
||||
|
||||
extern const device_t ali7101_smbus_device;
|
||||
|
||||
@@ -25,9 +25,11 @@
|
||||
#define SPD_TYPE_FPM 0x01
|
||||
#define SPD_TYPE_EDO 0x02
|
||||
#define SPD_TYPE_SDRAM 0x04
|
||||
#define SPD_TYPE_DDR 0x07
|
||||
|
||||
#define SPD_MIN_SIZE_EDO 8
|
||||
#define SPD_MIN_SIZE_SDRAM 8
|
||||
#define SPD_MIN_SIZE_DDR 8
|
||||
|
||||
#define SPD_SIGNAL_LVTTL 0x01
|
||||
|
||||
@@ -89,6 +91,29 @@ typedef struct {
|
||||
checksum2;
|
||||
} spd_sdram_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t bytes_used, spd_size, mem_type,
|
||||
row_bits, col_bits, rows,
|
||||
data_width_lsb, data_width_msb,
|
||||
signal_level, tclk, tac,
|
||||
config, refresh_rate,
|
||||
sdram_width, ecc_width,
|
||||
tccd, burst, banks, cas, cslat, we,
|
||||
mod_attr, dev_attr,
|
||||
tclk2, tac2, tclk3, tac3,
|
||||
trp, trrd, trcd, tras,
|
||||
bank_density,
|
||||
ca_setup, ca_hold, data_setup, data_hold,
|
||||
reserved[26],
|
||||
spd_rev, checksum,
|
||||
mfg_jedec[8], mfg_loc;
|
||||
char part_no[18];
|
||||
uint8_t rev_code[2],
|
||||
mfg_year, mfg_week, serial[4], mfg_specific[27],
|
||||
other_data[127],
|
||||
checksum2;
|
||||
} spd_ddr_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t slot;
|
||||
uint16_t size;
|
||||
@@ -99,6 +124,7 @@ typedef struct {
|
||||
uint8_t data[SPD_DATA_SIZE];
|
||||
spd_edo_t edo_data;
|
||||
spd_sdram_t sdram_data;
|
||||
spd_ddr_t ddr_data;
|
||||
};
|
||||
void *eeprom;
|
||||
} spd_t;
|
||||
@@ -109,5 +135,6 @@ extern void spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint
|
||||
extern void spd_write_drbs_with_ext(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit);
|
||||
extern void spd_write_drbs_interleaved(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit);
|
||||
extern void spd_write_drbs_ali1621(uint8_t *regs, uint8_t reg_min, uint8_t reg_max);
|
||||
extern void spd_write_drbs_intel_815ep(uint8_t *regs);
|
||||
|
||||
#endif /*EMU_SPD_H*/
|
||||
|
||||
33
src/include/86box/tco.h
Normal file
33
src/include/86box/tco.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Intel TCO Header
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2022 Tiseno100.
|
||||
*/
|
||||
|
||||
#ifndef EMU_TCO_H
|
||||
# define EMU_TCO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t regs[17];
|
||||
uint16_t tco_irq;
|
||||
pc_timer_t *tco_timer;
|
||||
} tco_t;
|
||||
|
||||
extern const device_t tco_device;
|
||||
|
||||
extern void tco_irq_update(tco_t *dev, uint16_t new_irq);
|
||||
extern void tco_write(uint16_t addr, uint8_t val, tco_t *dev);
|
||||
extern uint8_t tco_read(uint16_t addr, tco_t *dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EMU_TCO_H */
|
||||
@@ -22,7 +22,7 @@ add_library(mch OBJECT machine.c machine_table.c m_xt.c m_xt_compaq.c
|
||||
m_ps2_mca.c m_at_compaq.c m_at_286_386sx.c m_at_386dx_486.c
|
||||
m_at_socket4.c m_at_socket5.c m_at_socket7_3v.c m_at_socket7.c
|
||||
m_at_sockets7.c m_at_socket8.c m_at_slot1.c m_at_slot2.c m_at_socket370.c
|
||||
m_at_misc.c)
|
||||
m_at_misc.c m_at_ich2.c)
|
||||
|
||||
if(AN430TX)
|
||||
target_compile_definitions(mch PRIVATE USE_AN430TX)
|
||||
|
||||
148
src/machine/m_at_ich2.c
Normal file
148
src/machine/m_at_ich2.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Intel ICH2 based Motherboards
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2022 Tiseno100.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/chipset.h>
|
||||
#include <86box/flash.h>
|
||||
#include <86box/sio.h>
|
||||
#include <86box/spd.h>
|
||||
#include <86box/clock.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/machine.h>
|
||||
|
||||
/*
|
||||
* Biostar M6TSL
|
||||
*
|
||||
* North Bridge: Intel 815E
|
||||
* Super I/O: National Semiconductor NSC366 (PC87366)
|
||||
* BIOS: AwardBIOS 6.00PG
|
||||
* Notes: No integrated ESS Solo & GPU
|
||||
*/
|
||||
int
|
||||
machine_at_m6tsl_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear("roms/machines/m6tsl/tsl0425b.bin",
|
||||
0x00080000, 524288, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_at_common_init_ex(model, 2);
|
||||
|
||||
pci_init(PCI_CONFIG_TYPE_1);
|
||||
pci_register_bus_slot(0, 0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
|
||||
pci_register_bus_slot(0, 0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4);
|
||||
pci_register_bus_slot(0, 0x1e, PCI_CARD_BRIDGE, 0, 0, 0, 0);
|
||||
pci_register_bus_slot(0, 0x1f, PCI_CARD_SOUTHBRIDGE, 1, 2, 8, 4);
|
||||
pci_register_bus_slot(1, 0x01, PCI_CARD_AGP, 1, 2, 3, 4);
|
||||
pci_register_bus_slot(2, 0x03, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
||||
pci_register_bus_slot(2, 0x04, PCI_CARD_NORMAL, 2, 3, 4, 1);
|
||||
pci_register_bus_slot(2, 0x05, PCI_CARD_NORMAL, 3, 4, 1, 2);
|
||||
pci_register_bus_slot(2, 0x06, PCI_CARD_NORMAL, 4, 1, 2, 3);
|
||||
pci_register_bus_slot(2, 0x07, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
||||
pci_register_bus_slot(2, 0x08, PCI_CARD_NORMAL, 2, 3, 4, 1);
|
||||
|
||||
device_add(&intel_815ep_device); /* Intel 815EP MCH (This board has normally an i815E but this doesn't matter on our implementation) */
|
||||
device_add(&intel_ich2_device); /* Intel ICH2 */
|
||||
device_add(&nsc366_device); /* National Semiconductor NSC366 */
|
||||
device_add(&sst_flash_49lf004_device); /* SST 4Mbit Firmware Hub */
|
||||
device_add(ics9xxx_get(ICS9250_08)); /* ICS Clock Chip */
|
||||
spd_register(SPD_TYPE_SDRAM, 0x7, 512);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
machine_at_m6tss_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear("roms/machines/m6tss/tss0518b.bin",
|
||||
0x00080000, 524288, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_at_common_init_ex(model, 2);
|
||||
|
||||
pci_init(PCI_CONFIG_TYPE_1);
|
||||
pci_register_bus_slot(0, 0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
|
||||
pci_register_bus_slot(0, 0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4);
|
||||
pci_register_bus_slot(0, 0x1e, PCI_CARD_BRIDGE, 0, 0, 0, 0);
|
||||
pci_register_bus_slot(0, 0x1f, PCI_CARD_SOUTHBRIDGE, 1, 2, 8, 4);
|
||||
pci_register_bus_slot(1, 0x01, PCI_CARD_AGP, 1, 2, 3, 4);
|
||||
pci_register_bus_slot(2, 0x03, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
||||
pci_register_bus_slot(2, 0x04, PCI_CARD_NORMAL, 2, 3, 4, 1);
|
||||
pci_register_bus_slot(2, 0x05, PCI_CARD_NORMAL, 3, 4, 1, 2);
|
||||
pci_register_bus_slot(2, 0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); // 0x0a
|
||||
pci_register_bus_slot(2, 0x07, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
||||
|
||||
device_add(&intel_815ep_device); /* Intel 815EP MCH */
|
||||
device_add(&intel_ich2_device); /* Intel ICH2 */
|
||||
device_add(&nsc366_device); /* National Semiconductor NSC366 */
|
||||
device_add(&sst_flash_49lf004_device); /* SST 4Mbit Firmware Hub */
|
||||
device_add(ics9xxx_get(ICS9250_08)); /* ICS Clock Chip */
|
||||
spd_register(SPD_TYPE_SDRAM, 0x7, 512);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tyan Tomcat 815T (S2080)
|
||||
*
|
||||
* North Bridge: Intel 815EP
|
||||
* Super I/O: National Semiconductor NSC366 (PC87366)
|
||||
* BIOS: AMIBIOS 7 (AMI Home BIOS Fork)
|
||||
* Notes: None
|
||||
*/
|
||||
int
|
||||
machine_at_s2080_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear("roms/machines/s2080/2080V110.ROM",
|
||||
0x00080000, 524288, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_at_common_init_ex(model, 2);
|
||||
|
||||
pci_init(PCI_CONFIG_TYPE_1);
|
||||
pci_register_bus_slot(0, 0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
|
||||
pci_register_bus_slot(0, 0x01, PCI_CARD_AGPBRIDGE, 1, 2, 0, 0);
|
||||
pci_register_bus_slot(0, 0x1e, PCI_CARD_BRIDGE, 0, 0, 0, 0);
|
||||
pci_register_bus_slot(0, 0x1f, PCI_CARD_SOUTHBRIDGE, 1, 2, 8, 4);
|
||||
pci_register_bus_slot(1, 0x01, PCI_CARD_AGP, 1, 2, 3, 4);
|
||||
pci_register_bus_slot(2, 0x04, PCI_CARD_NORMAL, 2, 3, 4, 5);
|
||||
pci_register_bus_slot(2, 0x05, PCI_CARD_NORMAL, 3, 4, 5, 6);
|
||||
pci_register_bus_slot(2, 0x06, PCI_CARD_NORMAL, 4, 5, 6, 7);
|
||||
pci_register_bus_slot(2, 0x07, PCI_CARD_NORMAL, 5, 6, 7, 8);
|
||||
pci_register_bus_slot(2, 0x08, PCI_CARD_NORMAL, 6, 7, 8, 2); // 0x0a
|
||||
pci_register_bus_slot(2, 0x09, PCI_CARD_NORMAL, 7, 8, 2, 3);
|
||||
|
||||
device_add(&intel_815ep_device); /* Intel 815EP MCH */
|
||||
device_add(&intel_ich2_device); /* Intel ICH2 */
|
||||
device_add(&nsc366_device); /* National Semiconductor NSC366 */
|
||||
device_add(&sst_flash_49lf004_device); /* SST 4Mbit Firmware Hub */
|
||||
spd_register(SPD_TYPE_SDRAM, 0x7, 512);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -77,6 +77,7 @@ const machine_filter_t machine_types[] = {
|
||||
{ "Slot 1/Socket 370", MACHINE_TYPE_SLOT1_370 },
|
||||
{ "Slot 2", MACHINE_TYPE_SLOT2 },
|
||||
{ "Socket 370", MACHINE_TYPE_SOCKET370 },
|
||||
{ "Intel ICH2", MACHINE_TYPE_ICH2 },
|
||||
{ "Miscellaneous", MACHINE_TYPE_MISC }
|
||||
};
|
||||
|
||||
@@ -121,6 +122,7 @@ const machine_filter_t machine_chipsets[] = {
|
||||
{ "Intel 440BX", MACHINE_CHIPSET_INTEL_440BX },
|
||||
{ "Intel 440ZX", MACHINE_CHIPSET_INTEL_440ZX },
|
||||
{ "Intel 440GX", MACHINE_CHIPSET_INTEL_440GX },
|
||||
{ "Intel i815EP", MACHINE_CHIPSET_INTEL_I815EP },
|
||||
{ "OPTi 283", MACHINE_CHIPSET_OPTI_283 },
|
||||
{ "OPTi 291", MACHINE_CHIPSET_OPTI_291 },
|
||||
{ "OPTi 493", MACHINE_CHIPSET_OPTI_493 },
|
||||
@@ -10931,6 +10933,108 @@ const machine_t machines[] = {
|
||||
.vid_device = NULL
|
||||
},
|
||||
|
||||
/* Intel ICH2 */
|
||||
/* Has a NSC PC87366 LPC Super I/O with on-chip AMIKey-2 KBC firmware*/
|
||||
{
|
||||
.name = "[Intel i815E] Biostar M6TSL",
|
||||
.internal_name = "m6tsl",
|
||||
.type = MACHINE_TYPE_ICH2,
|
||||
.chipset = MACHINE_CHIPSET_INTEL_I815EP,
|
||||
.init = machine_at_m6tsl_init,
|
||||
.pad = 0,
|
||||
.pad0 = 0,
|
||||
.pad1 = MACHINE_AVAILABLE,
|
||||
.pad2 = 0,
|
||||
.cpu = {
|
||||
.package = CPU_PKG_SOCKET370,
|
||||
.block= CPU_BLOCK(CPU_CYRIX3S),
|
||||
.min_bus = 66666667,
|
||||
.max_bus = 133333333,
|
||||
.min_voltage = 1300,
|
||||
.max_voltage = 3500,
|
||||
.min_multi = 1.5,
|
||||
.max_multi = 8.0,
|
||||
},
|
||||
.bus_flags = MACHINE_PS2_NOISA,
|
||||
.flags = MACHINE_IDE_DUAL,
|
||||
.ram = {
|
||||
.min = 32768,
|
||||
.max = 524288,
|
||||
.step = 32768,
|
||||
},
|
||||
.nvrmask = 255,
|
||||
.device = NULL,
|
||||
.vid_device = NULL
|
||||
},
|
||||
{
|
||||
.name = "[Intel i815EP] Biostar M6TSS",
|
||||
.internal_name = "m6tss",
|
||||
.type = MACHINE_TYPE_ICH2,
|
||||
.chipset = MACHINE_CHIPSET_INTEL_I815EP,
|
||||
.init = machine_at_m6tss_init,
|
||||
.pad = 0,
|
||||
.pad0 = 0,
|
||||
.pad1 = MACHINE_AVAILABLE,
|
||||
.pad2 = 0,
|
||||
.cpu = {
|
||||
.package = CPU_PKG_SOCKET370,
|
||||
.block = CPU_BLOCK_NONE,
|
||||
.min_bus = 66666667,
|
||||
.max_bus = 133333333,
|
||||
.min_voltage = 1300,
|
||||
.max_voltage = 3500,
|
||||
.min_multi = 1.5,
|
||||
.max_multi = 8.0,
|
||||
},
|
||||
.bus_flags = MACHINE_PS2_AGP,
|
||||
.flags = MACHINE_IDE_DUAL,
|
||||
.ram = {
|
||||
.min = 32768,
|
||||
.max = 524288,
|
||||
.step = 32768,
|
||||
},
|
||||
.nvrmask = 255,
|
||||
.kbc = KBC_UNKNOWN,
|
||||
.kbc_p1 = 0,
|
||||
.gpio = 0,
|
||||
.device = NULL,
|
||||
.vid_device = NULL
|
||||
},
|
||||
{
|
||||
.name = "[Intel i815EP] Tyan Tomcat i815T",
|
||||
.internal_name = "s2080",
|
||||
.type = MACHINE_TYPE_ICH2,
|
||||
.chipset = MACHINE_CHIPSET_INTEL_I815EP,
|
||||
.init = machine_at_s2080_init,
|
||||
.pad = 0,
|
||||
.pad0 = 0,
|
||||
.pad1 = MACHINE_AVAILABLE,
|
||||
.pad2 = 0,
|
||||
.cpu = {
|
||||
.package = CPU_PKG_SOCKET370,
|
||||
.block = CPU_BLOCK_NONE,
|
||||
.min_bus = 66666667,
|
||||
.max_bus = 133333333,
|
||||
.min_voltage = 1300,
|
||||
.max_voltage = 3500,
|
||||
.min_multi = 1.5,
|
||||
.max_multi = 8.0,
|
||||
},
|
||||
.bus_flags = MACHINE_PS2_AGP,
|
||||
.flags = MACHINE_IDE_DUAL,
|
||||
.ram = {
|
||||
.min = 32768,
|
||||
.max = 524288,
|
||||
.step = 32768
|
||||
},
|
||||
.nvrmask = 255,
|
||||
.kbc = KBC_UNKNOWN,
|
||||
.kbc_p1 = 0,
|
||||
.gpio = 0,
|
||||
.device = NULL,
|
||||
.vid_device = NULL
|
||||
},
|
||||
|
||||
{
|
||||
.name = NULL,
|
||||
.internal_name = NULL,
|
||||
@@ -10967,6 +11071,41 @@ const machine_t machines[] = {
|
||||
}
|
||||
};
|
||||
|
||||
/* Saved copies - jumpers get applied to these.
|
||||
We use also machine_gpio to store IBM PC/XT jumpers as they need more than one byte. */
|
||||
static uint16_t machine_p1;
|
||||
static uint32_t machine_gpio;
|
||||
|
||||
uint8_t
|
||||
machine_get_p1(void)
|
||||
{
|
||||
return machine_p1;
|
||||
}
|
||||
|
||||
void
|
||||
machine_load_p1(int m)
|
||||
{
|
||||
machine_p1 = machines[machine].kbc_p1;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
machine_get_gpio(void)
|
||||
{
|
||||
return machine_gpio;
|
||||
}
|
||||
|
||||
void
|
||||
machine_load_gpio(int m)
|
||||
{
|
||||
machine_gpio = machines[machine].gpio;
|
||||
}
|
||||
|
||||
void
|
||||
machine_set_gpio(uint32_t gpio)
|
||||
{
|
||||
machine_gpio = gpio;
|
||||
}
|
||||
|
||||
int
|
||||
machine_count(void)
|
||||
{
|
||||
|
||||
139
src/mem/spd.c
139
src/mem/spd.c
@@ -190,6 +190,7 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
|
||||
uint16_t min_module_size, rows[SPD_MAX_SLOTS], asym;
|
||||
spd_edo_t *edo_data;
|
||||
spd_sdram_t *sdram_data;
|
||||
spd_ddr_t *ddr_data;
|
||||
|
||||
/* Determine the minimum module size for this RAM type. */
|
||||
switch (ram_type) {
|
||||
@@ -202,6 +203,10 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
|
||||
min_module_size = SPD_MIN_SIZE_SDRAM;
|
||||
break;
|
||||
|
||||
case SPD_TYPE_DDR:
|
||||
min_module_size = SPD_MIN_SIZE_DDR;
|
||||
break;
|
||||
|
||||
default:
|
||||
spd_log("SPD: unknown RAM type %02X\n", ram_type);
|
||||
return;
|
||||
@@ -335,6 +340,60 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
|
||||
for (i = 0; i < 129; i++)
|
||||
sdram_data->checksum2 += spd_modules[slot]->data[i];
|
||||
break;
|
||||
|
||||
case SPD_TYPE_DDR:
|
||||
ddr_data = &spd_modules[slot]->ddr_data;
|
||||
|
||||
ddr_data->bytes_used = 0x80;
|
||||
ddr_data->spd_size = 0x08;
|
||||
ddr_data->mem_type = ram_type;
|
||||
ddr_data->row_bits = SPD_ROLLUP(6 + log2i(spd_modules[slot]->row1)); /* first row */
|
||||
ddr_data->col_bits = 9;
|
||||
if (spd_modules[slot]->row1 != spd_modules[slot]->row2) { /* the upper 4 bits of row_bits/col_bits should be 0 on a symmetric module */
|
||||
ddr_data->row_bits |= SPD_ROLLUP(6 + log2i(spd_modules[slot]->row2)) << 4; /* second row, if different from first */
|
||||
ddr_data->col_bits |= 9 << 4; /* same as first row, but just in case */
|
||||
}
|
||||
ddr_data->rows = 2;
|
||||
ddr_data->data_width_lsb = 64;
|
||||
ddr_data->signal_level = SPD_SIGNAL_LVTTL;
|
||||
ddr_data->tclk = 0x75; /* 7.5 ns = 133.3 MHz */
|
||||
ddr_data->tac = 0x10;
|
||||
ddr_data->refresh_rate = SPD_SDR_REFRESH_SELF | SPD_REFRESH_NORMAL;
|
||||
ddr_data->sdram_width = 8;
|
||||
ddr_data->tccd = 1;
|
||||
ddr_data->burst = SPD_SDR_BURST_PAGE | 1 | 2 | 4 | 8;
|
||||
ddr_data->banks = 4;
|
||||
ddr_data->cas = 0x7f; /* CAS Latency */
|
||||
ddr_data->cslat = ddr_data->we = 0x7f;
|
||||
ddr_data->dev_attr = SPD_SDR_ATTR_EARLY_RAS | SPD_SDR_ATTR_AUTO_PC | SPD_SDR_ATTR_PC_ALL | SPD_SDR_ATTR_W1R_BURST;
|
||||
ddr_data->tclk2 = 0xA0; /* 10 ns = 100 MHz */
|
||||
ddr_data->tclk3 = 0xF0; /* 15 ns = 66.7 MHz */
|
||||
ddr_data->tac2 = ddr_data->tac3 = 0x10;
|
||||
ddr_data->trp = ddr_data->trrd = ddr_data->trcd = ddr_data->tras = 1;
|
||||
if (spd_modules[slot]->row1 != spd_modules[slot]->row2) {
|
||||
/* Utilities interpret bank_density a bit differently on asymmetric modules. */
|
||||
ddr_data->bank_density = 1 << (log2i(spd_modules[slot]->row1 >> 1) - 2); /* first row */
|
||||
ddr_data->bank_density |= 1 << (log2i(spd_modules[slot]->row2 >> 1) - 2); /* second row */
|
||||
} else {
|
||||
ddr_data->bank_density = 1 << (log2i(spd_modules[slot]->row1 >> 1) - 1); /* symmetric module = only one bit is set */
|
||||
}
|
||||
ddr_data->ca_setup = ddr_data->data_setup = 0x15;
|
||||
ddr_data->ca_hold = ddr_data->data_hold = 0x08;
|
||||
|
||||
ddr_data->spd_rev = 0x10;
|
||||
for (i = spd_write_part_no(ddr_data->part_no, "DDR", rows[row]);
|
||||
i < sizeof(ddr_data->part_no); i++)
|
||||
ddr_data->part_no[i] = ' '; /* part number should be space-padded */
|
||||
ddr_data->rev_code[0] = BCD8(EMU_VERSION_MAJ);
|
||||
ddr_data->rev_code[1] = BCD8(EMU_VERSION_MIN);
|
||||
ddr_data->mfg_year = 20;
|
||||
ddr_data->mfg_week = 13;
|
||||
|
||||
for (i = 0; i < 63; i++)
|
||||
ddr_data->checksum += spd_modules[slot]->data[i];
|
||||
for (i = 0; i < 129; i++)
|
||||
ddr_data->checksum2 += spd_modules[slot]->data[i];
|
||||
break;
|
||||
}
|
||||
|
||||
row++;
|
||||
@@ -518,7 +577,7 @@ spd_write_drbs_ali1621(uint8_t *regs, uint8_t reg_min, uint8_t reg_max)
|
||||
}
|
||||
|
||||
/* Write DRBs for each row. */
|
||||
spd_log("SPD: Writing DRBs... regs=[%02X:%02X] unit=%d\n", reg_min, reg_max, drb_unit);
|
||||
// spd_log("SPD: Writing DRBs... regs=[%02X:%02X] unit=%d\n", reg_min, reg_max, drb_unit);
|
||||
for (dimm = 0; dimm <= ((reg_max - reg_min) >> 2); dimm++) {
|
||||
size = 0;
|
||||
drb = reg_min + (dimm << 2);
|
||||
@@ -577,6 +636,84 @@ spd_write_drbs_ali1621(uint8_t *regs, uint8_t reg_min, uint8_t reg_max)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
spd_write_drbs_intel_815ep(uint8_t *regs)
|
||||
{
|
||||
/* All Intel MCH based boards demand SPD so we ignore completely the non-SPD calculations */
|
||||
int size;
|
||||
int reg_apply;
|
||||
uint16_t rows[SPD_MAX_SLOTS];
|
||||
|
||||
if(!spd_present)
|
||||
spd_populate(rows, 3, mem_size << 10, 32, 512, 0);
|
||||
|
||||
/* Clear previous configurations */
|
||||
regs[0x52] = regs[0x54] = 0;
|
||||
|
||||
/* Write DRBs for each row. */
|
||||
for (int slot = 0; slot < 3; slot++) {
|
||||
size = spd_modules[slot]->row1 + spd_modules[slot]->row2;
|
||||
spd_log("Intel 815EP SPD: Registering Slot %d with size %dMB.\n", slot, size);
|
||||
|
||||
/* Calculate Size. Nullify if the size is illegal. */
|
||||
switch(size)
|
||||
{
|
||||
default:
|
||||
reg_apply = 0;
|
||||
spd_log("Intel 815EP SPD: Illegal Size on Slot %d. Size not divisible by 32.\n", slot);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
reg_apply = 1;
|
||||
break;
|
||||
|
||||
case 48:
|
||||
reg_apply = 3;
|
||||
break;
|
||||
|
||||
case 64:
|
||||
reg_apply = 4;
|
||||
break;
|
||||
|
||||
case 96:
|
||||
reg_apply = 6;
|
||||
break;
|
||||
|
||||
case 128:
|
||||
reg_apply = 7;
|
||||
break;
|
||||
|
||||
case 192:
|
||||
reg_apply = 11;
|
||||
break;
|
||||
|
||||
case 256:
|
||||
reg_apply = 12;
|
||||
break;
|
||||
|
||||
case 512:
|
||||
reg_apply = 15;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Write on the representative register */
|
||||
switch(slot)
|
||||
{
|
||||
case 0:
|
||||
regs[0x52] |= reg_apply;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
regs[0x52] |= reg_apply << 4;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
regs[0x54] |= reg_apply;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const device_t spd_device = {
|
||||
.name = "Serial Presence Detect ROMs",
|
||||
.internal_name = "spd",
|
||||
|
||||
@@ -80,6 +80,9 @@ static char flash_path[1024];
|
||||
#define SST39SF020 0xb600
|
||||
#define SST39SF040 0xb700
|
||||
|
||||
#define SST49LF002 0x5700
|
||||
#define SST49LF004 0x6000
|
||||
|
||||
#define WINBOND 0xda /* Winbond Manufacturer's ID */
|
||||
#define W29C020 0x4500
|
||||
|
||||
@@ -564,3 +567,39 @@ const device_t sst_flash_39sf040_device = {
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Firmware Hubs. The FWH signals are not implemented yet. Firmware Hubs do write cycles
|
||||
* to read/write on the flash. SST Flashes still do traditional flashing via PP Mode. Our
|
||||
* BIOS firmwares don't seem to utilize FWH R/W thus the FWH ports remain unknown for an
|
||||
* implementation. We just contain the ID's so the BIOS can do ESCD & DMI writes with no
|
||||
* worries.
|
||||
*/
|
||||
const device_t sst_flash_49lf002_device = {
|
||||
.name = "SST 49LF002 Firmware Hub",
|
||||
.internal_name = "sst_flash_49lf002",
|
||||
.flags = 0,
|
||||
.local = SST | SST49LF002 | SIZE_2M,
|
||||
.init = sst_init,
|
||||
.close = sst_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t sst_flash_49lf004_device = {
|
||||
.name = "SST 49LF004 Firmware Hub",
|
||||
.internal_name = "sst_flash_49lf004",
|
||||
.flags = 0,
|
||||
.local = SST | SST49LF004 | SIZE_4M,
|
||||
|
||||
.init = sst_init,
|
||||
.close = sst_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
@@ -540,6 +540,11 @@ pic_set_pci(void)
|
||||
io_sethandler(i, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic);
|
||||
io_sethandler(i + 0x0080, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2);
|
||||
}
|
||||
|
||||
for (i = 0xff20; i < 0xff40; i += 4) {
|
||||
io_sethandler(i, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic);
|
||||
io_sethandler(i + 0x0080, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,10 +15,11 @@
|
||||
|
||||
add_library(sio OBJECT sio_acc3221.c sio_ali5123.c sio_f82c710.c sio_82091aa.c
|
||||
sio_fdc37c6xx.c sio_fdc37c67x.c sio_fdc37c669.c sio_fdc37c93x.c sio_fdc37m60x.c
|
||||
sio_nsc366.c
|
||||
sio_it8661f.c
|
||||
sio_pc87306.c sio_pc87307.c sio_pc87309.c sio_pc87310.c sio_pc87311.c sio_pc87332.c
|
||||
sio_prime3b.c sio_prime3c.c
|
||||
sio_w83787f.c sio_w83877f.c sio_w83977f.c sio_um8669f.c
|
||||
sio_w83627hf.c sio_w83787f.c sio_w83877f.c sio_w83977f.c sio_um8669f.c
|
||||
sio_vt82c686.c)
|
||||
|
||||
if(SIO_DETECT)
|
||||
|
||||
530
src/sio/sio_nsc366.c
Normal file
530
src/sio/sio_nsc366.c
Normal file
@@ -0,0 +1,530 @@
|
||||
/*
|
||||
* 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 PC87366 (NSC366)
|
||||
* Super I/O chip.
|
||||
*
|
||||
* Author: Tiseno100,
|
||||
* Copyright 2022 Tiseno100.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/hwm.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/lpt.h>
|
||||
#include <86box/nsc366.h>
|
||||
#include <86box/serial.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdd_common.h>
|
||||
#include <86box/port_92.h>
|
||||
#include <86box/sio.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fdc_t *fdc;
|
||||
serial_t *uart[2];
|
||||
nsc366_hwm_t *hwm;
|
||||
|
||||
uint8_t index, ldn, sio_config[14],
|
||||
ld_activate[15],
|
||||
io_base0[2][15],
|
||||
io_base1[2][15],
|
||||
int_num_irq[15],
|
||||
irq[15],
|
||||
dma_select0[15],
|
||||
dma_select1[15],
|
||||
dev_specific_config[3][15];
|
||||
|
||||
int siofc_lock;
|
||||
} nsc366_t;
|
||||
|
||||
#ifdef ENABLE_NSC366_LOG
|
||||
int nsc366_do_log = ENABLE_NSC366_LOG;
|
||||
|
||||
|
||||
void
|
||||
nsc366_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (nsc366_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define nsc366_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
nsc366_fdc(nsc366_t *dev)
|
||||
{
|
||||
fdc_remove(dev->fdc);
|
||||
int base = ((dev->io_base0[0][0] & 7) << 8) | (dev->io_base0[1][0] & 0xf8);
|
||||
int irq = dev->int_num_irq[0] & 0x0f;
|
||||
int dma_ch = dev->dma_select0[0] & 7;
|
||||
|
||||
if (dev->ld_activate[0]) {
|
||||
nsc366_log("NSC 366 FDC: Reconfigured with Base: 0x%04x IRQ: %d DMA Channel: %d\n", base, irq, dma_ch);
|
||||
fdc_set_base(dev->fdc, base);
|
||||
fdc_set_irq(dev->fdc, irq);
|
||||
fdc_set_dma_ch(dev->fdc, dma_ch);
|
||||
fdc_update_densel_polarity(dev->fdc, !!(dev->dev_specific_config[0][0] & 0x20));
|
||||
if (dev->dev_specific_config[0][0] & 8)
|
||||
fdc_writeprotect(dev->fdc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsc366_lpt(nsc366_t *dev)
|
||||
{
|
||||
lpt1_remove();
|
||||
int base = ((dev->io_base0[0][1] & 7) << 8) | (dev->io_base0[1][1] & 0xfc);
|
||||
int irq = (dev->int_num_irq[1] & 0x0f);
|
||||
|
||||
if (dev->ld_activate[1]) {
|
||||
nsc366_log("NSC 366 LPT: Reconfigured with Base 0x%04x IRQ: %d\n", base ,irq);
|
||||
lpt1_init(base);
|
||||
lpt1_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nsc366_uart(int uart, nsc366_t *dev)
|
||||
{
|
||||
serial_remove(dev->uart[uart]);
|
||||
int base = ((dev->io_base0[0][2 + uart] & 7) << 8) | (dev->io_base0[1][2 + uart] & 0xf8);
|
||||
int irq = (dev->int_num_irq[2 + uart] & 0x0f);
|
||||
|
||||
if (dev->ld_activate[2 + uart]) {
|
||||
nsc366_log("NSC 366 UART Serial %d: Reconfigured with Base 0x%04x IRQ: %d\n", uart, base ,irq);
|
||||
serial_setup(dev->uart[uart], base, irq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nsc366_fscm(nsc366_t *dev)
|
||||
{
|
||||
uint16_t base = (dev->io_base0[0][9] << 8) | (dev->io_base0[1][9] & 0xf0);
|
||||
|
||||
if (dev->ld_activate[9])
|
||||
nsc366_log("NSC 366 Fan Control: Reconfigured with Base 0x%04x\n", base);
|
||||
|
||||
nsc366_update_fscm_io(dev->ld_activate[9], base, dev->hwm);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nsc366_vlm(nsc366_t *dev)
|
||||
{
|
||||
uint16_t base = (dev->io_base0[0][13] << 8) | (dev->io_base0[1][13] & 0xf0);
|
||||
|
||||
if (dev->ld_activate[13])
|
||||
nsc366_log("NSC 366 Voltage Monitor: Reconfigured with Base 0x%04x\n", base);
|
||||
|
||||
nsc366_update_vlm_io(dev->ld_activate[13], base, dev->hwm);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nsc366_tms(nsc366_t *dev)
|
||||
{
|
||||
uint16_t base = (dev->io_base0[0][14] << 8) | (dev->io_base0[1][14] & 0xf0);
|
||||
|
||||
if (dev->ld_activate[14])
|
||||
nsc366_log("NSC 366 Temperature Monitor: Reconfigured with Base 0x%04x\n", base);
|
||||
|
||||
nsc366_update_tms_io(dev->ld_activate[14], base, dev->hwm);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nsc366_ldn_redirect(nsc366_t *dev)
|
||||
{
|
||||
switch(dev->ldn) {
|
||||
case 0:
|
||||
nsc366_fdc(dev);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
nsc366_lpt(dev);
|
||||
break;
|
||||
|
||||
case 2 ... 3:
|
||||
nsc366_uart(dev->ldn == 3, dev);
|
||||
break;
|
||||
|
||||
case 9:
|
||||
nsc366_fscm(dev);
|
||||
break;
|
||||
|
||||
case 13:
|
||||
nsc366_vlm(dev);
|
||||
break;
|
||||
|
||||
case 14:
|
||||
nsc366_tms(dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nsc366_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
nsc366_t *dev = (nsc366_t *)priv;
|
||||
|
||||
if (addr & 1) switch(dev->index) {
|
||||
/* LDN */
|
||||
case 0x07:
|
||||
if (val <= 0x0e)
|
||||
dev->ldn = val;
|
||||
break;
|
||||
|
||||
/* Super I/O Configuration */
|
||||
case 0x21:
|
||||
if (!dev->siofc_lock) {
|
||||
if (val & 0x80) {
|
||||
dev->sio_config[dev->index - 0x20] = val | 0x80;
|
||||
dev->siofc_lock = 1;
|
||||
} else
|
||||
dev->sio_config[dev->index - 0x20] = val;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x22:
|
||||
if (!dev->siofc_lock)
|
||||
dev->sio_config[dev->index - 0x20] = val;
|
||||
break;
|
||||
|
||||
case 0x23:
|
||||
if (!dev->siofc_lock)
|
||||
dev->sio_config[dev->index - 0x20] = val & 0xf7;
|
||||
break;
|
||||
|
||||
case 0x24:
|
||||
if (!dev->siofc_lock)
|
||||
dev->sio_config[dev->index - 0x20] = val;
|
||||
break;
|
||||
|
||||
case 0x25:
|
||||
if (!dev->siofc_lock)
|
||||
dev->sio_config[dev->index - 0x20] = val & 0xf3;
|
||||
break;
|
||||
|
||||
case 0x28:
|
||||
dev->sio_config[dev->index - 0x20] = val & 0xf3;
|
||||
break;
|
||||
|
||||
case 0x2a:
|
||||
if (!dev->siofc_lock)
|
||||
dev->sio_config[dev->index - 0x20] = val;
|
||||
break;
|
||||
|
||||
case 0x2b:
|
||||
if (!dev->siofc_lock)
|
||||
/* Force Case Intrusion to always off */
|
||||
dev->sio_config[dev->index - 0x20] = val & 0x4f;
|
||||
break;
|
||||
|
||||
case 0x2c ... 0x2d:
|
||||
dev->sio_config[dev->index - 0x20] = val & 0xf3;
|
||||
break;
|
||||
|
||||
/* Logical Devices */
|
||||
case 0x30:
|
||||
dev->ld_activate[dev->ldn] = (val & 1) && (dev->sio_config[0] & 1);
|
||||
nsc366_ldn_redirect(dev);
|
||||
break;
|
||||
|
||||
case 0x60 ... 0x61:
|
||||
dev->io_base0[dev->index & 1][dev->ldn] = val;
|
||||
nsc366_ldn_redirect(dev);
|
||||
break;
|
||||
|
||||
case 0x62 ... 0x63:
|
||||
dev->io_base1[dev->index & 1][dev->ldn] = val;
|
||||
nsc366_ldn_redirect(dev);
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
dev->int_num_irq[dev->ldn] = val & 0x1f;
|
||||
nsc366_ldn_redirect(dev);
|
||||
break;
|
||||
|
||||
case 0x71:
|
||||
dev->irq[dev->ldn] = val;
|
||||
nsc366_ldn_redirect(dev);
|
||||
break;
|
||||
|
||||
case 0x74:
|
||||
dev->dma_select0[dev->ldn] = val & 0x1f;
|
||||
nsc366_ldn_redirect(dev);
|
||||
break;
|
||||
|
||||
case 0x75:
|
||||
dev->dma_select1[dev->ldn] = val & 0x1f;
|
||||
nsc366_ldn_redirect(dev);
|
||||
break;
|
||||
|
||||
case 0xf0 ... 0xf2:
|
||||
dev->dev_specific_config[dev->index - 0xf0][dev->ldn] = val;
|
||||
nsc366_ldn_redirect(dev);
|
||||
break;
|
||||
} else
|
||||
dev->index = val;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
nsc366_read(uint16_t addr, void *priv)
|
||||
{
|
||||
nsc366_t *dev = (nsc366_t *)priv;
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
if (addr & 1) {
|
||||
switch (dev->index) {
|
||||
case 0x07:
|
||||
ret = dev->ldn;
|
||||
break;
|
||||
|
||||
case 0x20 ... 0x2d:
|
||||
ret = dev->sio_config[dev->index - 0x20];
|
||||
break;
|
||||
|
||||
case 0x30:
|
||||
ret = dev->ld_activate[dev->ldn];
|
||||
break;
|
||||
|
||||
case 0x60 ... 0x61:
|
||||
ret = dev->io_base0[dev->index & 1][dev->ldn];
|
||||
break;
|
||||
|
||||
case 0x62 ... 0x63:
|
||||
ret = dev->io_base1[dev->index & 1][dev->ldn];
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
ret = dev->int_num_irq[dev->ldn];
|
||||
break;
|
||||
|
||||
case 0x71:
|
||||
ret = dev->irq[dev->ldn];
|
||||
break;
|
||||
|
||||
case 0x74:
|
||||
ret = dev->dma_select0[dev->ldn];
|
||||
break;
|
||||
|
||||
case 0x75:
|
||||
ret = dev->dma_select1[dev->ldn];
|
||||
break;
|
||||
|
||||
case 0xf0 ... 0xf2:
|
||||
ret = dev->dev_specific_config[dev->index - 0xf0][dev->ldn];
|
||||
break;
|
||||
}
|
||||
} else
|
||||
ret = dev->index;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nsc366_reset(void *priv)
|
||||
{
|
||||
nsc366_t *dev = (nsc366_t *)priv;
|
||||
|
||||
/* Basic Configuration */
|
||||
dev->ldn = 0;
|
||||
dev->siofc_lock = 0;
|
||||
memset(dev->sio_config, 0, sizeof(dev->sio_config));
|
||||
memset(dev->ld_activate, 0, sizeof(dev->ld_activate));
|
||||
memset(dev->io_base0, 0, sizeof(dev->io_base0));
|
||||
memset(dev->io_base1, 0, sizeof(dev->io_base1));
|
||||
memset(dev->int_num_irq, 0, sizeof(dev->int_num_irq));
|
||||
memset(dev->irq, 0, sizeof(dev->irq));
|
||||
memset(dev->dma_select0, 0, sizeof(dev->dma_select0));
|
||||
memset(dev->dma_select1, 0, sizeof(dev->dma_select1));
|
||||
memset(dev->dev_specific_config, 0, sizeof(dev->dev_specific_config));
|
||||
|
||||
/* SIO Config */
|
||||
dev->sio_config[0x00] = 0xe9; /* National Semiconductor NSC366 */
|
||||
dev->sio_config[0x07] = 0x01;
|
||||
|
||||
/* FDC */
|
||||
fdc_reset(dev->fdc);
|
||||
dev->io_base0[0][0] = 0x03;
|
||||
dev->io_base0[1][0] = 0xf2;
|
||||
dev->int_num_irq[0] = 0x06;
|
||||
dev->irq[0] = 0x03;
|
||||
dev->dma_select0[0] = 0x02;
|
||||
dev->dma_select1[0] = 0x04;
|
||||
dev->dev_specific_config[0][0] = 0x24;
|
||||
|
||||
nsc366_fdc(dev);
|
||||
|
||||
/* LPT */
|
||||
dev->io_base0[0][1] = 0x02;
|
||||
dev->io_base0[1][1] = 0x78;
|
||||
dev->int_num_irq[1] = 0x07;
|
||||
dev->irq[1] = 0x02;
|
||||
dev->dma_select0[1] = 0x04;
|
||||
dev->dma_select1[1] = 0x04;
|
||||
dev->dev_specific_config[0][1] = 0xf2;
|
||||
|
||||
/* UART Serial 2 */
|
||||
dev->io_base0[0][2] = 0x02;
|
||||
dev->io_base0[1][2] = 0xf8;
|
||||
dev->int_num_irq[2] = 0x03;
|
||||
dev->irq[2] = 0x03;
|
||||
dev->dma_select0[2] = 0x04;
|
||||
dev->dma_select1[2] = 0x04;
|
||||
dev->dev_specific_config[0][2] = 0x02;
|
||||
|
||||
nsc366_uart(1, dev);
|
||||
|
||||
/* UART Serial 1 */
|
||||
dev->io_base0[0][3] = 0x03;
|
||||
dev->io_base0[1][3] = 0xf8;
|
||||
dev->int_num_irq[3] = 0x04;
|
||||
dev->irq[3] = 0x03;
|
||||
dev->dma_select0[3] = 0x04;
|
||||
dev->dma_select1[3] = 0x04;
|
||||
dev->dev_specific_config[0][3] = 0x02;
|
||||
|
||||
/* SWC */
|
||||
dev->irq[4] = 0x03;
|
||||
dev->dma_select0[4] = 0x04;
|
||||
|
||||
/* Keyboard Controller */
|
||||
dev->int_num_irq[5] = 0x0c;
|
||||
dev->irq[5] = 0x02;
|
||||
|
||||
/* Mouse Controller */
|
||||
dev->io_base0[1][6] = 0x60;
|
||||
dev->io_base1[1][6] = 0x64;
|
||||
dev->int_num_irq[6] = 0x01;
|
||||
dev->irq[6] = 0x02;
|
||||
dev->dma_select0[6] = 0x04;
|
||||
dev->dma_select1[6] = 0x04;
|
||||
dev->dev_specific_config[0][6] = 0x40;
|
||||
|
||||
/* GPIO */
|
||||
dev->irq[7] = 0x03;
|
||||
dev->dma_select0[7] = 0x04;
|
||||
dev->dma_select1[7] = 0x04;
|
||||
|
||||
/* ACB */
|
||||
dev->irq[8] = 0x03;
|
||||
dev->dma_select0[8] = 0x04;
|
||||
dev->dma_select1[8] = 0x04;
|
||||
|
||||
/* Fan Speed Monitor & Control */
|
||||
dev->irq[9] = 0x03;
|
||||
dev->dma_select0[9] = 0x04;
|
||||
dev->dma_select1[9] = 0x04;
|
||||
nsc366_fscm(dev);
|
||||
|
||||
/* Voltage Level Monitor */
|
||||
dev->irq[13] = 0x03;
|
||||
dev->dma_select0[13] = 0x04;
|
||||
dev->dma_select1[13] = 0x04;
|
||||
nsc366_vlm(dev);
|
||||
|
||||
/* Temperature Monitor */
|
||||
dev->irq[14] = 0x03;
|
||||
dev->dma_select0[14] = 0x04;
|
||||
dev->dma_select1[14] = 0x04;
|
||||
nsc366_tms(dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nsc366_close(void *priv)
|
||||
{
|
||||
nsc366_t *dev = (nsc366_t *)priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
nsc366_init(const device_t *info)
|
||||
{
|
||||
nsc366_t *dev = (nsc366_t *)malloc(sizeof(nsc366_t));
|
||||
memset(dev, 0, sizeof(nsc366_t));
|
||||
|
||||
io_sethandler(info->local, 2, nsc366_read, NULL, NULL, nsc366_write, NULL, NULL, dev); /* Ports 2E-2Fh(4E-4Fh if BADDR High): National Semiconductor NSC366 */
|
||||
|
||||
/* FDC */
|
||||
dev->fdc = device_add(&fdc_at_nsc_device);
|
||||
|
||||
/* Hardware Monitor Setup */
|
||||
dev->hwm = device_add(&nsc366_hwm_device);
|
||||
|
||||
/* Keyboard Controller */
|
||||
device_add(&keyboard_ps2_ami_pci_device);
|
||||
|
||||
/* Port 92h */
|
||||
device_add(&port_92_pci_device);
|
||||
|
||||
/* Serial */
|
||||
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
||||
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
||||
|
||||
nsc366_reset(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
const device_t nsc366_device = {
|
||||
.name = "National Semiconductor NSC366",
|
||||
.internal_name = "nsc366",
|
||||
.flags = 0,
|
||||
.local = 0x2e,
|
||||
.init = nsc366_init,
|
||||
.close = nsc366_close,
|
||||
.reset = nsc366_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t nsc366_4f_device = {
|
||||
.name = "National Semiconductor NSC366 (With BADDR Pin High)",
|
||||
.internal_name = "nsc366",
|
||||
.flags = 0,
|
||||
.local = 0x4e,
|
||||
.init = nsc366_init,
|
||||
.close = nsc366_close,
|
||||
.reset = nsc366_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
962
src/sio/sio_w83627hf.c
Normal file
962
src/sio/sio_w83627hf.c
Normal file
@@ -0,0 +1,962 @@
|
||||
/*
|
||||
* 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 Winbond W83627HF chipset.
|
||||
*
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020,2021 Tiseno100.
|
||||
* Copyright 2021,2021 Miran Grca.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Winbond W83627HF Register Summary for ISAPnP (potentially)
|
||||
|
||||
Found on: https://github.com/koitsu/bsdhwmon/issues/6
|
||||
|
||||
Register dump:
|
||||
idx 02 20 21 22 23 24 25 26 28 29 2a 2b 2c 2e 2f
|
||||
val ff 52 41 ff fe c4 00 00 00 50 fc 00 ff 00 ff
|
||||
def 00 52 NA ff 00 MM 00 00 00 00 7c c0 00 00 00
|
||||
LDN 0x00 (Floppy)
|
||||
idx 30 60 61 70 74 f0 f1 f2 f4 f5
|
||||
val 00 00 00 06 02 0e 00 ff 00 00
|
||||
def 01 03 f0 06 02 0e 00 ff 00 00
|
||||
LDN 0x01 (Parallel port)
|
||||
idx 30 60 61 70 74 f0
|
||||
val 00 00 00 07 03 3f
|
||||
def 01 03 78 07 04 3f
|
||||
LDN 0x02 (COM1)
|
||||
idx 30 60 61 70 f0
|
||||
val 01 03 f8 04 00
|
||||
def 01 03 f8 04 00
|
||||
LDN 0x03 (COM2)
|
||||
idx 30 60 61 70 f0 f1
|
||||
val 01 02 f8 03 00 40
|
||||
def 01 02 f8 03 00 00
|
||||
LDN 0x05 (Keyboard)
|
||||
idx 30 60 61 62 63 70 72 f0
|
||||
val 01 00 60 00 64 01 00 80
|
||||
def 01 00 60 00 64 01 0c 80
|
||||
LDN 0x06 (Consumer IR)
|
||||
idx 30 60 61 70
|
||||
val 00 00 00 00
|
||||
def 00 00 00 00
|
||||
LDN 0x07 (Game port, MIDI port, GPIO 1)
|
||||
idx 30 60 61 62 63 70 f0 f1 f2
|
||||
val 01 00 00 00 00 00 ff ff 00
|
||||
def 00 02 01 03 30 09 ff 00 00
|
||||
LDN 0x08 (GPIO 2, watchdog timer)
|
||||
idx 30 f0 f1 f2 f3 f5 f6 f6 f7
|
||||
val 00 ff ff ff 00 08 00 00 c0
|
||||
def 00 ff 00 00 00 00 00 00 00
|
||||
LDN 0x09 (GPIO 3)
|
||||
idx 30 f0 f1 f2 f3
|
||||
val 01 ff 14 00 40
|
||||
def 00 ff 00 00 00
|
||||
LDN 0x0a (ACPI)
|
||||
idx 30 70 e0 e1 e2 e3 e4 e5 e6 e7 f0 f1 f3 f4 f6 f7 f9 fe ff
|
||||
val 01 00 00 00 f2 00 40 00 00 00 00 af 32 00 00 00 00 00 00
|
||||
def 00 00 00 00 NA NA 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
LDN 0x0b (Hardware monitor)
|
||||
idx 30 60 61 70 f0
|
||||
val 01 02 95 00 01
|
||||
def 00 00 00 00 00
|
||||
Hardware monitor (0x029a)
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Notes : ISAPnP is missing and the Hardware Monitor I2C is not implemented.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/device.h>
|
||||
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/i2c.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/lpt.h>
|
||||
#include <86box/port_92.h>
|
||||
#include <86box/serial.h>
|
||||
|
||||
#include <86box/hwm.h>
|
||||
#include <86box/sio.h>
|
||||
|
||||
#ifdef ENABLE_W83627HF_LOG
|
||||
int w83627hf_do_log = ENABLE_W83627HF_LOG;
|
||||
|
||||
|
||||
static void
|
||||
w83627hf_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (w83627hf_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define w83627hf_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t hwm_index, hwm_regs[256];
|
||||
|
||||
uint8_t index, cfg_unlocked,
|
||||
regs[48], dev_regs[12][256];
|
||||
|
||||
int has_hwm;
|
||||
fdc_t *fdc_controller;
|
||||
port_92_t *port_92;
|
||||
serial_t *uart[2];
|
||||
} w83627hf_t;
|
||||
|
||||
/* These differ per board and must be programmed manually */
|
||||
int fan1_rpm, fan2_rpm, fan3_rpm, vcorea_voltage, vcoreb_voltage;
|
||||
|
||||
void
|
||||
w83627hf_stabilizer(int vcoreb, int fan1, int fan2, int fan3)
|
||||
{
|
||||
vcoreb_voltage = vcoreb;
|
||||
fan1_rpm = fan1;
|
||||
fan2_rpm = fan2;
|
||||
fan3_rpm = fan3;
|
||||
}
|
||||
|
||||
static void
|
||||
w83627hf_hwm_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
w83627hf_t *dev = (w83627hf_t *)priv;
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case 0x295:
|
||||
dev->hwm_index = val;
|
||||
break;
|
||||
|
||||
case 0x296:
|
||||
w83627hf_log("W83627HF-HWM: dev->regs[%02x] = %02x\n", dev->hwm_index, val);
|
||||
switch(dev->hwm_index)
|
||||
{
|
||||
case 0x2b ... 0x3f:
|
||||
case 0x6b ... 0x7f:
|
||||
dev->hwm_regs[dev->hwm_index & 0x1f] = val;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
dev->hwm_regs[dev->hwm_index] = val & 0x8b;
|
||||
break;
|
||||
|
||||
case 0x43:
|
||||
dev->hwm_regs[dev->hwm_index] = val;
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
dev->hwm_regs[dev->hwm_index] = val & 0x3f;
|
||||
break;
|
||||
|
||||
case 0x46:
|
||||
dev->hwm_regs[dev->hwm_index] = val & 0x80;
|
||||
if(val & 0x80)
|
||||
dev->hwm_regs[dev->hwm_index] &= 0x10;
|
||||
break;
|
||||
|
||||
case 0x47:
|
||||
dev->hwm_regs[dev->hwm_index] = val & 0x3f;
|
||||
break;
|
||||
|
||||
case 0x48: /* Serial Bus Address */
|
||||
dev->hwm_regs[dev->hwm_index] = val & 0x7f;
|
||||
break;
|
||||
|
||||
case 0x49:
|
||||
dev->hwm_regs[dev->hwm_index] = val & 1;
|
||||
break;
|
||||
|
||||
case 0x4a:
|
||||
dev->hwm_regs[dev->hwm_index] = val;
|
||||
break;
|
||||
|
||||
case 0x4b:
|
||||
dev->hwm_regs[dev->hwm_index] = val & 0xfc;
|
||||
break;
|
||||
|
||||
case 0x4c:
|
||||
dev->hwm_regs[dev->hwm_index] = val & 0x5c;
|
||||
break;
|
||||
|
||||
case 0x4d:
|
||||
dev->hwm_regs[dev->hwm_index] = val & 0xbf;
|
||||
break;
|
||||
|
||||
case 0x4e:
|
||||
dev->hwm_regs[dev->hwm_index] = val;
|
||||
break;
|
||||
|
||||
case 0x56:
|
||||
dev->hwm_regs[dev->hwm_index] = val;
|
||||
break;
|
||||
|
||||
case 0x57:
|
||||
dev->hwm_regs[dev->hwm_index] = val & 0xbf;
|
||||
break;
|
||||
|
||||
case 0x59:
|
||||
dev->hwm_regs[dev->hwm_index] = val & 0x70;
|
||||
break;
|
||||
|
||||
case 0x5a ... 0x5b:
|
||||
dev->hwm_regs[dev->hwm_index] = val;
|
||||
break;
|
||||
|
||||
case 0x5c:
|
||||
dev->hwm_regs[dev->hwm_index] = val & 0x77;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
w83627hf_hwm_read(uint16_t addr, void *priv)
|
||||
{
|
||||
w83627hf_t *dev = (w83627hf_t *)priv;
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case 0x295:
|
||||
return dev->hwm_index;
|
||||
|
||||
case 0x296:
|
||||
switch(dev->hwm_index)
|
||||
{
|
||||
case 0x20 ... 0x3f:
|
||||
case 0x60 ... 0x7f:
|
||||
switch(dev->hwm_index & 0x1f)
|
||||
{
|
||||
case 0x00: /* VCOREA */
|
||||
return hwm_get_vcore() + 0x78;
|
||||
|
||||
case 0x01: /* VCOREB */
|
||||
return vcoreb_voltage;
|
||||
|
||||
case 0x02: /* +3.3V */
|
||||
return 0xd0;
|
||||
|
||||
case 0x03: /* +5V */
|
||||
return 0xb9;
|
||||
|
||||
case 0x04: /* +12V */
|
||||
return 0xc4;
|
||||
|
||||
case 0x05: /* -12V */
|
||||
return 0x23;
|
||||
|
||||
case 0x06: /* -5V */
|
||||
return 0x34;
|
||||
|
||||
case 0x08: /* Fan 1 */
|
||||
return fan1_rpm;
|
||||
|
||||
case 0x09: /* Fan 2 */
|
||||
return fan2_rpm;
|
||||
|
||||
case 0x0a: /* Fan 3 */
|
||||
return fan3_rpm;
|
||||
|
||||
case 0x0b ... 0x1f:
|
||||
return dev->hwm_regs[dev->hwm_index & 0x1f];
|
||||
}
|
||||
|
||||
case 0x4f:
|
||||
if(dev->hwm_regs[0x4e] & 0x80)
|
||||
return 0x5c;
|
||||
else
|
||||
return 0xa3;
|
||||
|
||||
case 0x40 ... 0x4e:
|
||||
case 0x50 ... 0x5c:
|
||||
return dev->hwm_regs[dev->hwm_index];
|
||||
|
||||
default:
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w83627hf_fdc_write(uint16_t cur_reg, uint8_t val, w83627hf_t *dev)
|
||||
{
|
||||
|
||||
fdc_remove(dev->fdc_controller);
|
||||
|
||||
switch(cur_reg)
|
||||
{
|
||||
case 0x30:
|
||||
dev->dev_regs[0][cur_reg] = val & 1;
|
||||
break;
|
||||
|
||||
case 0x60 ... 0x61:
|
||||
dev->dev_regs[0][cur_reg] = val;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
dev->dev_regs[0][cur_reg] = val & 0x0f;
|
||||
break;
|
||||
|
||||
case 0x74:
|
||||
dev->dev_regs[0][cur_reg] = val & 7;
|
||||
break;
|
||||
|
||||
case 0xf0:
|
||||
dev->dev_regs[0][cur_reg] = val;
|
||||
break;
|
||||
|
||||
case 0xf1:
|
||||
dev->dev_regs[0][cur_reg] = val;
|
||||
fdc_update_boot_drive(dev->fdc_controller, (val & 0xc0) >> 6);
|
||||
|
||||
if(val & 2)
|
||||
fdc_writeprotect(dev->fdc_controller);
|
||||
|
||||
fdc_set_swwp(dev->fdc_controller, val & 1);
|
||||
break;
|
||||
|
||||
case 0xf2:
|
||||
dev->dev_regs[0][cur_reg] = val;
|
||||
break;
|
||||
|
||||
case 0xf4:
|
||||
case 0xf5:
|
||||
dev->dev_regs[0][cur_reg] = val & 0x5b;
|
||||
fdc_update_drvrate(dev->fdc_controller, cur_reg & 1, (val & 0x18) >> 3);
|
||||
break;
|
||||
}
|
||||
|
||||
if(dev->dev_regs[0][0x30] & 1)
|
||||
{
|
||||
fdc_set_irq(dev->fdc_controller, dev->dev_regs[0][0x70]);
|
||||
fdc_set_dma_ch(dev->fdc_controller, dev->dev_regs[0][0x74]);
|
||||
fdc_set_base(dev->fdc_controller, (dev->dev_regs[0][0x60] << 8) | (dev->dev_regs[0][0x61]));
|
||||
|
||||
w83627hf_log("W83627HF-FDC: BASE: %04x IRQ: %d DMA: %d\n", (dev->dev_regs[0][0x60] << 8) | (dev->dev_regs[0][0x61]), dev->dev_regs[0][0x70], dev->dev_regs[0][0x74]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w83627hf_lpt_write(uint16_t cur_reg, uint8_t val, w83627hf_t *dev)
|
||||
{
|
||||
lpt1_remove();
|
||||
|
||||
switch(cur_reg)
|
||||
{
|
||||
case 0x30:
|
||||
dev->dev_regs[1][cur_reg] = val & 1;
|
||||
break;
|
||||
|
||||
case 0x60 ... 0x61:
|
||||
dev->dev_regs[1][cur_reg] = val;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
dev->dev_regs[1][cur_reg] = val & 0x0f;
|
||||
break;
|
||||
|
||||
case 0xf0:
|
||||
dev->dev_regs[1][cur_reg] = val & 0x7f;
|
||||
break;
|
||||
}
|
||||
|
||||
if(dev->dev_regs[1][0x30] & 1)
|
||||
{
|
||||
lpt1_init((dev->dev_regs[1][0x60] << 8) | (dev->dev_regs[1][0x61]));
|
||||
lpt1_irq(dev->dev_regs[1][0x70]);
|
||||
w83627hf_log("W83627HF-LPT: BASE: %04x IRQ: %d\n", (dev->dev_regs[1][0x60] << 8) | (dev->dev_regs[1][0x61]), dev->dev_regs[1][0x70]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w83627hf_uart_write(int uart, uint16_t cur_reg, uint8_t val, w83627hf_t *dev)
|
||||
{
|
||||
double uart_clock = 24000000.0 / 13.0;
|
||||
|
||||
serial_remove(dev->uart[uart]);
|
||||
|
||||
switch(cur_reg)
|
||||
{
|
||||
case 0x30:
|
||||
dev->dev_regs[2 + uart][cur_reg] = val & 1;
|
||||
break;
|
||||
|
||||
case 0x60 ... 0x61:
|
||||
dev->dev_regs[2 + uart][cur_reg] = val;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
dev->dev_regs[2 + uart][cur_reg] = val & 0x0f;
|
||||
break;
|
||||
|
||||
case 0xf0:
|
||||
dev->dev_regs[2 + uart][cur_reg] = val & 3;
|
||||
switch(val & 3)
|
||||
{
|
||||
case 0:
|
||||
uart_clock = 24000000.0 / 13.0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
uart_clock = 24000000.0 / 12.0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
uart_clock = 24000000.0 / 1.625;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
uart_clock = 24000000.0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xf1:
|
||||
if(uart)
|
||||
dev->dev_regs[2 + uart][cur_reg] = val & 0x7f;
|
||||
break;
|
||||
}
|
||||
|
||||
if(dev->dev_regs[2 + uart][0x30] & 1)
|
||||
{
|
||||
serial_setup(dev->uart[uart], (dev->dev_regs[2 + uart][0x60] << 8) | (dev->dev_regs[2 + uart][0x61]), dev->dev_regs[2 + uart][0x70]);
|
||||
serial_set_clock_src(dev->uart[uart], uart_clock);
|
||||
w83627hf_log("W83627HF-UART%s: BASE: %04x IRQ: %d\n", uart ? "B" : "A", (dev->dev_regs[2 + uart][0x60] << 8) | (dev->dev_regs[2 + uart][0x61]), dev->dev_regs[2 + uart][0x70]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w83627hf_kbc_write(uint16_t cur_reg, uint8_t val, w83627hf_t *dev)
|
||||
{
|
||||
switch(cur_reg)
|
||||
{
|
||||
case 0x30:
|
||||
dev->dev_regs[5][cur_reg] = val & 1;
|
||||
break;
|
||||
|
||||
case 0x60 ... 0x61: /* See Notes on init */
|
||||
dev->dev_regs[5][cur_reg] = val;
|
||||
break;
|
||||
|
||||
case 0x62 ... 0x63: /* See Notes on init */
|
||||
dev->dev_regs[5][cur_reg] = val;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
dev->dev_regs[5][cur_reg] = val & 0x0f;
|
||||
break;
|
||||
|
||||
case 0x72:
|
||||
dev->dev_regs[5][cur_reg] = val & 0x0f;
|
||||
break;
|
||||
|
||||
case 0xf0:
|
||||
dev->dev_regs[5][cur_reg] = val & 0xc7;
|
||||
break;
|
||||
}
|
||||
|
||||
if(dev->dev_regs[5][0x30] & 1)
|
||||
{
|
||||
/* We don't disable Port 92h as intended because the BIOSes never enable it back, causing issues. */
|
||||
port_92_set_features(dev->port_92, !!(dev->dev_regs[5][0xf0] & 1), !!(dev->dev_regs[5][0xf0] & 2));
|
||||
w83627hf_log("W83627HF-PORT92: FASTA20: %d FASTRESET: %d\n", !!(dev->dev_regs[5][0xf0] & 2), !!(dev->dev_regs[5][0xf0] & 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w83627hf_cir_write(uint16_t cur_reg, uint8_t val, w83627hf_t *dev)
|
||||
{
|
||||
/* Unimplemented Functionality */
|
||||
switch(cur_reg)
|
||||
{
|
||||
case 0x30:
|
||||
dev->dev_regs[6][cur_reg] = val & 1;
|
||||
break;
|
||||
|
||||
case 0x60 ... 0x61:
|
||||
dev->dev_regs[6][cur_reg] = val;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
dev->dev_regs[6][cur_reg] = val & 0x0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w83627hf_gameport_midi_gpio1_write(uint16_t cur_reg, uint8_t val, w83627hf_t *dev)
|
||||
{
|
||||
switch(cur_reg)
|
||||
{
|
||||
case 0x30:
|
||||
dev->dev_regs[7][cur_reg] = val & 7;
|
||||
break;
|
||||
|
||||
case 0x60 ... 0x63:
|
||||
dev->dev_regs[7][cur_reg] = val;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
dev->dev_regs[7][cur_reg] = val & 0x0f;
|
||||
break;
|
||||
|
||||
case 0xf0 ... 0xf2:
|
||||
dev->dev_regs[7][cur_reg] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w83627hf_watchdog_timer_gpio2_write(uint16_t cur_reg, uint8_t val, w83627hf_t *dev)
|
||||
{
|
||||
switch(cur_reg)
|
||||
{
|
||||
case 0x30:
|
||||
dev->dev_regs[8][cur_reg] = val & 1;
|
||||
break;
|
||||
|
||||
case 0xf0 ... 0xf2:
|
||||
dev->dev_regs[8][cur_reg] = val;
|
||||
break;
|
||||
|
||||
case 0xf5:
|
||||
dev->dev_regs[8][cur_reg] = val & 0xcc;
|
||||
break;
|
||||
|
||||
case 0xf6 ... 0xf7:
|
||||
dev->dev_regs[8][cur_reg] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w83627hf_gpio3_vsb_write(uint16_t cur_reg, uint8_t val, w83627hf_t *dev)
|
||||
{
|
||||
switch(cur_reg)
|
||||
{
|
||||
case 0x30:
|
||||
dev->dev_regs[9][cur_reg] = val & 1;
|
||||
break;
|
||||
|
||||
case 0xf0 ... 0xf2:
|
||||
dev->dev_regs[9][cur_reg] = val;
|
||||
break;
|
||||
|
||||
case 0xf3:
|
||||
dev->dev_regs[9][cur_reg] = val & 0xc0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w83627hf_acpi_write(uint16_t cur_reg, uint8_t val, w83627hf_t *dev)
|
||||
{
|
||||
switch(cur_reg)
|
||||
{
|
||||
case 0x30:
|
||||
dev->dev_regs[0x0a][cur_reg] = val & 1;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
dev->dev_regs[0x0a][cur_reg] = val & 0x0f;
|
||||
break;
|
||||
|
||||
case 0xe0:
|
||||
dev->dev_regs[0x0a][cur_reg] = val & 0xc0;
|
||||
break;
|
||||
|
||||
case 0xe1 ... 0xe2:
|
||||
dev->dev_regs[0x0a][cur_reg] = val;
|
||||
break;
|
||||
|
||||
case 0xe4:
|
||||
dev->dev_regs[0x0a][cur_reg] = val & 0xfc;
|
||||
break;
|
||||
|
||||
case 0xe5 ... 0xe6:
|
||||
dev->dev_regs[0x0a][cur_reg] = val & 0x7f;
|
||||
|
||||
if(cur_reg == 0xe6)
|
||||
if(val & 0x40)
|
||||
dev->hwm_regs[0x42] &= 0x10;
|
||||
break;
|
||||
|
||||
case 0xe7:
|
||||
dev->dev_regs[0x0a][cur_reg] = val & 0x0f;
|
||||
break;
|
||||
|
||||
case 0xf0:
|
||||
dev->dev_regs[0x0a][cur_reg] = val;
|
||||
break;
|
||||
|
||||
case 0xf1:
|
||||
dev->dev_regs[0x0a][cur_reg] = val & 0xef;
|
||||
break;
|
||||
|
||||
case 0xf3 ... 0xf4:
|
||||
dev->dev_regs[0x0a][cur_reg] &= val & 0x3f;
|
||||
break;
|
||||
|
||||
case 0xf5:
|
||||
case 0xf7:
|
||||
dev->dev_regs[0x0a][cur_reg] = val & 0x3f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w83627hf_hwm_lpc_write(uint16_t cur_reg, uint8_t val, w83627hf_t *dev)
|
||||
{
|
||||
switch(cur_reg)
|
||||
{
|
||||
case 0x30:
|
||||
dev->dev_regs[0x0b][cur_reg] = val & 1;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
dev->dev_regs[0x0b][cur_reg] = val & 0x0f;
|
||||
break;
|
||||
|
||||
case 0xf0:
|
||||
dev->dev_regs[0x0b][cur_reg] = val & 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
w83627hf_hwm_reset(w83627hf_t *dev)
|
||||
{
|
||||
/* W83627HF Hardware Monitor */
|
||||
dev->hwm_regs[0x40] = 1;
|
||||
dev->hwm_regs[0x47] = 0xa0;
|
||||
dev->hwm_regs[0x48] = 0x2d;
|
||||
dev->hwm_regs[0x49] = 1;
|
||||
dev->hwm_regs[0x4a] = 1;
|
||||
dev->hwm_regs[0x4b] = 0x44;
|
||||
dev->hwm_regs[0x4d] = 0x15;
|
||||
dev->hwm_regs[0x4e] = 0x80;
|
||||
dev->hwm_regs[0x57] = 0x80;
|
||||
dev->hwm_regs[0x58] = 0x21;
|
||||
dev->hwm_regs[0x59] = 0x70;
|
||||
dev->hwm_regs[0x5a] = 0xff;
|
||||
dev->hwm_regs[0x5b] = 0xff;
|
||||
dev->hwm_regs[0x5c] = 0x11;
|
||||
}
|
||||
|
||||
static void
|
||||
w83627hf_reset(void *priv)
|
||||
{
|
||||
w83627hf_t *dev = (w83627hf_t *)priv;
|
||||
memset(dev->regs, 0, sizeof(dev->regs));
|
||||
dev->cfg_unlocked = 0;
|
||||
|
||||
/* Proper W83627HF Registers */
|
||||
dev->regs[0x20] = 0x52;
|
||||
dev->regs[0x21] = 0x17;
|
||||
|
||||
/* FDC Registers */
|
||||
dev->dev_regs[0][0x30] = 1;
|
||||
dev->dev_regs[0][0x60] = 3;
|
||||
dev->dev_regs[0][0x61] = 0xf0;
|
||||
dev->dev_regs[0][0x70] = 6;
|
||||
dev->dev_regs[0][0x74] = 2;
|
||||
dev->dev_regs[0][0xf0] = 0x0e;
|
||||
dev->dev_regs[0][0xf2] = 0xff;
|
||||
fdc_reset(dev->fdc_controller);
|
||||
w83627hf_fdc_write(0, 0, dev);
|
||||
|
||||
/* LPT Registers */
|
||||
dev->dev_regs[1][0x30] = 1;
|
||||
dev->dev_regs[1][0x60] = 3;
|
||||
dev->dev_regs[1][0x61] = 0x78;
|
||||
dev->dev_regs[1][0x70] = 7;
|
||||
dev->dev_regs[1][0x74] = 4;
|
||||
dev->dev_regs[1][0xf0] = 0x3f;
|
||||
w83627hf_lpt_write(0, 0, dev);
|
||||
|
||||
/* UART A Registers */
|
||||
dev->dev_regs[2][0x30] = 1;
|
||||
dev->dev_regs[2][0x60] = 3;
|
||||
dev->dev_regs[2][0x61] = 0xf8;
|
||||
dev->dev_regs[2][0x70] = 4;
|
||||
w83627hf_uart_write(0, 0, 0, dev);
|
||||
|
||||
/* UART B Registers */
|
||||
dev->dev_regs[3][0x30] = 1;
|
||||
dev->dev_regs[3][0x60] = 2;
|
||||
dev->dev_regs[3][0x61] = 0xf8;
|
||||
dev->dev_regs[3][0x70] = 3;
|
||||
w83627hf_uart_write(0, 0, 0, dev);
|
||||
|
||||
/* Keyboard Controller */
|
||||
dev->dev_regs[5][0x30] = 1;
|
||||
dev->dev_regs[5][0x61] = 0x60;
|
||||
dev->dev_regs[5][0x63] = 0x64;
|
||||
dev->dev_regs[5][0x70] = 1;
|
||||
dev->dev_regs[5][0x72] = 0x0c;
|
||||
dev->dev_regs[5][0xf0] = 0x80;
|
||||
w83627hf_kbc_write(0, 0, dev);
|
||||
|
||||
/* CIR */
|
||||
dev->dev_regs[6][0x30] = 1;
|
||||
w83627hf_cir_write(0, 0, dev);
|
||||
|
||||
/* Gameport, MIDI port and GPIO1 */
|
||||
dev->dev_regs[7][0x60] = 2;
|
||||
dev->dev_regs[7][0x61] = 1;
|
||||
dev->dev_regs[7][0x62] = 3;
|
||||
dev->dev_regs[7][0x63] = 0x30;
|
||||
dev->dev_regs[7][0x70] = 9;
|
||||
dev->dev_regs[7][0xf0] = 0xff;
|
||||
|
||||
/* GPIO3, VSB */
|
||||
dev->dev_regs[9][0xf0] = 0xff;
|
||||
|
||||
/* W83627HF Hardware Monitor */
|
||||
if(dev->has_hwm)
|
||||
w83627hf_hwm_reset(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
w83627hf_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
w83627hf_t *dev = (w83627hf_t *)priv;
|
||||
|
||||
switch(addr & 0x0f)
|
||||
{
|
||||
case 0x0e:
|
||||
if(!dev->cfg_unlocked)
|
||||
{
|
||||
dev->cfg_unlocked = (val == 0x87) && (dev->index == 0x87);
|
||||
dev->index = val;
|
||||
}
|
||||
else dev->index = val;
|
||||
break;
|
||||
|
||||
case 0x0f:
|
||||
if(dev->cfg_unlocked)
|
||||
switch(dev->index)
|
||||
{
|
||||
case 0x02: /* LDN */
|
||||
if(val & 1)
|
||||
w83627hf_reset(dev);
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
dev->regs[dev->index] = val;
|
||||
break;
|
||||
|
||||
case 0x22: /* Manual Power Down */
|
||||
dev->regs[dev->index] = val & 0x7f;
|
||||
break;
|
||||
|
||||
case 0x23: /* Full Power Down */
|
||||
dev->regs[dev->index] = val & 1;
|
||||
break;
|
||||
|
||||
case 0x24:
|
||||
dev->regs[dev->index] = val & 0xca;
|
||||
break;
|
||||
|
||||
case 0x25:
|
||||
dev->regs[dev->index] = val & 0x39;
|
||||
break;
|
||||
|
||||
case 0x26:
|
||||
dev->regs[dev->index] = val & 0xef;
|
||||
break;
|
||||
|
||||
case 0x28:
|
||||
dev->regs[dev->index] = val & 7;
|
||||
break;
|
||||
|
||||
case 0x29:
|
||||
dev->regs[dev->index] = val & 0xfc;
|
||||
break;
|
||||
|
||||
case 0x2a:
|
||||
case 0x2b:
|
||||
dev->regs[dev->index] = val;
|
||||
break;
|
||||
|
||||
case 0x30: /* Device Specific Registers */
|
||||
case 0x60 ... 0x63:
|
||||
case 0x70: case 0x72:case 0x74:
|
||||
case 0xe0 ... 0xe7:
|
||||
case 0xf0 ... 0xf6:
|
||||
switch(dev->regs[7])
|
||||
{
|
||||
case 0: /* FDC */
|
||||
w83627hf_fdc_write(dev->index, val, dev);
|
||||
break;
|
||||
|
||||
case 1: /* LPT */
|
||||
w83627hf_lpt_write(dev->index, val, dev);
|
||||
break;
|
||||
|
||||
case 2: /* UART A */
|
||||
case 3: /* UART B */
|
||||
w83627hf_uart_write(dev->regs[7] & 1, dev->index, val, dev);
|
||||
break;
|
||||
|
||||
case 5: /* KBC */
|
||||
w83627hf_kbc_write(dev->index, val, dev);
|
||||
break;
|
||||
|
||||
case 6: /* CIR */
|
||||
w83627hf_cir_write(dev->index, val, dev);
|
||||
break;
|
||||
|
||||
case 7: /* GAMEPORT, MIDI & GPIO1 */
|
||||
w83627hf_gameport_midi_gpio1_write(dev->index, val, dev);
|
||||
break;
|
||||
|
||||
case 8: /* WATCHDOG TIMER & GPIO2 */
|
||||
w83627hf_watchdog_timer_gpio2_write(dev->index, val, dev);
|
||||
break;
|
||||
|
||||
case 9: /* GPIO3 & VSB */
|
||||
w83627hf_gpio3_vsb_write(dev->index, val, dev);
|
||||
break;
|
||||
|
||||
case 0x0a: /* ACPI */
|
||||
w83627hf_acpi_write(dev->index, val, dev);
|
||||
break;
|
||||
|
||||
case 0x0b: /* HWM LPC */
|
||||
w83627hf_hwm_lpc_write(dev->index, val, dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
w83627hf_log("W83627HF: Writings to unknown LDN: %02x\n", dev->regs[7]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
w83627hf_read(uint16_t addr, void *priv)
|
||||
{
|
||||
w83627hf_t *dev = (w83627hf_t *)priv;
|
||||
|
||||
if((dev->index >= 0x00) && (dev->index <= 0x2f))
|
||||
return dev->regs[dev->index];
|
||||
else if((dev->index >= 0x30) && (dev->index <= 0xff) && (dev->regs[7] >= 0) && (dev->regs[7] <= 0x0b))
|
||||
return dev->dev_regs[dev->regs[7]][dev->index];
|
||||
else
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
w83627hf_close(void *priv)
|
||||
{
|
||||
w83627hf_t *dev = (w83627hf_t *)priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
w83627hf_init(const device_t *info)
|
||||
{
|
||||
w83627hf_t *dev = (w83627hf_t *)malloc(sizeof(w83627hf_t));
|
||||
memset(dev, 0, sizeof(w83627hf_t));
|
||||
|
||||
/* Knock out the Hardware Monitor if needed(Mainly for ASUS TUSL2-C) */
|
||||
dev->has_hwm = info->local;
|
||||
|
||||
/* I/O Ports */
|
||||
io_sethandler(0x002e, 2, w83627hf_read, NULL, NULL, w83627hf_write, NULL, NULL, dev);
|
||||
io_sethandler(0x004e, 2, w83627hf_read, NULL, NULL, w83627hf_write, NULL, NULL, dev);
|
||||
|
||||
if(dev->has_hwm)
|
||||
io_sethandler(0x0295, 2, w83627hf_hwm_read, NULL, NULL, w83627hf_hwm_write, NULL, NULL, dev);
|
||||
|
||||
/* Floppy Disk Controller */
|
||||
dev->fdc_controller = device_add(&fdc_at_smc_device);
|
||||
|
||||
/* Hardware Monitor */
|
||||
fan1_rpm = fan2_rpm = fan3_rpm = vcorea_voltage = vcoreb_voltage = 0;
|
||||
|
||||
/* Keyboard Controller (Based on AMIKEY-2) */
|
||||
/* Note: The base addresses and IRQ's of the Keyboard & PS/2 Mouse are remappable. Due to 86Box limitations we can't do that just yet */
|
||||
device_add(&keyboard_ps2_ami_pci_device);
|
||||
|
||||
/* Port 92h */
|
||||
dev->port_92 = device_add(&port_92_device);
|
||||
|
||||
/* UART */
|
||||
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
||||
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t w83627hf_device = {
|
||||
.name = "Winbond W83627HF",
|
||||
.internal_name = "w83627hf",
|
||||
.flags = 0,
|
||||
.local = 1,
|
||||
.init = w83627hf_init,
|
||||
.close = w83627hf_close,
|
||||
.reset = w83627hf_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t w83627hf_no_hwm_device = {
|
||||
.name = "Winbond W83627HF with no Hardware Monitor",
|
||||
.internal_name = "w83627hf_nohwm",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = w83627hf_init,
|
||||
.close = w83627hf_close,
|
||||
.reset = w83627hf_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
@@ -561,7 +561,8 @@ CHIPSETOBJ := 82c100.o acc2168.o \
|
||||
wd76c10.o vl82c480.o \
|
||||
umc_8886.o umc_hb4.o \
|
||||
via_vt82c49x.o via_vt82c505.o via_apollo.o via_pipc.o \
|
||||
sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o sis_5511.o sis_5571.o
|
||||
sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o sis_5511.o sis_5571.o \
|
||||
intel_ich2.o intel_815ep.o
|
||||
|
||||
MCHOBJ := machine.o machine_table.o \
|
||||
m_xt.o m_xt_compaq.o \
|
||||
@@ -579,11 +580,11 @@ MCHOBJ := machine.o machine_table.o \
|
||||
m_at_286_386sx.o m_at_386dx_486.o \
|
||||
m_at_socket4.o m_at_socket5.o m_at_socket7_3v.o m_at_socket7.o m_at_sockets7.o \
|
||||
m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o \
|
||||
m_at_misc.o
|
||||
m_at_misc.o m_at_ich2.o
|
||||
|
||||
ifeq ($(NEW_KBC), y)
|
||||
DEVOBJ := bugger.o cartridge.o cassette.o hasp.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 \
|
||||
DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_nsc366.o hwm_vt82c686.o \
|
||||
ibm_5161.o intel_ich2_gpio.o intel_ich2_trap.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \
|
||||
clock_ics9xxx.o isapnp.o \
|
||||
i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \
|
||||
keyboard.o \
|
||||
@@ -591,10 +592,11 @@ DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hw
|
||||
mouse.o \
|
||||
mouse_bus.o \
|
||||
mouse_serial.o mouse_ps2.o \
|
||||
phoenix_486_jumper.o
|
||||
phoenix_486_jumper.o \
|
||||
tco.o
|
||||
else
|
||||
DEVOBJ := bugger.o cartridge.o cassette.o hasp.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 \
|
||||
DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_nsc366.o hwm_vt82c686.o \
|
||||
ibm_5161.o intel_ich2_gpio.o intel_ich2_trap.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \
|
||||
clock_ics9xxx.o isapnp.o \
|
||||
i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \
|
||||
keyboard.o \
|
||||
@@ -602,7 +604,8 @@ DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hw
|
||||
mouse.o \
|
||||
mouse_bus.o \
|
||||
mouse_serial.o mouse_ps2.o \
|
||||
phoenix_486_jumper.o
|
||||
phoenix_486_jumper.o \
|
||||
tco.o
|
||||
endif
|
||||
|
||||
SIOOBJ := sio_acc3221.o sio_ali5123.o \
|
||||
@@ -611,10 +614,11 @@ SIOOBJ := sio_acc3221.o sio_ali5123.o \
|
||||
sio_it8661f.o \
|
||||
sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87310.o sio_pc87311.o sio_pc87332.o \
|
||||
sio_prime3b.o sio_prime3c.o \
|
||||
sio_w83787f.o \
|
||||
sio_w83627hf.o sio_w83787f.o \
|
||||
sio_w83877f.o sio_w83977f.o \
|
||||
sio_um8669f.o \
|
||||
sio_vt82c686.o
|
||||
sio_vt82c686.o \
|
||||
sio_nsc366.o
|
||||
|
||||
FDDOBJ := fdd.o fdc.o fdc_magitronic.o fdc_pii15xb.o \
|
||||
fdi2raw.o \
|
||||
|
||||
Reference in New Issue
Block a user