Merge pull request #1140 from richardg867/master

Unnamed big I2C rework / clock stuff PR
This commit is contained in:
Miran Grča
2020-12-03 06:22:24 +01:00
committed by GitHub
28 changed files with 1475 additions and 459 deletions

View File

@@ -1224,13 +1224,21 @@ acpi_reset(void *priv)
- Bit 4: 80-conductor cable on primary IDE channel (active low)
- Bit 3: 80-conductor cable on secondary IDE channel (active low)
- Bit 2: password cleared (active low)
ASUS P3V4X:
- Bit 15: 80-conductor cable on secondary IDE channel (active low)
- Bit 5: 80-conductor cable on primary IDE channel (active low)
AEWIN WCF-681:
- Bit 3: 80-conductor cable on primary IDE channel (active low)
- Bit 2: 80-conductor cable on secondary IDE channel (active low)
Acorp 6VIA85X:
ASUS CUV4X-LS:
- Bit 2: 80-conductor cable on secondary IDE channel (active low)
- Bit 1: 80-conductor cable on primary IDE channel (active low)
Acorp 6VIA90AP:
- Bit 3: 80-conductor cable on secondary IDE channel (active low)
- Bit 1: 80-conductor cable on primary IDE channel (active low) */
dev->regs.gpi_val = !strcmp(machines[machine].internal_name, "wcf681") ? 0xffffffe3 : 0xffffffe5;
dev->regs.gpi_val = 0xffff7fc1;
if (!strcmp(machines[machine].internal_name, "ficva503a"))
dev->regs.gpi_val |= 0x00000004;
}
acpi_rtc_status = 0;

View File

@@ -25,6 +25,7 @@
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include <86box/smram.h>
#include <86box/io.h>
@@ -35,18 +36,19 @@
#include <86box/chipset.h>
#include <86box/spd.h>
#define VIA_585 0x05850000
#define VIA_595 0x05950000
#define VIA_597 0x05970100
#define VIA_598 0x05980000
#define VIA_691 0x06910000
#define VIA_585 0x05850000
#define VIA_595 0x05950000
#define VIA_597 0x05970100
#define VIA_598 0x05980000
#define VIA_691 0x06910000
#define VIA_693A 0x06914400
#define VIA_694 0x0691c200
#define VIA_694 0x0691c200
#define VIA_8601 0x86010500
typedef struct via_apollo_t
{
uint32_t id;
uint8_t drb_unit;
uint8_t pci_conf[256];
smram_t *smram;
@@ -98,10 +100,10 @@ via_apollo_setup(via_apollo_t *dev)
dev->pci_conf[0x04] = 6;
dev->pci_conf[0x05] = 0;
if ((dev->id >= VIA_585) || (dev->id < VIA_597))
if ((dev->id >= VIA_585) || (dev->id < VIA_597))
dev->pci_conf[0x06] = 0xa0;
else
dev->pci_conf[0x06] = 0x90;
else
dev->pci_conf[0x06] = 0x90;
dev->pci_conf[0x07] = 0x02;
@@ -114,31 +116,30 @@ via_apollo_setup(via_apollo_t *dev)
dev->pci_conf[0x0e] = 0;
dev->pci_conf[0x0f] = 0;
if (dev->id >= VIA_597)
{
dev->pci_conf[0x10] = 0x08;
dev->pci_conf[0x34] = 0xa0;
}
if (dev->id >= VIA_597) {
dev->pci_conf[0x10] = 0x08;
dev->pci_conf[0x34] = 0xa0;
}
if ((dev->id >= VIA_585) || (dev->id < VIA_597))
if ((dev->id >= VIA_585) || (dev->id < VIA_597))
dev->pci_conf[0x52] = 0x02;
else if (dev->id >= VIA_694)
else if (dev->id >= VIA_694)
dev->pci_conf[0x52] = (dev->id == VIA_694) ? 0x90 : 0x10;
if(dev->id >= VIA_693A)
if (dev->id >= VIA_693A)
dev->pci_conf[0x53] = 0x10;
if (dev->id == VIA_691) {
dev->pci_conf[0x56] = 0x01;
dev->pci_conf[0x56] = 0x01;
dev->pci_conf[0x57] = 0x01;
}
if (dev->id >= VIA_693A)
dev->pci_conf[0x58] = 0x40;
else if (dev->id >= VIA_585)
dev->pci_conf[0x58] = 0x40;
else if (dev->id >= VIA_585)
dev->pci_conf[0x58] = 0x05;
if ((dev->id >= VIA_585) || (dev->id < VIA_597))
if ((dev->id >= VIA_585) || (dev->id < VIA_597))
dev->pci_conf[0x59] = 0x02;
dev->pci_conf[0x5a] = 0x01;
@@ -149,33 +150,46 @@ via_apollo_setup(via_apollo_t *dev)
dev->pci_conf[0x5f] = 0x01;
dev->pci_conf[0x64] = ((dev->id >= VIA_585) || (dev->id < VIA_597)) ? 0xab : 0xec;
if (dev->id >= VIA_597)
{
dev->pci_conf[0x65] = 0xec;
dev->pci_conf[0x66] = 0xec;
}
if (dev->id >= VIA_691)
dev->pci_conf[0x67] = 0xec; /* DRAM Timing for Banks 6,7. */
if (dev->id >= VIA_597) {
dev->pci_conf[0x65] = 0xec;
dev->pci_conf[0x66] = 0xec;
}
if (dev->id >= VIA_691)
dev->pci_conf[0x67] = 0xec; /* DRAM Timing for Banks 6, 7 */
if (dev->id >= VIA_693A) {
if (cpu_busspeed < 95000000)
dev->pci_conf[0x68] |= 0x00; /* 66 MHz */
else if (cpu_busspeed < 124000000)
dev->pci_conf[0x68] |= 0x01; /* 100 MHz */
else
dev->pci_conf[0x68] |= (dev->id == VIA_8601) ? 0x03 : 0x02; /* 133 MHz */
} else if (dev->id >= VIA_598) {
if (cpu_busspeed < 75000000)
dev->pci_conf[0x68] |= 0x00; /* 66 MHz */
else if (cpu_busspeed < 100000000)
dev->pci_conf[0x68] |= (dev->id >= VIA_691) ? 0x00 : 0x03; /* 75/83 MHz (66 MHz on 691) */
else
dev->pci_conf[0x68] |= 0x01; /* 100 MHz */
}
dev->pci_conf[0x6b] = 0x01;
if(dev->id >= VIA_597)
{
dev->pci_conf[0xa0] = 0x02;
dev->pci_conf[0xa2] = 0x10;
dev->pci_conf[0xa4] = 0x03;
dev->pci_conf[0xa5] = 0x02;
dev->pci_conf[0xa7] = 0x07;
if (dev->id >= VIA_597) {
dev->pci_conf[0xa0] = 0x02;
dev->pci_conf[0xa2] = 0x10;
dev->pci_conf[0xa4] = 0x03;
dev->pci_conf[0xa5] = 0x02;
dev->pci_conf[0xa7] = 0x07;
if(dev->id == VIA_693A) {
dev->pci_conf[0xac] = 0x08;
dev->pci_conf[0xad] = 0x02;
if (dev->id == VIA_693A) {
dev->pci_conf[0xac] = 0x08;
dev->pci_conf[0xad] = 0x02;
}
if(dev->id == VIA_694) {
dev->pci_conf[0xb0] = 0x80; /* The datasheet refers it as 8xh */
dev->pci_conf[0xb1] = 0x63;
}
if (dev->id == VIA_694) {
dev->pci_conf[0xb0] = 0x80; /* The datasheet refers it as 8xh */
dev->pci_conf[0xb1] = 0x63;
}
}
}
@@ -291,10 +305,10 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x56: case 0x57: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: /* DRAM Row Ending Address */
if (dev->id >= VIA_691)
spd_write_drbs(dev->pci_conf, 0x5a, 0x56, 8);
if ((dev->id >= VIA_691) && (dev->id != VIA_8601))
spd_write_drbs(dev->pci_conf, 0x5a, 0x56, dev->drb_unit);
else if (addr >= 0x5a)
spd_write_drbs(dev->pci_conf, 0x5a, 0x5f, 8);
spd_write_drbs(dev->pci_conf, 0x5a, 0x5f, dev->drb_unit);
break;
case 0x58:
@@ -427,25 +441,21 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf[0x66] = val;
break;
case 0x68:
if(dev->id != VIA_595){
if (dev->id == VIA_597)
dev->pci_conf[0x68] = (dev->pci_conf[0x6b] & ~0xfe) | (val & 0xfe);
else if ((dev->id == VIA_598) || (dev->id == VIA_693A) || (dev->id == VIA_8601))
dev->pci_conf[0x68] = val;
else if (dev->id == VIA_694)
dev->pci_conf[0x68] = (dev->pci_conf[0x68] & ~0xdf) | (val & 0xdf);
else if (dev->id == VIA_585)
dev->pci_conf[0x68] = (dev->pci_conf[0x68] & ~0x08) | (val & 0x08);
else
dev->pci_conf[0x68] = (dev->pci_conf[0x6b] & ~0xfd) | (val & 0xfd);
break;
if (dev->id != VIA_595) {
if (dev->id == VIA_597)
dev->pci_conf[0x68] = (dev->pci_conf[0x68] & ~0xfe) | (val & 0xfe);
else if ((dev->id == VIA_693A) || (dev->id == VIA_694))
dev->pci_conf[0x68] = (dev->pci_conf[0x68] & ~0xdc) | (val & 0xdc);
else
dev->pci_conf[0x68] = (dev->pci_conf[0x68] & ~0xfc) | (val & 0xfc);
}
break;
case 0x69:
if((dev->id != VIA_585) || (dev->id != VIA_595)){
if ((dev->id == VIA_693A) || (dev->id < VIA_8601))
dev->pci_conf[0x69] = (dev->pci_conf[0x69] & ~0xfe) | (val & 0xfe);
else
dev->pci_conf[0x69] = val;
if ((dev->id != VIA_585) || (dev->id != VIA_595)){
if ((dev->id == VIA_693A) || (dev->id < VIA_8601))
dev->pci_conf[0x69] = (dev->pci_conf[0x69] & ~0xfe) | (val & 0xfe);
else
dev->pci_conf[0x69] = val;
}
break;
case 0x6b:
@@ -684,6 +694,13 @@ via_apollo_init(const device_t *info)
break;
}
if ((dev->id >= VIA_694) && (dev->id != VIA_8601))
dev->drb_unit = 16;
else if (dev->id >= VIA_597)
dev->drb_unit = 8;
else
dev->drb_unit = 4;
via_apollo_setup(dev);
via_apollo_reset(dev);

View File

@@ -171,7 +171,7 @@ pipc_reset_hard(void *priv)
if (dev->local <= VIA_PIPC_586B)
dev->ide_regs[0x40] = 0x04;
dev->ide_regs[0x41] = 0x02;
dev->ide_regs[0x41] = (dev->local <= VIA_PIPC_686A) ? 0x06 : 0x02;
dev->ide_regs[0x42] = 0x09;
dev->ide_regs[0x43] = (dev->local >= VIA_PIPC_686A) ? 0x0a : 0x3a;
dev->ide_regs[0x44] = 0x68;
@@ -400,7 +400,7 @@ pipc_read(int func, int addr, void *priv)
if (func > dev->max_func)
return ret;
else if (func == 0) { /* PCI-ISA bridge */
if ((addr >= 0x60) && (addr <= 0x6f)) {
if ((addr >= 0x60) && (addr <= 0x6f)) { /* DMA shadow registers */
c = (addr & 0x0e) >> 1;
if (addr & 0x01)
ret = (dma[c].ab & 0x0000ff00) >> 8;
@@ -411,19 +411,38 @@ pipc_read(int func, int addr, void *priv)
} else
ret = dev->pci_isa_regs[addr];
}
else if ((func == 1) && !(dev->pci_isa_regs[0x48] & 0x02)) /* IDE */
else if ((func == 1) && !(dev->pci_isa_regs[0x48] & 0x02)) { /* IDE */
ret = dev->ide_regs[addr];
if ((addr >= 0x50) && (addr <= 0x53)) { /* UDMA timing registers */
/* Set or clear bit 5 according to UDMA mode. Documentation is unclear, but a real
686B does set bit 5 when UDMA is enabled through the method specified in bit 7. */
c = 0x53 - addr;
if (ret & 0x80) /* bit 7 set = use bit 6 */
c = ret & 0x40;
else if (ide_drives[c]) /* bit 7 clear = use SET FEATURES mode */
c = (ide_drives[c]->mdma_mode & 0xf00) == 0x300;
else /* no drive here */
c = 0;
/* 586A/B datasheet claims bit 5 must be clear for UDMA, unlike later models where
it must be set, but the Windows driver doesn't care and always checks if it's set. */
if (c)
ret |= 0x20;
else
ret &= ~0x20;
}
}
else if ((func < pm_func) && !((func == 2) ? (dev->pci_isa_regs[0x48] & 0x04) : (dev->pci_isa_regs[0x85] & 0x10))) /* USB */
ret = dev->usb_regs[func - 2][addr];
else if (func == pm_func) { /* Power */
ret = dev->power_regs[addr];
if (addr == 0x42) {
ret &= ~0x10;
if (dev->nvr->regs[0x0d] & 0x80)
ret |= 0x10;
else
ret &= ~0x10;
}
}
else if ((func <= (pm_func + 2)) && !(dev->pci_isa_regs[0x85] & ((func == (pm_func + 1)) ? 0x04 : 0x08)) && 0) /* AC97 / MC97; temporarily disabled while unimplemented */
else if ((func <= (pm_func + 2)) && !(dev->pci_isa_regs[0x85] & ((func == (pm_func + 1)) ? 0x04 : 0x08))) /* AC97 / MC97 */
ret = dev->ac97_regs[func - pm_func - 1][addr];
pipc_log("PIPC: read(%d, %02X) = %02X\n", func, addr, ret);
@@ -667,31 +686,69 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x40:
if (dev->local <= VIA_PIPC_586B) {
dev->ide_regs[0x40] = val & 0x03;
dev->ide_regs[0x40] |= 0x04;
} else
if (dev->local <= VIA_PIPC_586B)
dev->ide_regs[0x40] = (val & 0x03) | 0x04;
else
dev->ide_regs[0x40] = val & 0x0f;
pipc_ide_handlers(dev);
break;
case 0x50: case 0x52:
if (dev->local <= VIA_PIPC_586B)
dev->ide_regs[addr] = val & 0xe3;
else if (dev->local <= VIA_PIPC_596B)
dev->ide_regs[addr] = val & 0xeb;
else if (dev->local <= VIA_PIPC_686A)
dev->ide_regs[addr] = val & 0xef;
case 0x41:
if (dev->local <= VIA_PIPC_686A)
dev->ide_regs[0x41] = val;
else
dev->ide_regs[addr] = val & 0xf7;
dev->ide_regs[0x41] = val & 0xf2;
break;
case 0x51: case 0x53:
if (dev->local <= VIA_PIPC_596B)
dev->ide_regs[addr] = val & 0xe3;
else if (dev->local <= VIA_PIPC_686A)
dev->ide_regs[addr] = val & 0xe7;
case 0x43:
if (dev->local <= VIA_PIPC_586A)
dev->ide_regs[0x43] = (val & 0x6f) | 0x10;
else if (dev->local <= VIA_PIPC_586B)
dev->ide_regs[0x43] = (val & 0xef) | 0x10;
else
dev->ide_regs[addr] = val & 0xf7;
dev->ide_regs[0x43] = val & 0x0f;
break;
case 0x44:
if (dev->local <= VIA_PIPC_586A)
dev->ide_regs[0x44] = val & 0x78;
else if (dev->local <= VIA_PIPC_586B)
dev->ide_regs[0x44] = val & 0x7b;
else if (dev->local <= VIA_PIPC_596B)
dev->ide_regs[0x44] = val & 0x7f;
else if (dev->local <= VIA_PIPC_686A)
dev->ide_regs[0x44] = val & 0x69;
else
dev->ide_regs[0x44] = val & 0x7d;
break;
case 0x45:
if (dev->local <= VIA_PIPC_586B)
dev->ide_regs[0x45] = val & 0x40;
else if (dev->local <= VIA_PIPC_596B)
dev->ide_regs[0x45] = val & 0x4f;
else if (dev->local <= VIA_PIPC_686A)
dev->ide_regs[0x45] = val & 0x5f;
else
dev->ide_regs[0x45] = (val & 0x5c) | 0x20;
break;
case 0x46:
if (dev->local <= VIA_PIPC_686A)
dev->ide_regs[0x46] = val & 0xf3;
else
dev->ide_regs[0x46] = val & 0xc0;
break;
case 0x50: case 0x51: case 0x52: case 0x53:
if (dev->local <= VIA_PIPC_586B)
dev->ide_regs[addr] = val & 0xc3;
else if (dev->local <= VIA_PIPC_596B)
dev->ide_regs[addr] = val & ((addr & 1) ? 0xc3 : 0xcb);
else if (dev->local <= VIA_PIPC_686A)
dev->ide_regs[addr] = val & ((addr & 1) ? 0xc7 : 0xcf);
else
dev->ide_regs[addr] = val & 0xd7;
break;
case 0x61: case 0x69:
@@ -805,9 +862,6 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
if ((func == (pm_func + 2)) && ((addr == 0x4a) || (addr == 0x4b) || (dev->pci_isa_regs[0x85] & 0x08)))
return;
if (1) /* temporarily disabled while unimplemented */
return;
switch (addr) {
default:
dev->ac97_regs[func - pm_func - 1][addr] = val;
@@ -879,7 +933,7 @@ pipc_init(const device_t *info)
if (dev->local >= VIA_PIPC_596A)
dev->acpi = device_add(&acpi_via_596b_device);
else if (dev->local >= VIA_PIPC_586B)
dev->acpi = device_add(&acpi_via_device);
dev->acpi = device_add(&acpi_via_device);
dev->usb[0] = device_add_inst(&usb_device, 1);
if (dev->local >= VIA_PIPC_686A)

View File

@@ -938,19 +938,24 @@ const cpu_family_t cpu_families[] = {
.name = "Cyrix III",
.internal_name = "c3_samuel",
.cpus = {
{"66", CPU_CYRIX3S, fpus_internal, 66666666, 1.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6, 3, 3, 8}, /*66 MHz version*/
{"233", CPU_CYRIX3S, fpus_internal, 233333333, 3.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 21, 21, 9, 9, 28},
{"266", CPU_CYRIX3S, fpus_internal, 266666666, 4.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 24, 24, 12, 12, 32},
{"300", CPU_CYRIX3S, fpus_internal, 300000000, 4.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 27, 27, 13, 13, 36},
{"333", CPU_CYRIX3S, fpus_internal, 333333333, 5.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 30, 30, 15, 15, 40},
{"350", CPU_CYRIX3S, fpus_internal, 350000000, 3.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 32, 32, 11, 11, 42},
{"400", CPU_CYRIX3S, fpus_internal, 400000000, 4.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 36, 36, 12, 12, 48},
{"450", CPU_CYRIX3S, fpus_internal, 450000000, 4.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 41, 41, 14, 14, 54}, /*^ is lower P2 speeds to allow emulation below 466 mhz*/
{"500", CPU_CYRIX3S, fpus_internal, 500000000, 5.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 45, 45, 15, 15, 60},
{"550", CPU_CYRIX3S, fpus_internal, 550000000, 5.5, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 50, 50, 17, 17, 66},
{"600", CPU_CYRIX3S, fpus_internal, 600000000, 6.0, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 54, 54, 18, 18, 72},
{"650", CPU_CYRIX3S, fpus_internal, 650000000, 6.5, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 58, 58, 20, 20, 78},
{"700", CPU_CYRIX3S, fpus_internal, 700000000, 7.0, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 62, 62, 21, 21, 84},
{"66", CPU_CYRIX3S, fpus_internal, 66666666, 1.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6, 3, 3, 8}, /* not in multiplier range */
{"233", CPU_CYRIX3S, fpus_internal, 233333333, 3.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 21, 21, 9, 9, 28}, /* not in multiplier range */
{"266", CPU_CYRIX3S, fpus_internal, 266666666, 4.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 24, 24, 12, 12, 32}, /* not in multiplier range */
{"300", CPU_CYRIX3S, fpus_internal, 300000000, 4.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 27, 27, 13, 13, 36}, /* not specified */
{"333", CPU_CYRIX3S, fpus_internal, 333333333, 5.0, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 30, 30, 15, 15, 40}, /* not specified */
{"366", CPU_CYRIX3S, fpus_internal, 366666666, 5.5, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 33, 33, 16, 16, 44}, /* not specified */
{"400", CPU_CYRIX3S, fpus_internal, 400000000, 6.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 36, 36, 17, 17, 48},
{"433", CPU_CYRIX3S, fpus_internal, 433333333, 6.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 39, 39, 18, 18, 52}, /* not specified */
{"450", CPU_CYRIX3S, fpus_internal, 450000000, 4.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 41, 41, 14, 14, 54},
{"466", CPU_CYRIX3S, fpus_internal, 466666666, 6.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 42, 42, 14, 14, 56}, /* not specified */
{"500", CPU_CYRIX3S, fpus_internal, 500000000, 5.0, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 45, 45, 15, 15, 60},
{"533", CPU_CYRIX3S, fpus_internal, 533333333, 8.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 48, 48, 15, 15, 64}, /* not specified */
{"550", CPU_CYRIX3S, fpus_internal, 550000000, 5.5, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 50, 50, 17, 17, 66},
{"600/100", CPU_CYRIX3S, fpus_internal, 600000000, 6.0, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 54, 54, 18, 18, 72},
{"600/133", CPU_CYRIX3S, fpus_internal, 600000000, 4.5, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 54, 54, 13, 13, 72},
{"650", CPU_CYRIX3S, fpus_internal, 650000000, 6.5, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 58, 58, 20, 20, 78},
{"667", CPU_CYRIX3S, fpus_internal, 666666667, 5.0, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 60, 60, 16, 16, 80},
{"700", CPU_CYRIX3S, fpus_internal, 700000000, 7.0, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 63, 63, 21, 21, 84},
{"", 0}
}
}, {

906
src/device/clock_ics9xxx.c Normal file
View File

@@ -0,0 +1,906 @@
/*
* 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 ICS9xxx series of clock generators.
*
*
*
* Authors: RichardG, <richardg867@gmail.com>
*
* Copyright 2020 RichardG.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#define HAVE_STDARG_H
#include <wchar.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/i2c.h>
#include "cpu.h"
enum {
ICS9150_08 = 1,
ICS9248_39,
ICS9248_98,
ICS9250_08,
ICS9250_10,
ICS9250_13,
ICS9250_14,
ICS9250_16,
ICS9250_18,
ICS9250_19,
ICS9250_23,
ICS9250_25,
ICS9250_26,
ICS9250_27,
ICS9250_28,
ICS9250_29,
ICS9250_30,
ICS9250_32,
ICS9250_38,
ICS9250_50
};
typedef struct {
uint16_t bus;
double ram_mult;
uint8_t pci_div;
} ics9xxx_frequency_t;
typedef struct {
uint8_t model;
uint8_t max_reg: 3;
uint8_t regs[8];
struct {
uint8_t normal_reg: 3;
uint8_t normal_bit: 3;
uint8_t inv_reg: 3;
uint8_t inv_bit: 3;
} fs_regs[5];
uint8_t normal_bits_fixed: 1;
uint8_t frequencies_ref;
ics9xxx_frequency_t frequencies[32];
ics9xxx_frequency_t *frequencies_ptr;
int8_t addr_register;
uint8_t bus_match: 5;
} ics9xxx_t;
static const ics9xxx_t ics9xxx_devices[] = {
[ICS9150_08] = {
.max_reg = 5,
.regs = {0x00, 0xff, 0xff, 0xff, 0x6f, 0xbf},
.fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 7, 4, 1}, {-1, -1, -1, -1}},
.frequencies = {
{.bus = 5000, .pci_div = 2},
{.bus = 7500, .pci_div = 2},
{.bus = 8333, .pci_div = 2},
{.bus = 6680, .pci_div = 2},
{.bus = 10300, .pci_div = 3},
{.bus = 11200, .pci_div = 3},
{.bus = 13333, .pci_div = 4},
{.bus = 10020, .pci_div = 3},
}
},
[ICS9248_39] = {
.max_reg = 5,
.regs = {0x00, 0x7f, 0xff, 0xbf, 0xf5, 0xff},
.fs_regs = {{0, 4, 3, 6}, {0, 5, 4, 3}, {0, 6, 1, 7}, {0, 7, 4, 1}, {-1, -1, -1, -1}},
.frequencies = {
{.bus = 12400, .pci_div = 3},
{.bus = 7500, .pci_div = 2},
{.bus = 8333, .pci_div = 2},
{.bus = 6680, .pci_div = 2},
{.bus = 10300, .pci_div = 3},
{.bus = 11200, .pci_div = 3},
{.bus = 13300, .pci_div = 3},
{.bus = 10030, .pci_div = 3},
{.bus = 12000, .pci_div = 3},
{.bus = 11500, .pci_div = 3},
{.bus = 11000, .pci_div = 3},
{.bus = 10500, .pci_div = 3},
{.bus = 14000, .pci_div = 4},
{.bus = 15000, .pci_div = 4},
{.bus = 12400, .pci_div = 4},
{.bus = 13300, .pci_div = 4}
}
},
[ICS9248_98] = {
.max_reg = 6,
.regs = {0x00, 0x7f, 0xff, 0xbf, 0xf5, 0xff, 0x06},
.fs_regs = {{0, 4, 3, 6}, {0, 5, 4, 3}, {0, 6, 1, 7}, {0, 7, 4, 1}, {-1, -1, -1, -1}},
.frequencies = {
{.bus = 8000, .pci_div = 2},
{.bus = 7500, .pci_div = 2},
{.bus = 8331, .pci_div = 2},
{.bus = 6682, .pci_div = 2},
{.bus = 10300, .pci_div = 3},
{.bus = 11201, .pci_div = 3},
{.bus = 6801, .pci_div = 2},
{.bus = 10023, .pci_div = 3},
{.bus = 12000, .pci_div = 3},
{.bus = 11499, .pci_div = 3},
{.bus = 10999, .pci_div = 3},
{.bus = 10500, .pci_div = 3},
{.bus = 14000, .pci_div = 4},
{.bus = 15000, .pci_div = 4},
{.bus = 12400, .pci_div = 4},
{.bus = 13299, .pci_div = 4},
{.bus = 13500, .pci_div = 4},
{.bus = 12999, .pci_div = 4},
{.bus = 12600, .pci_div = 4},
{.bus = 11800, .pci_div = 3},
{.bus = 11598, .pci_div = 3},
{.bus = 9500, .pci_div = 3},
{.bus = 9000, .pci_div = 3},
{.bus = 8501, .pci_div = 3},
{.bus = 16600, .pci_div = 4},
{.bus = 16001, .pci_div = 4},
{.bus = 15499, .pci_div = 4},
{.bus = 14795, .pci_div = 4},
{.bus = 14598, .pci_div = 4},
{.bus = 14398, .pci_div = 4},
{.bus = 14199, .pci_div = 4},
{.bus = 13801, .pci_div = 4}
}
},
[ICS9250_08] = {
.max_reg = 5,
.regs = {0x00, 0xff, 0xff, 0xff, 0x6d, 0xbf},
.fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 7, 4, 1}, {-1, -1, -1, -1}},
.frequencies_ref = ICS9248_39
},
[ICS9250_10] = {
.max_reg = 5,
.regs = {0x1f, 0xff, 0xfe, 0x00, 0x00, 0x06},
.fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}},
.frequencies = {
{.bus = 6667, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7067, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7466, .ram_mult = 1.5, .pci_div = 2},
{.bus = 8266, .ram_mult = 1.5, .pci_div = 2},
{.bus = 6350, .ram_mult = 1.5, .pci_div = 2},
{.bus = 6867, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7267, .ram_mult = 1.5, .pci_div = 2},
{.bus = 8866, .ram_mult = 1.5, .pci_div = 2},
{.bus = 10000, .ram_mult = 1, .pci_div = 3},
{.bus = 10600, .ram_mult = 1, .pci_div = 3},
{.bus = 11200, .ram_mult = 1, .pci_div = 3},
{.bus = 12400, .ram_mult = 1, .pci_div = 3},
{.bus = 9525, .ram_mult = 1, .pci_div = 3},
{.bus = 10300, .ram_mult = 1, .pci_div = 3},
{.bus = 10900, .ram_mult = 1, .pci_div = 3},
{.bus = 13300, .ram_mult = 1, .pci_div = 3}
}
},
[ICS9250_13] = {
.max_reg = 5,
.regs = {0x82, 0xcf, 0x7f, 0xff, 0xff, 0xf7},
.fs_regs = {{0, 4, 1, 4}, {0, 5, 5, 7}, {0, 6, 1, 5}, {0, 2, 2, 7}, {-1, -1, -1, -1}},
.frequencies = {
{.bus = 9000, .ram_mult = 1, .pci_div = 2},
{.bus = 8901, .ram_mult = 1, .pci_div = 2},
{.bus = 8800, .ram_mult = 1, .pci_div = 2},
{.bus = 8699, .ram_mult = 1, .pci_div = 2},
{.bus = 8591, .ram_mult = 1, .pci_div = 2},
{.bus = 8501, .ram_mult = 1, .pci_div = 2},
{.bus = 8400, .ram_mult = 1, .pci_div = 2},
{.bus = 8200, .ram_mult = 1, .pci_div = 2},
{.bus = 8101, .ram_mult = 1, .pci_div = 2},
{.bus = 8000, .ram_mult = 1, .pci_div = 2},
{.bus = 8331, .ram_mult = 1, .pci_div = 2},
{.bus = 6849, .ram_mult = 1, .pci_div = 2},
{.bus = 7800, .ram_mult = 1, .pci_div = 2},
{.bus = 7500, .ram_mult = 1, .pci_div = 2},
{.bus = 7199, .ram_mult = 1, .pci_div = 2},
{.bus = 6682, .ram_mult = 1, .pci_div = 2}
}
},
[ICS9250_14] = {
.max_reg = 5,
.regs = {0x02, 0x1f, 0xff, 0xff, 0xeb, 0xff},
.fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}},
.frequencies = {
{.bus = 6781, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7000, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7201, .ram_mult = 1.5, .pci_div = 2},
{.bus = 6667, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7301, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7500, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7700, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7801, .ram_mult = 1.5, .pci_div = 2},
{.bus = 8000, .ram_mult = 1.5, .pci_div = 2},
{.bus = 8300, .ram_mult = 1.5, .pci_div = 2},
{.bus = 8449, .ram_mult = 1.5, .pci_div = 2},
{.bus = 10000, .ram_mult = 1.5, .pci_div = 2},
{.bus = 8608, .ram_mult = 1.5, .pci_div = 2},
{.bus = 8800, .ram_mult = 1.5, .pci_div = 2},
{.bus = 9000, .ram_mult = 1.5, .pci_div = 2},
{.bus = 9500, .ram_mult = 1.5, .pci_div = 2},
{.bus = 4990, .ram_mult = 1, .pci_div = 3},
{.bus = 10000, .ram_mult = 1, .pci_div = 3},
{.bus = 7485, .ram_mult = 1, .pci_div = 3},
{.bus = 6658, .ram_mult = 1, .pci_div = 3},
{.bus = 8284, .ram_mult = 1, .pci_div = 3},
{.bus = 8981, .ram_mult = 1, .pci_div = 3},
{.bus = 9480, .ram_mult = 1, .pci_div = 3},
{.bus = 10050, .ram_mult = 1, .pci_div = 3},
{.bus = 10478, .ram_mult = 1, .pci_div = 3},
{.bus = 11177, .ram_mult = 1, .pci_div = 3},
{.bus = 11477, .ram_mult = 1, .pci_div = 3},
{.bus = 10000, .ram_mult = 1, .pci_div = 3},
{.bus = 12375, .ram_mult = 1, .pci_div = 3},
{.bus = 13274, .ram_mult = 1, .pci_div = 3},
{.bus = 13975, .ram_mult = 1, .pci_div = 3},
{.bus = 14969, .ram_mult = 1, .pci_div = 3}
}
},
[ICS9250_16] = {
.max_reg = 5,
.regs = {0x1f, 0xff, 0xff, 0x00, 0x00, 0x06},
.fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}},
.frequencies = {
{.bus = 6667, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7000, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7267, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7467, .ram_mult = 1.5, .pci_div = 2},
{.bus = 10000, .ram_mult = 1, .pci_div = 3},
{.bus = 10500, .ram_mult = 1, .pci_div = 3},
{.bus = 10900, .ram_mult = 1, .pci_div = 3},
{.bus = 11201, .ram_mult = 1, .pci_div = 3},
{.bus = 13334, .ram_mult = 1, .pci_div = 3},
{.bus = 14000, .ram_mult = 0.75, .pci_div = 4},
{.bus = 12000, .ram_mult = 0.75, .pci_div = 4},
{.bus = 12400, .ram_mult = 1, .pci_div = 3},
{.bus = 13334, .ram_mult = 0.75, .pci_div = 4},
{.bus = 15000, .ram_mult = 1, .pci_div = 4},
{.bus = 14000, .ram_mult = 1, .pci_div = 4},
{.bus = 13299, .ram_mult = 1, .pci_div = 4}
}
},
[ICS9250_18] = {
.max_reg = 5,
.regs = {0x02, 0xff, 0xff, 0xff, 0x6d, 0xbf},
.fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 7, 4, 1}, {-1, -1, -1, -1}},
.frequencies = {
{.bus = 8000, .pci_div = 2},
{.bus = 7500, .pci_div = 2},
{.bus = 8331, .pci_div = 2},
{.bus = 6690, .pci_div = 2},
{.bus = 10300, .pci_div = 3},
{.bus = 11201, .pci_div = 3},
{.bus = 6801, .pci_div = 2},
{.bus = 10070, .pci_div = 3},
{.bus = 12000, .pci_div = 3},
{.bus = 11499, .pci_div = 3},
{.bus = 10999, .pci_div = 3},
{.bus = 10500, .pci_div = 3},
{.bus = 14000, .pci_div = 4},
{.bus = 15000, .pci_div = 4},
{.bus = 12400, .pci_div = 4},
{.bus = 13390, .pci_div = 4},
{.bus = 13500, .pci_div = 4},
{.bus = 12999, .pci_div = 4},
{.bus = 12600, .pci_div = 4},
{.bus = 11800, .pci_div = 4},
{.bus = 11598, .pci_div = 4},
{.bus = 9500, .pci_div = 3},
{.bus = 9000, .pci_div = 3},
{.bus = 8501, .pci_div = 3},
{.bus = 16600, .pci_div = 4},
{.bus = 16001, .pci_div = 4},
{.bus = 15499, .pci_div = 4},
{.bus = 14795, .pci_div = 4},
{.bus = 14598, .pci_div = 4},
{.bus = 14398, .pci_div = 4},
{.bus = 14199, .pci_div = 4},
{.bus = 13801, .pci_div = 4}
}
},
[ICS9250_19] = {
.max_reg = 5,
.regs = {0x02, 0xff, 0xff, 0xff, 0x6d, 0xbf},
.fs_regs = {{0, 4, 4, 7}, {0, 5, 4, 4}, {0, 6, 5, 6}, {0, 7, 4, 1}, {-1, -1, -1, -1}},
.frequencies_ref = ICS9250_08
},
[ICS9250_23] = {
.max_reg = 5,
.regs = {0x02, 0x1f, 0xff, 0xff, 0xeb, 0xff},
.fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}},
.frequencies = {
{.bus = 6900, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7000, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7100, .ram_mult = 1.5, .pci_div = 2},
{.bus = 6690, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7200, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7500, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7660, .ram_mult = 1.5, .pci_div = 2},
{.bus = 8500, .ram_mult = 1.5, .pci_div = 2},
{.bus = 6800, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7400, .ram_mult = 1.5, .pci_div = 2},
{.bus = 14000, .ram_mult = 1, .pci_div = 4},
{.bus = 13333, .ram_mult = 1, .pci_div = 4},
{.bus = 15000, .ram_mult = 1, .pci_div = 4},
{.bus = 15500, .ram_mult = 1, .pci_div = 4},
{.bus = 16600, .ram_mult = 1, .pci_div = 4},
{.bus = 16600, .ram_mult = 1, .pci_div = 3},
{.bus = 11177, .ram_mult = 1, .pci_div = 3},
{.bus = 10478, .ram_mult = 1, .pci_div = 3},
{.bus = 10951, .ram_mult = 1, .pci_div = 3},
{.bus = 10090, .ram_mult = 1, .pci_div = 3},
{.bus = 11700, .ram_mult = 1, .pci_div = 3},
{.bus = 12375, .ram_mult = 1, .pci_div = 3},
{.bus = 13333, .ram_mult = 1, .pci_div = 3},
{.bus = 14250, .ram_mult = 1, .pci_div = 3},
{.bus = 13600, .ram_mult = 0.75, .pci_div = 4},
{.bus = 14000, .ram_mult = 0.75, .pci_div = 4},
{.bus = 14300, .ram_mult = 0.75, .pci_div = 4},
{.bus = 13390, .ram_mult = 0.75, .pci_div = 4},
{.bus = 14667, .ram_mult = 0.75, .pci_div = 4},
{.bus = 14933, .ram_mult = 0.75, .pci_div = 4},
{.bus = 15330, .ram_mult = 0.75, .pci_div = 4},
{.bus = 16667, .ram_mult = 0.75, .pci_div = 4}
}
},
[ICS9250_25] = {
.max_reg = 6,
.regs = {0x02, 0x1f, 0xff, 0xff, 0xeb, 0xff, 0x06},
.fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}},
.frequencies = {
{.bus = 5500, .ram_mult = 1.5, .pci_div = 2},
{.bus = 6000, .ram_mult = 1.5, .pci_div = 2},
{.bus = 6680, .ram_mult = 1.5, .pci_div = 2},
{.bus = 6833, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7000, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7200, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7500, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7700, .ram_mult = 1.5, .pci_div = 2},
{.bus = 8330, .ram_mult = 1, .pci_div = 3},
{.bus = 9000, .ram_mult = 1, .pci_div = 3},
{.bus = 10030, .ram_mult = 1, .pci_div = 3},
{.bus = 10300, .ram_mult = 1, .pci_div = 3},
{.bus = 11250, .ram_mult = 1, .pci_div = 3},
{.bus = 11500, .ram_mult = 1, .pci_div = 3},
{.bus = 12000, .ram_mult = 1, .pci_div = 3},
{.bus = 12500, .ram_mult = 1, .pci_div = 3},
{.bus = 12800, .ram_mult = 1, .pci_div = 4},
{.bus = 13000, .ram_mult = 1, .pci_div = 4},
{.bus = 13370, .ram_mult = 1, .pci_div = 4},
{.bus = 13700, .ram_mult = 1, .pci_div = 4},
{.bus = 14000, .ram_mult = 1, .pci_div = 4},
{.bus = 14500, .ram_mult = 1, .pci_div = 4},
{.bus = 15000, .ram_mult = 1, .pci_div = 4},
{.bus = 15333, .ram_mult = 1, .pci_div = 4},
{.bus = 12500, .ram_mult = 0.75, .pci_div = 4},
{.bus = 13000, .ram_mult = 0.75, .pci_div = 4},
{.bus = 13370, .ram_mult = 0.75, .pci_div = 4},
{.bus = 13700, .ram_mult = 0.75, .pci_div = 4},
{.bus = 14000, .ram_mult = 0.75, .pci_div = 4},
{.bus = 14500, .ram_mult = 0.75, .pci_div = 4},
{.bus = 15000, .ram_mult = 0.75, .pci_div = 4},
{.bus = 15333, .ram_mult = 0.75, .pci_div = 4}
}
},
[ICS9250_26] = {
.max_reg = 5,
.regs = {0x1e, 0xff, 0xff, 0x00, 0x00, 0x06},
.fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}},
.frequencies_ref = ICS9250_16
},
[ICS9250_27] = {
.max_reg = 5,
.regs = {0x0f, 0xff, 0xfe, 0x00, 0x00, 0x00},
.fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}},
.frequencies = {
{.bus = 6666, .ram_mult = 1.5, .pci_div = 2},
{.bus = 13332, .ram_mult = 1, .pci_div = 4},
{.bus = 10000, .ram_mult = 1, .pci_div = 3},
{.bus = 13332, .ram_mult = 0.75, .pci_div = 4},
{.bus = 6666, .ram_mult = 1.5, .pci_div = 2},
{.bus = 13332, .ram_mult = 1, .pci_div = 4},
{.bus = 10000, .ram_mult = 1, .pci_div = 3},
{.bus = 13332, .ram_mult = 1, .pci_div = 4}
}
},
[ICS9250_28] = {
.max_reg = 4,
.regs = {0x1e, 0xff, 0xfe, 0x00, 0x00},
.fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}},
.frequencies_ref = ICS9250_27
},
[ICS9250_29] = {
.max_reg = 5,
.regs = {0x16, 0xff, 0xfe, 0x00, 0x00, 0x00},
.fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}},
.frequencies_ref = ICS9250_27
},
[ICS9250_30] = {
.max_reg = 6,
.regs = {0x02, 0x0f, 0xff, 0xff, 0xeb, 0xff, 0x06},
.fs_regs = {{0, 4, 1, 6}, {0, 5, 4, 2}, {0, 6, 1, 5}, {0, 7, 1, 7}, {0, 2, 4, 4}},
.frequencies = {
{.bus = 6667, .ram_mult = 1.5, .pci_div = 2},
{.bus = 6000, .ram_mult = 1.5, .pci_div = 2},
{.bus = 6680, .ram_mult = 1.5, .pci_div = 2},
{.bus = 6833, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7000, .ram_mult = 1.5, .pci_div = 2},
{.bus = 7500, .ram_mult = 1.5, .pci_div = 2},
{.bus = 8000, .ram_mult = 1.5, .pci_div = 2},
{.bus = 8300, .ram_mult = 1.5, .pci_div = 2},
{.bus = 10000, .ram_mult = 1, .pci_div = 3},
{.bus = 9000, .ram_mult = 1, .pci_div = 3},
{.bus = 10030, .ram_mult = 1, .pci_div = 3},
{.bus = 10300, .ram_mult = 1, .pci_div = 3},
{.bus = 10500, .ram_mult = 1, .pci_div = 3},
{.bus = 11000, .ram_mult = 1, .pci_div = 3},
{.bus = 11500, .ram_mult = 1, .pci_div = 3},
{.bus = 20000, .ram_mult = 1, .pci_div = 6},
{.bus = 13333, .ram_mult = 1, .pci_div = 4},
{.bus = 16667, .ram_mult = 1, .pci_div = 4},
{.bus = 13370, .ram_mult = 1, .pci_div = 4},
{.bus = 13700, .ram_mult = 1, .pci_div = 4},
{.bus = 14000, .ram_mult = 1, .pci_div = 4},
{.bus = 14500, .ram_mult = 1, .pci_div = 4},
{.bus = 15000, .ram_mult = 1, .pci_div = 4},
{.bus = 16000, .ram_mult = 1, .pci_div = 4},
{.bus = 13333, .ram_mult = 0.75, .pci_div = 4},
{.bus = 16667, .ram_mult = 0.75, .pci_div = 4},
{.bus = 13370, .ram_mult = 0.75, .pci_div = 4},
{.bus = 13700, .ram_mult = 0.75, .pci_div = 4},
{.bus = 14000, .ram_mult = 0.75, .pci_div = 4},
{.bus = 14500, .ram_mult = 0.75, .pci_div = 4},
{.bus = 15000, .ram_mult = 0.75, .pci_div = 4},
{.bus = 16000, .ram_mult = 0.75, .pci_div = 4}
}
},
[ICS9250_32] = {
.max_reg = 4,
.regs = {0x07, 0xff, 0xff, 0x00, 0x00},
.fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}
},
[ICS9250_38] = {
.max_reg = 6,
.regs = {0x18, 0x07, 0xfe, 0xc7, 0xfc, 0x00, 0x80},
.fs_regs = {{0, 0, -1, -1}, {0, 1, -1, -1}, {0, 2, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}},
.normal_bits_fixed = 1,
.frequencies = {
{.bus = 6666, .ram_mult = 1, .pci_div = 1},
{.bus = 10000, .ram_mult = 2.0/3.0, .pci_div = 3},
{.bus = 20000, .ram_mult = 1.0/3.0, .pci_div = 6},
{.bus = 13333, .ram_mult = 0.5, .pci_div = 2},
{.bus = 6666, .ram_mult = 1, .pci_div = 1},
{.bus = 10000, .ram_mult = 2.0/3.0, .pci_div = 3},
{.bus = 20000, .ram_mult = 1.0/3.0, .pci_div = 6},
{.bus = 13333, .ram_mult = 0.5, .pci_div = 2}
}
},
[ICS9250_50] = {
.max_reg = 6,
.regs = {0x02, 0x6f, 0xff, 0xff, 0xef, 0xff, 0x06},
.fs_regs = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {0, 7, 1, 7}, {0, 2, 4, 4}},
.frequencies = {
{.bus = 6667, .ram_mult = 1.5, .pci_div = 2},
{.bus = 10000, .ram_mult = 1, .pci_div = 3},
{.bus = 13333, .ram_mult = 1, .pci_div = 4},
{.bus = 13333, .ram_mult = 0.75, .pci_div = 4}
}
}
};
#define ENABLE_ICS9xxx_LOG 1
#ifdef ENABLE_ICS9xxx_LOG
int ics9xxx_do_log = ENABLE_ICS9xxx_LOG;
static void
ics9xxx_log(const char *fmt, ...)
{
va_list ap;
if (ics9xxx_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define ics9xxx_log(fmt, ...)
#endif
static uint8_t
ics9xxx_start(void *bus, uint8_t addr, uint8_t read, void *priv)
{
ics9xxx_t *dev = (ics9xxx_t *) priv;
ics9xxx_log("ICS9xxx: start()\n");
dev->addr_register = -2; /* -2 = command; -1 = SMBus block length; 0+ = registers */
return 1;
}
static uint8_t
ics9xxx_read(void *bus, uint8_t addr, void *priv)
{
ics9xxx_t *dev = (ics9xxx_t *) priv;
uint8_t ret = 0xff;
if (dev->addr_register < 0) {
dev->addr_register = -1;
ret = dev->max_reg + 1;
} else if ((dev->model == ICS9250_50) && (dev->addr_register == 0))
ret = dev->regs[dev->addr_register] & 0x0b; /* -50 reads back revision ID instead */
else
ret = dev->regs[dev->addr_register];
ics9xxx_log("ICS9xxx: read(%02X) = %02X\n", dev->addr_register, ret);
if (++dev->addr_register > dev->max_reg)
dev->addr_register = 0; /* roll-over */
return ret;
}
static void
ics9xxx_set(ics9xxx_t *dev, uint8_t val)
{
/* Add register-defined frequency bits to the static frequency bits we were passed. */
for (uint8_t i = 0; i < sizeof(dev->fs_regs) / sizeof(dev->fs_regs[0]); i++) {
if ((dev->fs_regs[i].normal_reg < 7) && (dev->regs[dev->fs_regs[i].normal_reg] & (1 << dev->fs_regs[i].normal_bit)))
val |= 1 << i;
}
ics9xxx_log("ICS9xxx: set(%02X) = %d\n", val, ics9xxx_devices[dev->model].frequencies[val].bus);
}
static uint8_t
ics9xxx_write(void *bus, uint8_t addr, uint8_t data, void *priv)
{
ics9xxx_t *dev = (ics9xxx_t *) priv;
ics9xxx_log("ICS9xxx: write(%02X, %02X)\n", dev->addr_register, data);
if (dev->addr_register >= 0) {
/* Preserve fixed bits. */
for (uint8_t i = 0; i < sizeof(dev->fs_regs) / sizeof(dev->fs_regs[0]); i++) {
if (dev->normal_bits_fixed && (dev->fs_regs[i].normal_reg == dev->addr_register))
data = (dev->regs[dev->addr_register] & (1 << dev->fs_regs[i].normal_bit)) | (data & ~(1 << dev->fs_regs[i].normal_bit));
if (dev->fs_regs[i].inv_reg == dev->addr_register)
data = (dev->regs[dev->addr_register] & (1 << dev->fs_regs[i].inv_bit)) | (data & ~(1 << dev->fs_regs[i].inv_bit));
}
switch (dev->addr_register) {
case 0:
if (dev->model == ICS9250_38)
data = (dev->regs[dev->addr_register] & ~0xef) | (data & 0xef);
else if (dev->model == ICS9250_10)
ics9xxx_set(dev, (cpu_busspeed >= 100000000) * 0x08);
else if ((dev->model == ICS9250_16) || (dev->model == ICS9250_26))
ics9xxx_set(dev, ((cpu_busspeed >= 120000000) * 0x08) | ((((cpu_busspeed >= 100000000) && (cpu_busspeed < 120000000)) || (cpu_busspeed == 150000000) || (cpu_busspeed == 132999999)) * 0x04));
else if ((dev->model == ICS9250_27) || (dev->model == ICS9250_28) || (dev->model == ICS9250_29))
ics9xxx_set(dev, ((cpu_busspeed == 100000000) * 0x02) | ((cpu_busspeed > 100000000) * 0x01));
else
ics9xxx_set(dev, 0x00);
break;
case 1:
if (dev->model == ICS9250_38)
data = (dev->regs[dev->addr_register] & ~0xfe) | (data & 0xfe);
break;
case 3:
if (dev->model == ICS9250_32)
data ^= 0x70;
break;
case 4:
if (dev->model == ICS9250_38)
data = (dev->regs[dev->addr_register] & ~0xfc) | (data & 0xfc);
break;
case 6:
if (dev->model == ICS9250_38)
data = dev->regs[dev->addr_register];
break;
}
dev->regs[dev->addr_register] = data;
}
if (++dev->addr_register > dev->max_reg)
dev->addr_register = 0; /* roll-over */
return 1;
}
static uint8_t
find_bus_match(ics9xxx_t *dev, uint32_t bus, uint8_t preset_mask, uint8_t preset) {
uint8_t best_match = 0;
uint32_t delta, best_delta = -1;
for (uint8_t i = 0; i < (sizeof(dev->frequencies) / sizeof(dev->frequencies[0])); i++) {
if (((i & preset_mask) != preset) || !dev->frequencies_ptr[i].bus)
continue;
delta = ABS((int32_t) (bus - (dev->frequencies_ptr[i].bus * 10000)));
if (delta < best_delta) {
best_match = i;
best_delta = delta;
}
}
ics9xxx_log("ICS9xxx: find_match(%02X, %d) = %d (%02X)\n", dev->model, bus, dev->frequencies_ptr[best_match].bus, best_match);
return best_match;
}
static void *
ics9xxx_init(const device_t *info)
{
ics9xxx_t *dev = (ics9xxx_t *) malloc(sizeof(ics9xxx_t));
memcpy(dev, &ics9xxx_devices[info->local], sizeof(ics9xxx_t));
ics9xxx_log("ICS9xxx: init(%02X)\n", info->local);
dev->model = info->local;
dev->frequencies_ptr = (ics9xxx_frequency_t *) ics9xxx_devices[dev->frequencies_ref ? dev->frequencies_ref : dev->model].frequencies;
if (!dev->frequencies_ptr)
fatal("ICS9xxx: NULL frequency table\n");
/* Determine which frequency bits cannot be strapped (register only). */
uint8_t register_only_bits = 0x00;
uint8_t i;
for (i = 0; i < sizeof(dev->fs_regs) / sizeof(dev->fs_regs[0]); i++) {
if ((dev->fs_regs[i].normal_reg == 7) && (dev->fs_regs[i].inv_reg == 7))
register_only_bits |= 1 << i;
}
/* Find bus speed match and set default register bits accordingly. */
dev->bus_match = find_bus_match(dev, cpu_busspeed, register_only_bits, 0x00);
for (i = 0; i < sizeof(dev->fs_regs) / sizeof(dev->fs_regs[0]); i++) {
if (dev->fs_regs[i].normal_reg < 7) {
if (dev->bus_match & (1 << i))
dev->regs[dev->fs_regs[i].normal_reg] |= 1 << dev->fs_regs[i].normal_bit;
else
dev->regs[dev->fs_regs[i].normal_reg] &= ~(1 << dev->fs_regs[i].normal_bit);
}
if (dev->fs_regs[i].inv_reg < 7) {
if (dev->bus_match & (1 << i))
dev->regs[dev->fs_regs[i].inv_reg] &= ~(1 << dev->fs_regs[i].inv_bit);
else
dev->regs[dev->fs_regs[i].inv_reg] |= 1 << dev->fs_regs[i].inv_bit;
}
}
i2c_sethandler(i2c_smbus, 0x69, 1, ics9xxx_start, ics9xxx_read, ics9xxx_write, NULL, dev);
return dev;
}
static void
ics9xxx_close(void *priv)
{
ics9xxx_t *dev = (ics9xxx_t *) priv;
ics9xxx_log("ICS9xxx: close()\n");
i2c_removehandler(i2c_smbus, 0x69, 1, ics9xxx_start, ics9xxx_read, ics9xxx_write, NULL, dev);
free(dev);
}
const device_t ics9150_08_device = {
"ICS9150-08 Clock Generator",
DEVICE_ISA,
ICS9150_08,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9248_39_device = {
"ICS9248-39 Clock Generator",
DEVICE_ISA,
ICS9248_39,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9248_98_device = {
"ICS9248-98 Clock Generator",
DEVICE_ISA,
ICS9248_98,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_08_device = {
"ICS9250-08 Clock Generator",
DEVICE_ISA,
ICS9250_08,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_10_device = {
"ICS9250-10 Clock Generator",
DEVICE_ISA,
ICS9250_10,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_13_device = {
"ICS9250-13 Clock Generator",
DEVICE_ISA,
ICS9250_13,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_14_device = {
"ICS9250-14 Clock Generator",
DEVICE_ISA,
ICS9250_14,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_16_device = {
"ICS9250-16 Clock Generator",
DEVICE_ISA,
ICS9250_16,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_18_device = {
"ICS9250-18 Clock Generator",
DEVICE_ISA,
ICS9250_18,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_19_device = {
"ICS9250-19 Clock Generator",
DEVICE_ISA,
ICS9250_19,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_23_device = {
"ICS9250-23 Clock Generator",
DEVICE_ISA,
ICS9250_23,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_25_device = {
"ICS9250-25 Clock Generator",
DEVICE_ISA,
ICS9250_25,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_26_device = {
"ICS9250-26 Clock Generator",
DEVICE_ISA,
ICS9250_26,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_27_device = {
"ICS9250-27 Clock Generator",
DEVICE_ISA,
ICS9250_27,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_28_device = {
"ICS9250-28 Clock Generator",
DEVICE_ISA,
ICS9250_28,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_29_device = {
"ICS9250-29 Clock Generator",
DEVICE_ISA,
ICS9250_29,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_30_device = {
"ICS9250-30 Clock Generator",
DEVICE_ISA,
ICS9250_30,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_32_device = {
"ICS9250-32 Clock Generator",
DEVICE_ISA,
ICS9250_32,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_38_device = {
"ICS9250-38 Clock Generator",
DEVICE_ISA,
ICS9250_38,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ics9250_50_device = {
"ICS9250-50 Clock Generator",
DEVICE_ISA,
ICS9250_50,
ics9xxx_init, ics9xxx_close, NULL,
{ NULL }, NULL, NULL,
NULL
};

View File

@@ -35,7 +35,7 @@ static uint8_t lm75_i2c_read(void *bus, uint8_t addr, void *priv);
static uint8_t lm75_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv);
static void lm75_reset(lm75_t *dev);
#define ENABLE_LM75_LOG 1
#ifdef ENABLE_LM75_LOG
int lm75_do_log = ENABLE_LM75_LOG;

View File

@@ -24,6 +24,7 @@
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include "cpu.h"
#include <86box/i2c.h>
#include <86box/hwm.h>
@@ -50,6 +51,7 @@ typedef struct {
uint32_t local;
hwm_values_t *values;
device_t *lm75[2];
pc_timer_t hard_reset_timer;
uint8_t regs[256];
uint8_t regs_782d[2][16];
@@ -369,10 +371,18 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank)
}
break;
case 0x81:
/* CUV4X-LS performs a hard reset through this register. */
if ((dev->local & LM78_AS99127F) && (val == 0xa9)) {
lm78_log("LM78: Hard reset requested through AS99127F\n");
timer_set_delay_u64(&dev->hard_reset_timer, 1); /* hard reset on a timer to avoid issues caused by invalidation of the I2C bus */
}
break;
case 0x87:
/* AS99127F boards perform a soft reset through this register */
/* Other AS99127F boards perform a soft reset through this register. */
if ((dev->local & LM78_AS99127F) && (val == 0x01)) {
lm78_log("LM78: Reset requested through AS99127F\n");
lm78_log("LM78: Soft reset requested through AS99127F\n");
resetx86();
}
break;
@@ -382,6 +392,13 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank)
}
static void
lm78_hard_reset_timer(void *priv)
{
pc_reset_hard();
}
static void
lm78_reset(lm78_t *dev, uint8_t initialization)
{
@@ -500,6 +517,8 @@ lm78_init(const device_t *info)
if (dev->local & LM78_AS99127F) {
/* AS99127: different -12V Rin value (bruteforced) */
defaults.voltages[5] = LM78_NEG_VOLTAGE(12000, 2400);
timer_add(&dev->hard_reset_timer, lm78_hard_reset_timer, dev, 0);
} else if (dev->local & LM78_W83782D) {
/* W83782D: different negative voltage formula */
defaults.voltages[5] = LM78_NEG_VOLTAGE2(12000, 232);

View File

@@ -6,14 +6,12 @@
*
* This file is part of the 86Box distribution.
*
* Emulation of a GPIO-based I2C device.
* Emulation of a GPIO-based I2C host controller.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* RichardG, <richardg867@gmail.com>
* Authors: RichardG, <richardg867@gmail.com>
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2020 RichardG.
*/
#include <stdarg.h>
@@ -27,36 +25,11 @@
#include <86box/i2c.h>
enum {
TRANSMITTER_SLAVE = 1,
TRANSMITTER_MASTER = 2
};
enum {
I2C_IDLE = 0,
I2C_RECEIVE,
I2C_RECEIVE_WAIT,
I2C_TRANSMIT_START,
I2C_TRANSMIT,
I2C_ACKNOWLEDGE,
I2C_NOTACKNOWLEDGE,
I2C_TRANSACKNOWLEDGE,
I2C_TRANSMIT_WAIT
};
enum {
SLAVE_IDLE = 0,
SLAVE_RECEIVEADDR,
SLAVE_RECEIVEDATA,
SLAVE_SENDDATA,
SLAVE_INVALID
};
typedef struct {
char *bus_name;
void *i2c;
uint8_t scl, sda, receive_wait_sda, state, slave_state, slave_addr,
slave_read, last_sda, pos, transmit, byte;
uint8_t prev_scl, prev_sda, slave_sda, started,
slave_addr_received, slave_addr, slave_read, pos, byte;
} i2c_gpio_t;
@@ -90,7 +63,7 @@ i2c_gpio_init(char *bus_name)
dev->bus_name = bus_name;
dev->i2c = i2c_addbus(dev->bus_name);
dev->scl = dev->sda = 1;
dev->prev_scl = dev->prev_sda = dev->slave_sda = 1;
dev->slave_addr = 0xff;
return dev;
@@ -110,206 +83,77 @@ i2c_gpio_close(void *dev_handle)
}
void
i2c_gpio_next_byte(i2c_gpio_t *dev)
{
dev->byte = i2c_read(dev->i2c, dev->slave_addr);
i2c_gpio_log(1, "I2C GPIO %s: Transmitting data %02X\n", dev->bus_name, dev->byte);
}
uint8_t
i2c_gpio_write(i2c_gpio_t *dev)
{
uint8_t i;
switch (dev->slave_state) {
case SLAVE_IDLE:
i = dev->slave_addr;
dev->slave_addr = dev->byte >> 1;
dev->slave_read = dev->byte & 1;
i2c_gpio_log(1, "I2C GPIO %s: Initiating %s address %02X\n", dev->bus_name, dev->slave_read ? "read from" : "write to", dev->slave_addr);
if (!i2c_has_device(dev->i2c, dev->slave_addr) ||
((i == 0xff) && !i2c_start(dev->i2c, dev->slave_addr, dev->slave_read))) { /* start only once per transfer */
dev->slave_state = SLAVE_INVALID;
dev->slave_addr = 0xff;
return I2C_NOTACKNOWLEDGE;
}
if (dev->slave_read) {
dev->slave_state = SLAVE_SENDDATA;
dev->transmit = TRANSMITTER_SLAVE;
dev->byte = i2c_read(dev->i2c, dev->slave_addr);
} else {
dev->slave_state = SLAVE_RECEIVEADDR;
dev->transmit = TRANSMITTER_MASTER;
}
break;
case SLAVE_RECEIVEADDR:
i2c_gpio_log(1, "I2C GPIO %s: Receiving address %02X\n", dev->bus_name, dev->byte);
dev->slave_state = dev->slave_read ? SLAVE_SENDDATA : SLAVE_RECEIVEDATA;
if (!i2c_write(dev->i2c, dev->slave_addr, dev->byte))
return I2C_NOTACKNOWLEDGE;
break;
case SLAVE_RECEIVEDATA:
i2c_gpio_log(1, "I2C GPIO %s: Receiving data %02X\n", dev->bus_name, dev->byte);
if (!i2c_write(dev->i2c, dev->slave_addr, dev->byte))
return I2C_NOTACKNOWLEDGE;
break;
case SLAVE_INVALID:
return I2C_NOTACKNOWLEDGE;
}
return I2C_ACKNOWLEDGE;
}
void
i2c_gpio_stop(i2c_gpio_t *dev)
{
i2c_gpio_log(1, "I2C GPIO %s: Stopping transfer\n", dev->bus_name);
if (dev->slave_addr != 0xff) /* don't stop if no transfer was in progress */
i2c_stop(dev->i2c, dev->slave_addr);
dev->slave_addr = 0xff;
dev->slave_state = SLAVE_IDLE;
dev->transmit = TRANSMITTER_MASTER;
}
void
i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
{
i2c_gpio_t *dev = (i2c_gpio_t *) dev_handle;
i2c_gpio_log(3, "I2C GPIO %s: scl=%d->%d sda=%d->%d last_valid_sda=%d state=%d\n", dev->bus_name, dev->scl, scl, dev->last_sda, sda, dev->sda, dev->state);
i2c_gpio_log(3, "I2C GPIO %s: write scl=%d->%d sda=%d->%d read=%d\n", dev->bus_name, dev->prev_scl, scl, dev->prev_sda, sda, dev->slave_read);
switch (dev->state) {
case I2C_IDLE:
if (scl && dev->last_sda && !sda) { /* start condition; dev->scl check breaks NCR SDMS */
i2c_gpio_log(2, "I2C GPIO %s: Start condition received (from IDLE)\n", dev->bus_name);
dev->state = I2C_RECEIVE;
dev->pos = 0;
}
break;
if (dev->prev_scl && scl) {
if (dev->prev_sda && !sda) {
i2c_gpio_log(2, "I2C GPIO %s: Start condition\n", dev->bus_name);
dev->started = 1;
dev->pos = 0;
dev->slave_read = 2; /* start with address transfer */
dev->slave_sda = 1;
} else if (!dev->prev_sda && sda) {
i2c_gpio_log(2, "I2C GPIO %s: Stop condition\n", dev->bus_name);
dev->started = 0;
dev->slave_sda = 1;
}
} else if (!dev->prev_scl && scl && dev->started) {
if (dev->pos++ < 8) {
if (dev->slave_read == 1) {
dev->slave_sda = !!(dev->byte & 0x80);
dev->byte <<= 1;
} else {
dev->byte <<= 1;
dev->byte |= sda;
}
case I2C_RECEIVE_WAIT:
if (!dev->scl && scl)
dev->state = I2C_RECEIVE;
else if (!dev->scl && !scl && dev->last_sda && sda) /* workaround for repeated start condition on Windows XP DDC */
dev->receive_wait_sda = 1;
/* fall-through */
i2c_gpio_log(2, "I2C GPIO %s: Bit %d = %d\n", dev->bus_name, 8 - dev->pos, (dev->slave_read == 1) ? dev->slave_sda : sda);
}
case I2C_RECEIVE:
if (!dev->scl && scl) {
dev->byte <<= 1;
if (sda)
dev->byte |= 1;
else
dev->byte &= 0xfe;
if (++dev->pos == 8)
dev->state = i2c_gpio_write(dev);
} else if (dev->scl && scl) {
if (sda && !dev->last_sda) { /* stop condition */
i2c_gpio_log(2, "I2C GPIO %s: Stop condition received (from RECEIVE)\n", dev->bus_name);
dev->state = I2C_IDLE;
i2c_gpio_stop(dev);
} else if (!sda && dev->last_sda) { /* start condition */
i2c_gpio_log(2, "I2C GPIO %s: Start condition received (from RECEIVE)\n", dev->bus_name);
dev->pos = 0;
dev->slave_state = SLAVE_IDLE;
}
}
break;
if (dev->pos == 8) {
i2c_gpio_log(2, "I2C GPIO %s: Byte = %02X\n", dev->bus_name, dev->byte);
case I2C_ACKNOWLEDGE:
if (!dev->scl && scl) {
i2c_gpio_log(2, "I2C GPIO %s: Acknowledging transfer to %02X\n", dev->bus_name, dev->slave_addr);
sda = 0;
dev->receive_wait_sda = 0; /* ack */
dev->pos = 0;
dev->state = (dev->transmit == TRANSMITTER_MASTER) ? I2C_RECEIVE_WAIT : I2C_TRANSMIT;
}
break;
/* (N)ACKing here instead of at the 9th bit may sound odd, but is required by the Matrox Mystique Windows drivers. */
switch (dev->slave_read) {
case 2: /* address transfer */
dev->slave_addr = dev->byte >> 1;
dev->slave_read = (dev->byte & 1);
case I2C_NOTACKNOWLEDGE:
if (!dev->scl && scl) {
i2c_gpio_log(2, "I2C GPIO %s: Not acknowledging transfer\n", dev->bus_name);
sda = 1;
dev->pos = 0;
dev->state = I2C_IDLE;
dev->slave_state = SLAVE_IDLE;
}
break;
/* slave ACKs? */
dev->slave_sda = !(i2c_has_device(dev->i2c, dev->slave_addr) && i2c_start(dev->i2c, dev->slave_addr, dev->slave_read));
i2c_gpio_log(2, "I2C GPIO %s: Slave %02X %s %sACK\n", dev->bus_name, dev->slave_addr, dev->slave_read ? "read" : "write", dev->slave_sda ? "N" : "");
case I2C_TRANSACKNOWLEDGE:
if (!dev->scl && scl) {
if (sda) { /* not acknowledged; must be end of transfer */
i2c_gpio_log(2, "I2C GPIO %s: End of transfer\n", dev->bus_name);
dev->state = I2C_IDLE;
i2c_gpio_stop(dev);
} else { /* next byte to transfer */
dev->state = I2C_TRANSMIT_START;
i2c_gpio_next_byte(dev);
dev->pos = 0;
i2c_gpio_log(2, "I2C GPIO %s: Next byte = %02X\n", dev->bus_name, dev->byte);
}
}
break;
if (!dev->slave_sda && dev->slave_read) /* read first byte on an ACKed read transfer */
dev->byte = i2c_read(dev->i2c, dev->slave_addr);
case I2C_TRANSMIT_WAIT:
if (dev->scl && scl) {
if (dev->last_sda && !sda) { /* start condition */
i2c_gpio_next_byte(dev);
dev->pos = 0;
i2c_gpio_log(2, "I2C GPIO %s: Next byte = %02X\n", dev->bus_name, dev->byte);
}
if (!dev->last_sda && sda) { /* stop condition */
i2c_gpio_log(2, "I2C GPIO %s: Stop condition received (from TRANSMIT_WAIT)\n", dev->bus_name);
dev->state = I2C_IDLE;
i2c_gpio_stop(dev);
}
}
break;
dev->slave_read |= 0x80; /* slave_read was overwritten; stop the master ACK read logic from running at the 9th bit if we're reading */
break;
case I2C_TRANSMIT_START:
if (!dev->scl && scl)
dev->state = I2C_TRANSMIT;
if (dev->scl && scl && !dev->last_sda && sda) { /* stop condition */
i2c_gpio_log(2, "I2C GPIO %s: Stop condition received (from TRANSMIT_START)\n", dev->bus_name);
dev->state = I2C_IDLE;
i2c_gpio_stop(dev);
}
/* fall-through */
case I2C_TRANSMIT:
if (!dev->scl && scl) {
dev->scl = scl;
if (!dev->pos)
i2c_gpio_log(2, "I2C GPIO %s: Transmit byte %02X\n", dev->bus_name, dev->byte);
dev->sda = sda = dev->byte & 0x80;
i2c_gpio_log(2, "I2C GPIO %s: Transmit bit %02X %d\n", dev->bus_name, dev->byte, dev->pos);
dev->byte <<= 1;
dev->pos++;
return;
}
if (dev->scl && !scl && (dev->pos == 8)) {
dev->state = I2C_TRANSACKNOWLEDGE;
i2c_gpio_log(2, "I2C GPIO %s: Acknowledge mode\n", dev->bus_name);
}
break;
case 0: /* write transfer */
dev->slave_sda = !i2c_write(dev->i2c, dev->slave_addr, dev->byte);
i2c_gpio_log(2, "I2C GPIO %s: Write %02X %sACK\n", dev->bus_name, dev->byte, dev->slave_sda ? "N" : "");
break;
}
} else if (dev->pos == 9) {
if (dev->slave_read == 1) { /* read transfer (unless we're in an address transfer) */
if (!sda) /* master ACKs? */
dev->byte = i2c_read(dev->i2c, dev->slave_addr);
i2c_gpio_log(2, "I2C GPIO %s: Read %02X %sACK\n", dev->bus_name, dev->byte, sda ? "N" : "");
} else
dev->slave_read &= 1; /* if we're in an address transfer, clear it */
dev->pos = 0; /* start over */
}
} else if (dev->prev_scl && !scl && (dev->pos != 8)) { /* keep (N)ACK computed at the 8th bit when transitioning to the 9th bit */
dev->slave_sda = 1;
}
if (!dev->scl && scl)
dev->sda = sda;
dev->last_sda = sda;
dev->scl = scl;
dev->prev_scl = scl;
dev->prev_sda = sda;
}
@@ -317,7 +161,7 @@ uint8_t
i2c_gpio_get_scl(void *dev_handle)
{
i2c_gpio_t *dev = (i2c_gpio_t *) dev_handle;
return dev->scl;
return dev->prev_scl;
}
@@ -325,17 +169,8 @@ uint8_t
i2c_gpio_get_sda(void *dev_handle)
{
i2c_gpio_t *dev = (i2c_gpio_t *) dev_handle;
switch (dev->state) {
case I2C_TRANSMIT:
case I2C_ACKNOWLEDGE:
return dev->sda;
case I2C_RECEIVE_WAIT:
return dev->receive_wait_sda;
default:
return 1;
}
i2c_gpio_log(3, "I2C GPIO %s: read myscl=%d mysda=%d slavesda=%d\n", dev->bus_name, dev->prev_scl, dev->prev_sda, dev->slave_sda);
return dev->prev_sda && dev->slave_sda;
}

View File

@@ -94,7 +94,7 @@ postcard_reset(void)
static void
postcard_write(uint16_t port, uint8_t val, void *priv)
{
if (postcard_written && val == postcard_code)
if (postcard_written && (val == postcard_code))
return;
postcard_prev_code = postcard_code;
@@ -117,7 +117,7 @@ postcard_init(const device_t *info)
postcard_port = 0x190; /* ISA PS/2 machines */
else if (strstr(machines[machine].name, " IBM XT "))
postcard_port = 0x60; /* IBM XT */
else if (strstr(machines[machine].name, "PCjr"))
else if (strstr(machines[machine].name, " IBM PCjr"))
postcard_port = 0x10; /* IBM PCjr */
else if (strstr(machines[machine].name, " Compaq ") && !(machines[machine].flags & MACHINE_PCI))
postcard_port = 0x84; /* ISA Compaq machines */

View File

@@ -127,6 +127,9 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
smbus_addr = (dev->addr >> 1);
read = dev->addr & 0x01;
cmd = (val >> 2) & 0xf;
smbus_piix4_log("SMBus PIIX4: addr=%02X read=%d protocol=%X cmd=%02X data0=%02X data1=%02X\n", smbus_addr, read, cmd, dev->cmd, dev->data0, dev->data1);
/* Raise DEV_ERR if no device is at this address, or if the device returned NAK when starting the transfer. */
if (!i2c_has_device(i2c_smbus, smbus_addr) || !i2c_start(i2c_smbus, smbus_addr, read)) {
dev->next_stat = 0x04;
@@ -137,8 +140,6 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
/* Decode the command protocol.
VIA-specific modes (0x4 and [0x6:0xf]) are undocumented and required real hardware research. */
cmd = (val >> 2) & 0xf;
smbus_piix4_log("SMBus PIIX4: protocol=%X cmd=%02X data0=%02X data1=%02X\n", cmd, dev->cmd, dev->data0, dev->data1);
switch (cmd) {
case 0x0: /* quick R/W */
break;
@@ -217,15 +218,15 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
if (read) {
/* block read [data0] (I2C) or [first byte] (SMBus) bytes */
block_len = (cmd == 0x5) ? i2c_read(i2c_smbus, smbus_addr) : dev->data0;
for (i = 0; i < block_len; i++)
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 {
block_len = dev->data0;
if (cmd == 0x5) /* send length [data0] as first byte on SMBus */
i2c_write(i2c_smbus, smbus_addr, block_len);
i2c_write(i2c_smbus, smbus_addr, dev->data0);
/* block write [data0] bytes */
for (i = 0; i < block_len; i++) {
for (i = 0; i < dev->data0; i++) {
if (!i2c_write(i2c_smbus, smbus_addr, dev->data[i & SMBUS_PIIX4_BLOCK_DATA_MASK]))
break;
}
@@ -349,6 +350,8 @@ smbus_piix4_init(const device_t *info)
memset(dev, 0, sizeof(smbus_piix4_t));
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");
timer_add(&dev->response_timer, smbus_piix4_response, dev, 0);

View File

@@ -573,7 +573,8 @@ ide_identify(ide_t *ide)
ide->buffer[51] = ide_get_timings(ide, TIMINGS_PIO);
ide->buffer[53] &= 0xfff9;
ide->buffer[52] = ide->buffer[62] = ide->buffer[63] = ide->buffer[64] = 0x0000;
ide->buffer[65] = ide->buffer[66] = ide->buffer[67] = ide->buffer[68] = 0x0000;
ide->buffer[65] = ide->buffer[66] = ide_get_timings(ide, TIMINGS_DMA);
ide->buffer[67] = ide->buffer[68] = 0x0000;
ide->buffer[88] = 0x0000;
if (max_pio >= 3) {

42
src/include/86box/clock.h Normal file
View File

@@ -0,0 +1,42 @@
/*
* 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.
*
* Definitions for clock generator chips.
*
*
*
* Authors: RichardG, <richardg867@gmail.com>
*
* Copyright 2020 RichardG.
*/
#ifndef EMU_CLOCK_H
# define EMU_CLOCK_H
/* clock_ics9xxx.c */
extern const device_t ics9150_08_device;
extern const device_t ics9248_39_device;
extern const device_t ics9248_98_device;
extern const device_t ics9250_08_device;
extern const device_t ics9250_10_device;
extern const device_t ics9250_13_device;
extern const device_t ics9250_14_device;
extern const device_t ics9250_16_device;
extern const device_t ics9250_18_device;
extern const device_t ics9250_19_device;
extern const device_t ics9250_23_device;
extern const device_t ics9250_25_device;
extern const device_t ics9250_26_device;
extern const device_t ics9250_27_device;
extern const device_t ics9250_28_device;
extern const device_t ics9250_29_device;
extern const device_t ics9250_30_device;
extern const device_t ics9250_32_device;
extern const device_t ics9250_38_device;
extern const device_t ics9250_50_device;
#endif /*EMU_CLOCK_H*/

View File

@@ -55,6 +55,7 @@ extern uint8_t i2c_write(void *bus_handle, uint8_t addr, uint8_t data);
extern void i2c_stop(void *bus_handle, uint8_t addr);
/* i2c_eeprom.c */
extern uint8_t log2i(uint32_t i);
extern void *i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint32_t size, uint8_t writable);
extern void i2c_eeprom_close(void *dev_handle);

View File

@@ -54,7 +54,6 @@
#define MACHINE_PCMCIA 0x00000400 /* sys is AT-compatible laptop with PCMCIA */
#define MACHINE_AGP 0x00000A0C /* sys is AT-compatible with AGP */
#define MACHINE_AGP98 0x00000A10 /* sys is NEC PC-98x1 series with AGP (did that even exist?) */
#define MACHINE_IS_AT 0x00000FCC /* sys is AT-compatible (ISA + ISA16) */
/* Feature flags for miscellaneous internal devices. */
#define MACHINE_VIDEO 0x00001000 /* sys has int video */
#define MACHINE_VIDEO_ONLY 0x00002000 /* sys has fixed video */
@@ -83,7 +82,8 @@
#define MACHINE_SCSI 0x08000000 /* sys has int single SCSI - mark as pri SCSI */
#define MACHINE_SCSI_DUAL 0x18000000 /* sys has int dual SCSI - mark as both pri and sec SCSI */
#define IS_ARCH(m, a) (machines[(m)].flags & (a)) ? 1 : 0;
#define IS_ARCH(m, a) (machines[m].flags & (a)) ? 1 : 0;
#define IS_AT(m) ((machines[m].flags & 0x00000FCC) && !(machines[m].flags & MACHINE_PC98)) ? 1 : 0;
#define MACHINE_MULTIPLIER_FIXED -1, -1
@@ -462,13 +462,14 @@ extern int machine_at_p3bf_init(const machine_t *);
extern int machine_at_bf6_init(const machine_t *);
extern int machine_at_ax6bc_init(const machine_t *);
extern int machine_at_atc6310bxii_init(const machine_t *);
extern int machine_at_ga686bx_init(const machine_t *);
extern int machine_at_686bx_init(const machine_t *);
extern int machine_at_tsunamiatx_init(const machine_t *);
extern int machine_at_p6sba_init(const machine_t *);
#if defined(DEV_BRANCH) && defined(NO_SIO)
extern int machine_at_ergox365_init(const machine_t *);
#endif
extern int machine_at_ficka6130_init(const machine_t *);
extern int machine_at_p3v4x_init(const machine_t *);
#ifdef EMU_DEVICE_H
extern const device_t *at_tsunamiatx_get_device(void);
@@ -490,10 +491,11 @@ extern int machine_at_63a_init(const machine_t *);
extern int machine_at_s370sba_init(const machine_t *);
extern int machine_at_apas3_init(const machine_t *);
extern int machine_at_wcf681_init(const machine_t *);
extern int machine_at_6via85x_init(const machine_t *);
extern int machine_at_cuv4xls_init(const machine_t *);
extern int machine_at_6via90ap_init(const machine_t *);
extern int machine_at_603tcf_init(const machine_t *);
extern int machine_at_trinity371_init(const machine_t *);
extern int machine_at_p6bap_init(const machine_t *);
extern int machine_at_trinity371_init(const machine_t *);
extern int machine_at_p6bap_init(const machine_t *);
/* m_at_misc.c */
extern int machine_at_vpc2007_init(const machine_t *);

View File

@@ -37,6 +37,7 @@
#include "cpu.h"
#include <86box/machine.h>
#include <86box/sound.h>
#include <86box/clock.h>
int
machine_at_p65up5_cpknd_init(const machine_t *model)
@@ -214,6 +215,7 @@ machine_at_p2bls_init(const machine_t *model)
device_add(&piix4e_device);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&w83977ef_device);
device_add(&ics9150_08_device);
device_add(&sst_flash_39sf020_device);
spd_register(SPD_TYPE_SDRAM, 0xF, 256);
device_add(&w83781d_device); /* fans: Chassis, CPU, Power; temperatures: MB, unused, CPU */
@@ -251,6 +253,7 @@ machine_at_p3bf_init(const machine_t *model)
device_add(&piix4e_device);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&w83977ef_device);
device_add(&ics9250_08_device);
device_add(&sst_flash_39sf020_device);
spd_register(SPD_TYPE_SDRAM, 0xF, 256);
device_add(&as99127f_device); /* fans: Chassis, CPU, Power; temperatures: MB, JTPWR, CPU */
@@ -363,11 +366,11 @@ machine_at_atc6310bxii_init(const machine_t *model)
int
machine_at_ga686bx_init(const machine_t *model)
machine_at_686bx_init(const machine_t *model)
{
int ret;
ret = bios_load_linear(L"roms/machines/ga686bx/6BX.F2a",
ret = bios_load_linear(L"roms/machines/686bx/6BX.F2a",
0x000c0000, 262144, 0);
if (bios_only || !ret)
@@ -507,8 +510,8 @@ machine_at_ergox365_init(const machine_t *model)
device_add(&i440bx_device);
device_add(&piix4e_device);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&fdc37c665_device); // Placeholder for the SM(S)C FDC37C675
device_add(&sst_flash_39sf040_device); // Placeholder for the Intel 28F004 flash chip
device_add(&fdc37c665_device); /* Placeholder for the SM(S)C FDC37C675 */
device_add(&sst_flash_39sf040_device); /* Placeholder for the Intel 28F004 flash chip */
spd_register(SPD_TYPE_SDRAM, 0xF, 256);
return ret;
@@ -545,3 +548,39 @@ machine_at_ficka6130_init(const machine_t *model)
return ret;
}
int
machine_at_p3v4x_init(const machine_t *model)
{
int ret;
ret = bios_load_linear(L"roms/machines/p3v4x/1006.004",
0x000c0000, 262144, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x04, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3);
pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3);
pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4);
device_add(&via_apro133a_device);
device_add(&via_vt82c596b_device);
device_add(&w83977ef_device);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&ics9250_18_device);
device_add(&sst_flash_39sf020_device);
spd_register(SPD_TYPE_SDRAM, 0xF, 512);
device_add(&as99127f_device); /* fans: Chassis, CPU, Power; temperatures: MB, JTPWR, CPU */
return ret;
}

View File

@@ -36,6 +36,7 @@
#include <86box/video.h>
#include "cpu.h"
#include <86box/machine.h>
#include <86box/clock.h>
int
machine_at_s370slm_init(const machine_t *model)
@@ -162,6 +163,7 @@ machine_at_cubx_init(const machine_t *model)
device_add(&piix4e_device);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&w83977ef_device);
device_add(&ics9250_08_device);
device_add(&sst_flash_39sf020_device);
spd_register(SPD_TYPE_SDRAM, 0xF, 256);
device_add(&as99127f_device); /* fans: Chassis, CPU, Power; temperatures: MB, JTPWR, CPU */
@@ -334,8 +336,8 @@ machine_at_wcf681_init(const machine_t *model)
{
int ret;
ret = bios_load_linear(L"roms/machines/wcf681/681osda2.bin",
0x000c0000, 262144, 0);
ret = bios_load_linear(L"roms/machines/wcf681/p3tdde.bin",
0x00080000, 524288, 0);
if (bios_only || !ret)
return ret;
@@ -344,7 +346,8 @@ machine_at_wcf681_init(const machine_t *model)
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 0, 0);
pci_register_slot(0x10, PCI_CARD_SOUTHBRIDGE, 1, 2, 0, 0);
pci_register_slot(0x11, PCI_CARD_SOUTHBRIDGE, 1, 2, 0, 0);
pci_register_slot(0x14, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x12, PCI_CARD_NORMAL, 4, 1, 2, 3);
@@ -352,12 +355,12 @@ machine_at_wcf681_init(const machine_t *model)
pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4);
device_add(&via_apro133a_device);
device_add(&via_vt82c596b_device);
device_add(&w83977tf_device);
device_add(&via_vt82c686b_device);
device_add(&via_vt82c686_sio_device);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&sst_flash_39sf020_device);
spd_register(SPD_TYPE_SDRAM, 0x3, 512);
device_add(&w83781d_device); /* fans: CPU, unused, unused; temperatures: System, unused, CPU */
device_add(&via_vt82c686_hwm_device); /* fans: CPU, unused, unused; temperatures: System, unused, CPU */
hwm_values.voltages[1] = 2500; /* +2.5V */
hwm_values.fans[1] = 0; /* unused */
hwm_values.fans[2] = 0; /* unused */
@@ -367,11 +370,48 @@ machine_at_wcf681_init(const machine_t *model)
}
int
machine_at_6via85x_init(const machine_t *model)
machine_at_cuv4xls_init(const machine_t *model)
{
int ret;
ret = bios_load_linear(L"roms/machines/6via85x/6VIA85X_ver_1_1.bin",
ret = bios_load_linear(L"roms/machines/cuv4xls/1005LS.001",
0x000c0000, 262144, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x04, PCI_CARD_SOUTHBRIDGE, 4, 1, 2, 3);
pci_register_slot(0x05, PCI_CARD_SOUND, 3, 0, 0, 0);
pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x07, PCI_CARD_NORMAL, 2, 3, 0, 0);
pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3);
pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4);
device_add(&via_apro133a_device);
device_add(&via_vt82c686b_device);
device_add(&via_vt82c686_sio_device);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&ics9250_18_device);
device_add(&sst_flash_39sf020_device);
spd_register(SPD_TYPE_SDRAM, 0xF, 512);
device_add(&as99127f_device); /* fans: Chassis, CPU, Power; temperatures: MB, JTPWR, CPU */
return ret;
}
int
machine_at_6via90ap_init(const machine_t *model)
{
int ret;
ret = bios_load_linear(L"roms/machines/6via90ap/90ap10.bin",
0x000c0000, 262144, 0);
if (bios_only || !ret)
@@ -407,7 +447,7 @@ machine_at_603tcf_init(const machine_t *model)
{
int ret;
ret = bios_load_linear(L"roms/machines/603tcf/603tcfA4.BIN",
ret = bios_load_linear(L"roms/machines/603tcf/6VX-4X.F8",
0x000c0000, 262144, 0);
if (bios_only || !ret)
@@ -423,11 +463,11 @@ machine_at_603tcf_init(const machine_t *model)
pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3);
pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4);
device_add(&via_vt8601_device);
device_add(&via_vt82c686b_device);
device_add(&via_apro133a_device);
device_add(&via_vt82c686a_device);
device_add(&via_vt82c686_sio_device);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&sst_flash_39sf020_device);
device_add(&sst_flash_29ee020_device);
spd_register(SPD_TYPE_SDRAM, 0x3, 512);
device_add(&via_vt82c686_hwm_device); /* fans: 1, 2; temperatures: CPU, System, unused */
hwm_values.temperatures[0] += 2; /* CPU offset */

View File

@@ -76,7 +76,7 @@ machine_init_ex(int m)
is_vpc = 0;
/* Set up the architecture flags. */
AT = IS_ARCH(machine, (MACHINE_BUS_ISA16 | MACHINE_BUS_MCA | MACHINE_BUS_PCMCIA));
AT = IS_AT(machine);
PCI = IS_ARCH(machine, MACHINE_BUS_PCI);
/* Reset the memory state. */

View File

@@ -272,7 +272,7 @@ const machine_t machines[] = {
{ "[i430HX] SuperMicro Super P55T2S", "p55t2s", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3300, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 768, 8, 127, machine_at_p55t2s_init, NULL },
{ "[i430HX] Acer V35N", "acerv35n", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 192, 8, 127, machine_at_acerv35n_init, NULL },
{ "[i430HX] ASUS P/I-P55T2P4", "p55t2p4", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 75000000, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 256, 8, 127, machine_at_p55t2p4_init, NULL },
{ "[i430HX] ASUS P/I-P55T2P4", "p55t2p4", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 83333333, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 256, 8, 127, machine_at_p55t2p4_init, NULL },
{ "[i430HX] Micronics M7S-Hi", "m7shi", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 128, 8, 511, machine_at_m7shi_init, NULL },
{ "[i430HX] Intel TC430HX", "tc430hx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 128, 8, 255, machine_at_tc430hx_init, NULL },
{ "[i430HX] Toshiba Equium 5200D", "equium5200", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 192, 8, 127, machine_at_equium5200_init, NULL },
@@ -340,7 +340,7 @@ const machine_t machines[] = {
{ "[i440BX] ABIT BF6", "bf6", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 133333333, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 768, 8, 255, machine_at_bf6_init, NULL },
{ "[i440BX] AOpen AX6BC", "ax6bc", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 112121212, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 768, 8, 255, machine_at_ax6bc_init, NULL },
{ "[i440BX] A-Trend ATC6310BXII", "atc6310bxii", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 133333333, 1800, 3500, 3.0, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 768, 8, 255, machine_at_atc6310bxii_init, NULL },
{ "[i440BX] Gigabyte GA-686BX", "ga686bx", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 3.0, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 1024, 8, 255, machine_at_ga686bx_init, NULL },
{ "[i440BX] Gigabyte GA-686BX", "686bx", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 3.0, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 1024, 8, 255, machine_at_686bx_init, NULL },
{ "[i440BX] Tyan Tsunami ATX", "tsunamiatx", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 112121212, 1800, 3500, 3.5, 5.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_SOUND, 8, 1024, 8, 255, machine_at_tsunamiatx_init, at_tsunamiatx_get_device },
{ "[i440BX] SuperMicro Super P6SBA", "p6sba", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 3.0, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 768, 8, 255, machine_at_p6sba_init, NULL },
#if defined(DEV_BRANCH) && defined(NO_SIO)
@@ -352,6 +352,7 @@ const machine_t machines[] = {
/* VIA Apollo Pro */
{ "[VIA Apollo Pro] FIC KA-6130", "ficka6130", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 3.5, 5.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 512, 8, 255, machine_at_ficka6130_init, NULL },
{ "[VIA Apollo Pro133A] ASUS P3V4X", "p3v4x", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 150000000, 1800, 3500, 2.0, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 2048, 8, 255, machine_at_p3v4x_init, NULL },
/* Slot 2 machines(Including Slot 1/2 Hybrids) */
/* 440GX */
@@ -376,7 +377,8 @@ const machine_t machines[] = {
/* VIA Apollo Pro */
{ "[VIA Apollo Pro] PC Partner APAS3", "apas3", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 100000000, 1800, 3500, 3.0, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 768, 8, 255, machine_at_apas3_init, NULL },
{ "[VIA Apollo Pro133A] AEWIN WCF-681", "wcf681", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1800, 3500, 0, 0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 1024, 8, 255, machine_at_wcf681_init, NULL },
{ "[VIA Apollo Pro133A] Acorp 6VIA85X", "6via85x", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1800, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 1536, 8, 255, machine_at_6via85x_init, NULL },
{ "[VIA Apollo Pro133A] ASUS CUV4X-LS", "cuv4xls", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1800, 3500, 2.0, 8.0, (MACHINE_AGP & ~MACHINE_AT) | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16, 1536, 8, 255, machine_at_cuv4xls_init, NULL },
{ "[VIA Apollo Pro133A] Acorp 6VIA90AP", "6via90ap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1800, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 1536, 8, 255, machine_at_6via90ap_init, NULL },
{ "[VIA Apollo Pro133A] ECS P6BAP", "p6bap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1800, 3500, 2.0, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 1536, 8, 255, machine_at_p6bap_init, NULL },
{ "[VIA Apollo ProMedia] Jetway 603TCF", "603tcf", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1800, 3500, 2.0, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 1024, 8, 255, machine_at_603tcf_init, NULL },

View File

@@ -54,35 +54,37 @@ i2c_eeprom_log(const char *fmt, ...)
#endif
uint8_t
static uint8_t
i2c_eeprom_start(void *bus, uint8_t addr, uint8_t read, void *priv)
{
i2c_eeprom_t *dev = (i2c_eeprom_t *) priv;
i2c_eeprom_log("I2C EEPROM %s %02X: start()\n", i2c_getbusname(dev->i2c), dev->addr);
dev->addr_pos = 0;
dev->addr_register = (addr << dev->addr_len) & dev->addr_mask;
if (!read) {
dev->addr_pos = 0;
dev->addr_register = (addr << dev->addr_len) & dev->addr_mask;
}
return 1;
}
uint8_t
static uint8_t
i2c_eeprom_read(void *bus, uint8_t addr, void *priv)
{
i2c_eeprom_t *dev = (i2c_eeprom_t *) priv;
uint8_t ret = dev->data[dev->addr_register];
i2c_eeprom_log("I2C EEPROM %s %02X: read(%06X) = %02X\n", i2c_getbusname(dev->i2c), dev->addr, dev->addr_register, ret);
if (++dev->addr_register > dev->addr_mask) /* roll-over */
dev->addr_register = 0;
dev->addr_register++;
dev->addr_register &= dev->addr_mask; /* roll-over */
return ret;
}
uint8_t
static uint8_t
i2c_eeprom_write(void *bus, uint8_t addr, uint8_t data, void *priv)
{
i2c_eeprom_t *dev = (i2c_eeprom_t *) priv;
@@ -93,14 +95,14 @@ i2c_eeprom_write(void *bus, uint8_t addr, uint8_t data, void *priv)
dev->addr_register &= (1 << dev->addr_len) - 1;
dev->addr_register |= addr << dev->addr_len;
dev->addr_register &= dev->addr_mask;
i2c_eeprom_log("I2C EEPROM %s %02X: write(address, %04X)\n", i2c_getbusname(dev->i2c), dev->addr, dev->addr_register);
i2c_eeprom_log("I2C EEPROM %s %02X: write(address, %06X)\n", i2c_getbusname(dev->i2c), dev->addr, dev->addr_register);
dev->addr_pos += 8;
} else {
i2c_eeprom_log("I2C EEPROM %s %02X: write(%06X, %02X) = %d\n", i2c_getbusname(dev->i2c), dev->addr, dev->addr_register, data, !!dev->writable);
if (dev->writable)
dev->data[dev->addr_register] = data;
if (++dev->addr_register > dev->addr_mask) /* roll-over */
dev->addr_register = 0;
dev->addr_register++;
dev->addr_register &= dev->addr_mask; /* roll-over */
return dev->writable;
}
@@ -108,12 +110,26 @@ i2c_eeprom_write(void *bus, uint8_t addr, uint8_t data, void *priv)
}
uint8_t
log2i(uint32_t i)
{
uint8_t ret = 0;
while ((i >>= 1))
ret++;
return ret;
}
void *
i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint32_t size, uint8_t writable)
{
i2c_eeprom_t *dev = (i2c_eeprom_t *) malloc(sizeof(i2c_eeprom_t));
memset(dev, 0, sizeof(i2c_eeprom_t));
/* Round size up to the next power of 2. */
uint32_t pow_size = 1 << log2i(size);
if (pow_size < size)
size = pow_size << 1;
size &= 0x7fffff; /* address space limit of 8 MB = 7 bits from I2C address + 16 bits */
i2c_eeprom_log("I2C EEPROM %s %02X: init(%d, %d)\n", i2c_getbusname(i2c), addr, size, writable);

View File

@@ -25,6 +25,7 @@
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/version.h>
#include "cpu.h"
#include "x86_ops.h"
#include "x86.h"
@@ -2558,26 +2559,29 @@ mem_reset(void)
}
#endif
if (mem_size > 2097152)
fatal("Attempting to use more than 2 GB of guest RAM\n");
fatal("Attempting to use more than 2 GB of emulated RAM\n");
#if (!(defined __amd64__ || defined _M_X64))
if (mem_size > 1048576) {
ram = (uint8_t *)malloc(1 << 30); /* allocate and clear the RAM block of the first 1 GB */
if (ram == NULL) {
fatal("X86 > 1 GB: Failed to malloc() ram\n");
fatal("Failed to allocate primary RAM block. Make sure you have enough RAM available.\n");
return;
}
memset(ram, 0x00, (1 << 30));
ram2 = (uint8_t *)malloc(m - (1 << 30)); /* allocate and clear the RAM block above 1 GB */
if (ram2 == NULL) {
fatal("X86 > 1 GB: Failed to malloc() ram2\n");
if (config_changed == 2)
fatal(EMU_NAME " must be restarted for the memory amount change to be applied.\n");
else
fatal("Failed to allocate secondary RAM block. Make sure you have enough RAM available.\n");
return;
}
memset(ram2, 0x00, m - (1 << 30));
} else {
ram = (uint8_t *)malloc(m); /* allocate and clear the RAM block */
if (ram == NULL) {
fatal("X86 <= 1 GB: Failed to malloc() ram\n");
fatal("Failed to allocate RAM block. Make sure you have enough RAM available.\n");
return;
}
memset(ram, 0x00, m);
@@ -2585,7 +2589,7 @@ mem_reset(void)
#else
ram = (uint8_t *)malloc(m); /* allocate and clear the RAM block */
if (ram == NULL) {
fatal("X64: Failed to malloc() ram\n");
fatal("Failed to allocate RAM block. Make sure you have enough RAM available.\n");
return;
}
memset(ram, 0x00, m);

View File

@@ -88,16 +88,6 @@ spd_init(const device_t *info)
}
uint8_t
log2_ui16(uint16_t i)
{
uint8_t ret = 0;
while ((i >>= 1))
ret++;
return ret;
}
int
comp_ui16_rev(const void *elem1, const void *elem2)
{
@@ -117,7 +107,7 @@ spd_populate(uint16_t *rows, uint8_t slot_count, uint16_t total_size, uint16_t m
memset(rows, 0, SPD_MAX_SLOTS << 1);
for (row = 0; row < slot_count && total_size; row++) {
/* populate slot */
rows[row] = 1 << log2_ui16(MIN(total_size, max_module_size));
rows[row] = 1 << log2i(MIN(total_size, max_module_size));
if (total_size >= rows[row]) {
spd_log("SPD: Initial row %d = %d MB\n", row, rows[row]);
total_size -= rows[row];
@@ -133,7 +123,7 @@ spd_populate(uint16_t *rows, uint8_t slot_count, uint16_t total_size, uint16_t m
if (enable_asym) {
row = slot_count - 1;
do {
asym = (1 << log2_ui16(MIN(total_size, rows[row])));
asym = (1 << log2i(MIN(total_size, rows[row])));
if (rows[row] + asym <= max_module_size) {
rows[row] += asym;
total_size -= asym;
@@ -151,7 +141,7 @@ spd_populate(uint16_t *rows, uint8_t slot_count, uint16_t total_size, uint16_t m
/* Look for a module to split. */
split = 0;
for (row = 0; row < slot_count; row++) {
if ((rows[row] < (min_module_size << 1)) || (rows[row] != (1 << log2_ui16(rows[row]))))
if ((rows[row] < (min_module_size << 1)) || (rows[row] != (1 << log2i(rows[row]))))
continue; /* no module here, module is too small to be split, or asymmetric module */
/* Find next empty row. */
@@ -224,7 +214,7 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
spd_modules[slot]->size = rows[row];
/* Determine the second row size, from which the first row size can be obtained. */
asym = rows[row] - (1 << log2_ui16(rows[row])); /* separate the powers of 2 */
asym = rows[row] - (1 << log2i(rows[row])); /* separate the powers of 2 */
if (!asym) /* is the module asymmetric? */
asym = rows[row] >> 1; /* symmetric, therefore divide by 2 */
@@ -245,10 +235,10 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
edo_data->bytes_used = 0x80;
edo_data->spd_size = 0x08;
edo_data->mem_type = ram_type;
edo_data->row_bits = SPD_ROLLUP(7 + log2_ui16(spd_modules[slot]->row1)); /* first row */
edo_data->row_bits = SPD_ROLLUP(7 + log2i(spd_modules[slot]->row1)); /* first row */
edo_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 */
edo_data->row_bits |= SPD_ROLLUP(7 + log2_ui16(spd_modules[slot]->row2)) << 4; /* second row, if different from first */
edo_data->row_bits |= SPD_ROLLUP(7 + log2i(spd_modules[slot]->row2)) << 4; /* second row, if different from first */
edo_data->col_bits |= 9 << 4; /* same as first row, but just in case */
}
edo_data->banks = 2;
@@ -281,10 +271,10 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
sdram_data->bytes_used = 0x80;
sdram_data->spd_size = 0x08;
sdram_data->mem_type = ram_type;
sdram_data->row_bits = SPD_ROLLUP(6 + log2_ui16(spd_modules[slot]->row1)); /* first row */
sdram_data->row_bits = SPD_ROLLUP(6 + log2i(spd_modules[slot]->row1)); /* first row */
sdram_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 */
sdram_data->row_bits |= SPD_ROLLUP(6 + log2_ui16(spd_modules[slot]->row2)) << 4; /* second row, if different from first */
sdram_data->row_bits |= SPD_ROLLUP(6 + log2i(spd_modules[slot]->row2)) << 4; /* second row, if different from first */
sdram_data->col_bits |= 9 << 4; /* same as first row, but just in case */
}
sdram_data->rows = 2;
@@ -306,10 +296,10 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
sdram_data->trp = sdram_data->trrd = sdram_data->trcd = sdram_data->tras = 1;
if (spd_modules[slot]->row1 != spd_modules[slot]->row2) {
/* Utilities interpret bank_density a bit differently on asymmetric modules. */
sdram_data->bank_density = 1 << (log2_ui16(spd_modules[slot]->row1 >> 1) - 2); /* first row */
sdram_data->bank_density |= 1 << (log2_ui16(spd_modules[slot]->row2 >> 1) - 2); /* second row */
sdram_data->bank_density = 1 << (log2i(spd_modules[slot]->row1 >> 1) - 2); /* first row */
sdram_data->bank_density |= 1 << (log2i(spd_modules[slot]->row2 >> 1) - 2); /* second row */
} else {
sdram_data->bank_density = 1 << (log2_ui16(spd_modules[slot]->row1 >> 1) - 1); /* symmetric module = only one bit is set */
sdram_data->bank_density = 1 << (log2i(spd_modules[slot]->row1 >> 1) - 1); /* symmetric module = only one bit is set */
}
sdram_data->ca_setup = sdram_data->data_setup = 0x15;
sdram_data->ca_hold = sdram_data->data_hold = 0x08;
@@ -355,7 +345,7 @@ spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit
/* No SPD: split SIMMs into pairs as if they were "DIMM"s. */
if (!spd_present) {
dimm = ((reg_max - reg_min) + 1) >> 1; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */
spd_populate(rows, dimm, mem_size >> 10, drb_unit, 1 << (log2_ui16(machines[machine].max_ram / dimm)), 0);
spd_populate(rows, dimm, mem_size >> 10, drb_unit, 1 << (log2i(machines[machine].max_ram / dimm)), 0);
}
/* Write DRBs for each row. */

View File

@@ -147,7 +147,7 @@ onesec_timer(void *priv)
if (++nvr->onesec_cnt >= 100) {
/* Update the internal clock. */
is_at = IS_ARCH(machine, (MACHINE_BUS_ISA16 | MACHINE_BUS_MCA | MACHINE_BUS_PCMCIA));
is_at = IS_AT(machine);
if (!is_at)
rtc_tick();

View File

@@ -180,7 +180,7 @@ find_best_interrupt(pic_t *dev)
dev->interrupt = (ret == -1) ? 7 : ret;
is_at = IS_ARCH(machine, (MACHINE_BUS_ISA16 | MACHINE_BUS_MCA | MACHINE_BUS_PCMCIA));
is_at = IS_AT(machine);
if (is_at && (ret != -1) && (cpu_fast_off_flags & (1 << dev->interrupt)))
cpu_fast_off_count = cpu_fast_off_val + 1;
@@ -191,7 +191,7 @@ find_best_interrupt(pic_t *dev)
static __inline void
pic_update_pending(void)
{
int is_at = IS_ARCH(machine, (MACHINE_BUS_ISA16 | MACHINE_BUS_MCA | MACHINE_BUS_PCMCIA));
int is_at = IS_AT(machine);
if (is_at) {
pic2.int_pending = (find_best_interrupt(&pic2) != -1);
@@ -231,7 +231,7 @@ pic_callback(void *priv)
void
pic_reset()
{
int is_at = IS_ARCH(machine, (MACHINE_BUS_ISA16 | MACHINE_BUS_MCA | MACHINE_BUS_PCMCIA));
int is_at = IS_AT(machine);
memset(&pic, 0, sizeof(pic_t));
memset(&pic2, 0, sizeof(pic_t));
@@ -497,7 +497,7 @@ picint_common(uint16_t num, int level, int set)
int is_at;
uint8_t b, slaves = 0;
is_at = IS_ARCH(machine, (MACHINE_BUS_ISA16 | MACHINE_BUS_MCA | MACHINE_BUS_PCMCIA));
is_at = IS_AT(machine);
/* Make sure to ignore all slave IRQ's, and in case of AT+,
translate IRQ 2 to IRQ 9. */

View File

@@ -1846,7 +1846,7 @@ static const device_config_t BT958D_Config[] = {
};
const device_t buslogic_542b_1991_device = {
"Buslogic BT-542B ISA",
"BusLogic BT-542B ISA",
DEVICE_ISA | DEVICE_AT,
CHIP_BUSLOGIC_ISA_542_1991,
buslogic_init, x54x_close, NULL,
@@ -1855,7 +1855,7 @@ const device_t buslogic_542b_1991_device = {
};
const device_t buslogic_device = {
"Buslogic BT-542BH ISA",
"BusLogic BT-542BH ISA",
DEVICE_ISA | DEVICE_AT,
CHIP_BUSLOGIC_ISA_542,
buslogic_init, x54x_close, NULL,
@@ -1864,7 +1864,7 @@ const device_t buslogic_device = {
};
const device_t buslogic_545s_device = {
"Buslogic BT-545S ISA",
"BusLogic BT-545S ISA",
DEVICE_ISA | DEVICE_AT,
CHIP_BUSLOGIC_ISA,
buslogic_init, x54x_close, NULL,
@@ -1873,7 +1873,7 @@ const device_t buslogic_545s_device = {
};
const device_t buslogic_640a_device = {
"Buslogic BT-640A MCA",
"BusLogic BT-640A MCA",
DEVICE_MCA,
CHIP_BUSLOGIC_MCA,
buslogic_init, x54x_close, NULL,
@@ -1882,7 +1882,7 @@ const device_t buslogic_640a_device = {
};
const device_t buslogic_445s_device = {
"Buslogic BT-445S VLB",
"BusLogic BT-445S VLB",
DEVICE_VLB,
CHIP_BUSLOGIC_VLB,
buslogic_init, x54x_close, NULL,
@@ -1891,7 +1891,7 @@ const device_t buslogic_445s_device = {
};
const device_t buslogic_pci_device = {
"Buslogic BT-958D PCI",
"BusLogic BT-958D PCI",
DEVICE_PCI,
CHIP_BUSLOGIC_PCI,
buslogic_init, x54x_close, NULL,

View File

@@ -1529,7 +1529,7 @@ ncr53c8xx_reg_writeb(ncr53c8xx_t *dev, uint32_t offset, uint8_t val)
case 0x07: /* GPREG */
ncr53c8xx_log("NCR 810: GPREG write %02X\n", val);
dev->gpreg = val;
i2c_gpio_set(dev->i2c, !!(dev->gpreg & 0x02), !!(dev->gpreg & 0x01));
i2c_gpio_set(dev->i2c, (dev->gpreg & 0x02) || ((dev->gpcntl & 0x82) == 0x02), (dev->gpreg & 0x01) || ((dev->gpcntl & 0x41) == 0x01));
break;
case 0x08: /* SFBR */
/* The CPU is not allowed to write to this register. However the

View File

@@ -25,10 +25,29 @@
#include <86box/i2c.h>
#define STD_TIMING(idx, width, aspect_ratio) do { \
edid->standard_timings[idx].horiz_pixels = ((width) >> 3) - 31; \
edid->standard_timings[idx].aspect_ratio_refresh_rate = (aspect_ratio) << 6; /* 60 Hz */ \
} while (0)
#define PIXEL_MM(px) ((uint16_t) (((px) * 25.4) / 96))
#define STANDARD_TIMING(slot, width, aspect_ratio, refresh) do { \
edid->slot.horiz_pixels = ((width) >> 3) - 31; \
edid->slot.aspect_ratio_refresh_rate = ((aspect_ratio) << 6) | ((refresh) - 60); \
} while (0)
#define DETAILED_TIMING(slot, clk, width, height, hblank, vblank, hfp, hsp, vfp, vsp) do { \
edid->slot.pixel_clock_lsb = ((clk) / 10) & 0xff; \
edid->slot.pixel_clock_msb = ((clk) / 10) >> 8; \
edid->slot.h_active_lsb = (width) & 0xff; \
edid->slot.h_blank_lsb = (hblank) & 0xff; \
edid->slot.h_active_blank_msb = (((width) >> 4) & 0xf0) | (((hblank) >> 8) & 0x0f); \
edid->slot.v_active_lsb = (height) & 0xff; \
edid->slot.v_blank_lsb = (vblank) & 0xff; \
edid->slot.v_active_blank_msb = (((height) >> 4) & 0xf0) | (((vblank) >> 8) & 0x0f); \
edid->slot.h_front_porch_lsb = (hfp) & 0xff; \
edid->slot.h_sync_pulse_lsb = (hsp) & 0xff; \
edid->slot.v_front_porch_sync_pulse_lsb = (((vfp) & 0x0f) << 4) | ((vsp) & 0x0f); \
edid->slot.hv_front_porch_sync_pulse_msb = (((hfp) >> 2) & 0xc0) | (((hsp) >> 4) & 0x30) | (((vfp) >> 2) & 0x0c) | (((vsp) >> 4) & 0x03); \
edid->slot.h_size_lsb = horiz_mm & 0xff; \
edid->slot.v_size_lsb = vert_mm & 0xff; \
edid->slot.hv_size_msb = ((horiz_mm >> 4) & 0xf0) | ((vert_mm >> 8) & 0x0f); \
} while (0)
enum {
STD_ASPECT_16_10 = 0x0,
@@ -114,6 +133,9 @@ ddc_init(void *i2c)
edid_t *edid = malloc(sizeof(edid_t));
memset(edid, 0, sizeof(edid_t));
uint8_t *edid_bytes = (uint8_t *) edid;
uint16_t horiz_mm = PIXEL_MM(1366), vert_mm = PIXEL_MM(768);
memset(&edid->magic[1], 0xff, sizeof(edid->magic) - 2);
edid->mfg[0] = 0x09; /* manufacturer "BOX" (apparently unassigned by UEFI) */
@@ -121,11 +143,12 @@ ddc_init(void *i2c)
edid->mfg_week = 48;
edid->mfg_year = 2020 - 1990;
edid->edid_version = 0x01;
edid->edid_rev = 0x04; /* EDID 1.4 */
edid->edid_rev = 0x03; /* EDID 1.3 */
edid->input_params = 0x0e; /* analog input; separate sync; composite sync; sync on green */
edid->horiz_size = ((4.0 / 3.0) * 100) - 99; /* landscape 4:3 */
edid->features = 0x09; /* RGB color; GTF/CVT */
edid->horiz_size = horiz_mm / 10;
edid->vert_size = vert_mm / 10;
edid->features = 0x0b; /* RGB color; first timing is preferred; GTF/CVT */
edid->red_green_lsb = 0x81;
edid->blue_white_lsb = 0xf1;
@@ -140,34 +163,23 @@ ddc_init(void *i2c)
memset(&edid->established_timings, 0xff, sizeof(edid->established_timings)); /* all enabled */
#if 0
memset(&edid->standard_timings, 0x01, sizeof(edid->standard_timings)); /* pad unused entries */
#endif
STD_TIMING(0, 1280, STD_ASPECT_16_9); /* 1280x720 */
STD_TIMING(1, 1280, STD_ASPECT_16_10); /* 1280x800 */
STD_TIMING(2, 1366, STD_ASPECT_16_9); /* 1360x768 (closest to 1366x768) */
STD_TIMING(3, 1440, STD_ASPECT_16_10); /* 1440x900 */
STD_TIMING(4, 1600, STD_ASPECT_16_9); /* 1600x900 */
STD_TIMING(5, 1680, STD_ASPECT_16_10); /* 1680x1050 */
STD_TIMING(6, 1920, STD_ASPECT_16_9); /* 1920x1080 */
STD_TIMING(7, 2048, STD_ASPECT_4_3); /* 2048x1536 */
/* 60 Hz timings */
STANDARD_TIMING(standard_timings[0], 1280, STD_ASPECT_16_9, 60); /* 1280x720 */
STANDARD_TIMING(standard_timings[1], 1280, STD_ASPECT_16_10, 60); /* 1280x800 */
STANDARD_TIMING(standard_timings[2], 1366, STD_ASPECT_16_9, 60); /* 1360x768 (closest to 1366x768) */
STANDARD_TIMING(standard_timings[3], 1440, STD_ASPECT_16_10, 60); /* 1440x900 */
STANDARD_TIMING(standard_timings[4], 1600, STD_ASPECT_16_9, 60); /* 1600x900 */
STANDARD_TIMING(standard_timings[5], 1680, STD_ASPECT_16_10, 60); /* 1680x1050 */
STANDARD_TIMING(standard_timings[6], 1920, STD_ASPECT_16_9, 60); /* 1920x1080 */
STANDARD_TIMING(standard_timings[7], 2048, STD_ASPECT_4_3, 60); /* 2048x1536 */
/* Detailed timings for the preferred mode of 800x600 @ 60 Hz */
edid->detailed_timings[0].pixel_clock_lsb = 4000 & 0xff; /* 40.000 MHz */
edid->detailed_timings[0].pixel_clock_msb = 4000 >> 8;
edid->detailed_timings[0].h_active_lsb = 800 & 0xff;
edid->detailed_timings[0].h_blank_lsb = 256 & 0xff;
edid->detailed_timings[0].h_active_blank_msb = ((800 >> 4) & 0xf0) | ((256 >> 8) & 0x0f);
edid->detailed_timings[0].v_active_lsb = 600 & 0xff;
edid->detailed_timings[0].v_blank_lsb = 28;
edid->detailed_timings[0].v_active_blank_msb = (600 >> 4) & 0xf0;
edid->detailed_timings[0].h_front_porch_lsb = 40;
edid->detailed_timings[0].h_sync_pulse_lsb = 128;
edid->detailed_timings[0].v_front_porch_sync_pulse_lsb = (1 << 4) | 4;
/* Detailed timing for the preferred mode of 800x600 @ 60 Hz */
DETAILED_TIMING(detailed_timings[0], 40000, 800, 600, 256, 28, 40, 128, 1, 4);
edid->descriptors[1].tag = 0xf7; /* established timings 3 */
edid->descriptors[1].established_timings3.version = 0x0a;
memset(&edid->descriptors[1].established_timings3.timings, 0xff, sizeof(edid->descriptors[1].established_timings3.timings)); /* all enabled */
edid->descriptors[1].established_timings3.timings[5] &= 0xf0; /* reserved bits */
edid->descriptors[2].tag = 0xfc; /* display name */
memcpy(&edid->descriptors[2].ascii, "86Box Monitor", 13); /* exactly 13 characters (would otherwise require LF termination and space padding) */
@@ -182,10 +194,30 @@ ddc_init(void *i2c)
edid->descriptors[3].range_limits.padding[0] = 0x0a;
memset(&edid->descriptors[3].range_limits.padding[1], 0x20, sizeof(edid->descriptors[3].range_limits.padding) - 1);
uint8_t *edid_bytes = (uint8_t *) edid;
edid->extensions = 1;
for (uint8_t c = 0; c < 127; c++)
edid->checksum += edid_bytes[c];
edid->checksum = 256 - edid->checksum;
edid->ext_tag = 0x02;
edid->ext_rev = 0x03;
edid->ext_native_dtds = 0x80; /* underscans IT; no native extended modes */
edid->ext_dtd_offset = 0x04;
/* Detailed timing for 1366x768 */
DETAILED_TIMING(ext_detailed_timings[0], 85500, 1366, 768, 426, 30, 70, 143, 3, 3);
/* High refresh rate timings (VGA is limited to 85 Hz) */
edid->ext_descriptors[1].tag = 0xfa; /* standard timing identifiers */
#define ext_standard_timings0 ext_descriptors[1].ext_standard_timings.timings
STANDARD_TIMING(ext_standard_timings0[0], 640, STD_ASPECT_4_3, 90); /* 640x480 @ 90 Hz */
STANDARD_TIMING(ext_standard_timings0[1], 640, STD_ASPECT_4_3, 120); /* 640x480 @ 120 Hz */
STANDARD_TIMING(ext_standard_timings0[2], 800, STD_ASPECT_4_3, 90); /* 800x600 @ 90 Hz */
STANDARD_TIMING(ext_standard_timings0[3], 800, STD_ASPECT_4_3, 120); /* 800x600 @ 120 Hz */
STANDARD_TIMING(ext_standard_timings0[4], 1024, STD_ASPECT_4_3, 90); /* 1024x768 @ 90 Hz */
STANDARD_TIMING(ext_standard_timings0[5], 1280, STD_ASPECT_5_4, 90); /* 1280x1024 @ 90 Hz */
edid->ext_descriptors[1].ext_standard_timings.padding = 0x0a;
for (uint8_t c = 128; c < 255; c++)
edid->checksum2 += edid_bytes[c];
edid->checksum2 = 256 - edid->checksum2;

View File

@@ -618,7 +618,7 @@ MAINOBJ := pc.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \
usb.o device.o nvr.o nvr_at.o nvr_ps2.o \
$(VNCOBJ)
MEMOBJ := catalyst_flash.o intel_flash.o mem.o rom.o smram.o spd.o sst_flash.o
MEMOBJ := catalyst_flash.o i2c_eeprom.o intel_flash.o mem.o rom.o smram.o spd.o sst_flash.o
CPUOBJ := cpu.o cpu_table.o \
808x.o 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o $(CGTOBJ) \
@@ -649,8 +649,8 @@ MCHOBJ := machine.o machine_table.o \
m_at_misc.o
DEVOBJ := bugger.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 vpc2007.o \
i2c.o i2c_eeprom.o i2c_gpio.o smbus_piix4.o \
lpt.o pci_bridge.o postcard.o serial.o vpc2007.o clock_ics9xxx.o \
i2c.o i2c_gpio.o smbus_piix4.o \
keyboard.o \
keyboard_xt.o keyboard_at.o \
mouse.o \

View File

@@ -621,7 +621,7 @@ win_settings_save(void)
}
/* Mark configuration as changed. */
config_changed = 1;
config_changed = 2;
pc_reset_hard_init();
}
@@ -782,7 +782,7 @@ win_settings_machine_recalc_machine(HWND hdlg)
accel.nSec = 0;
accel.nInc = machines[temp_machine].ram_granularity;
SendMessage(h, UDM_SETACCEL, 1, (LPARAM)&accel);
is_at = IS_ARCH(temp_machine, (MACHINE_BUS_ISA16 | MACHINE_BUS_MCA | MACHINE_BUS_PCMCIA));
is_at = IS_AT(temp_machine);
if (!is_at || (machines[temp_machine].ram_granularity >= 128)) {
SendMessage(h, UDM_SETPOS, 0, temp_mem_size);
h = GetDlgItem(hdlg, IDC_TEXT_MB);
@@ -989,7 +989,7 @@ win_settings_machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
temp_mem_size = machines[temp_machine].min_ram;
else if (temp_mem_size > machines[temp_machine].max_ram)
temp_mem_size = machines[temp_machine].max_ram;
is_at = IS_ARCH(temp_machine, (MACHINE_BUS_ISA16 | MACHINE_BUS_MCA | MACHINE_BUS_PCMCIA));
is_at = IS_AT(temp_machine);
if (is_at && (machines[temp_machine].ram_granularity < 128))
temp_mem_size *= 1024;
free(stransi);
@@ -1616,7 +1616,7 @@ win_settings_storage_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
settings_enable_window(hdlg, IDC_COMBO_SCSI, d);
settings_enable_window(hdlg, IDC_CONFIGURE_SCSI, scsi_card_has_config(temp_scsi_card));
is_at = IS_ARCH(temp_machine, (MACHINE_BUS_ISA16 | MACHINE_BUS_MCA | MACHINE_BUS_PCMCIA));
is_at = IS_AT(temp_machine);
settings_enable_window(hdlg, IDC_CHECK_IDE_TER, is_at);
settings_enable_window(hdlg, IDC_BUTTON_IDE_TER, is_at && temp_ide_ter);
settings_enable_window(hdlg, IDC_CHECK_IDE_QUA, is_at);