diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 38afdda57..ef0878b46 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -32,10 +32,15 @@ #ifdef RELEASE_BUILD #define EMU_VERSION "2.07" #define EMU_VERSION_W L"2.07" +#define EMU_VERSION_MAJ 2 +#define EMU_VERSION_MIN 7 #else #define EMU_VERSION "2.10" #define EMU_VERSION_W L"2.10" +#define EMU_VERSION_MAJ 2 +#define EMU_VERSION_MIN 10 #endif +#define COPYRIGHT_YEAR "2020" /* Filename and pathname info. */ #define CONFIG_FILE L"86box.cfg" diff --git a/src/include/86box/smbus.h b/src/include/86box/smbus.h index 058b70ffc..6923a7edb 100644 --- a/src/include/86box/smbus.h +++ b/src/include/86box/smbus.h @@ -24,7 +24,7 @@ extern void smbus_sethandler(uint8_t base, int size, uint8_t (*read_byte)(uint8_t addr, void *priv), uint8_t (*read_byte_cmd)(uint8_t addr, uint8_t cmd, void *priv), uint16_t (*read_word_cmd)(uint8_t addr, uint8_t cmd, void *priv), - uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv), + uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), void (*write_byte)(uint8_t addr, uint8_t val, void *priv), void (*write_byte_cmd)(uint8_t addr, uint8_t cmd, uint8_t val, void *priv), void (*write_word_cmd)(uint8_t addr, uint8_t cmd, uint16_t val, void *priv), @@ -35,7 +35,7 @@ extern void smbus_removehandler(uint8_t base, int size, uint8_t (*read_byte)(uint8_t addr, void *priv), uint8_t (*read_byte_cmd)(uint8_t addr, uint8_t cmd, void *priv), uint16_t (*read_word_cmd)(uint8_t addr, uint8_t cmd, void *priv), - uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv), + uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), void (*write_byte)(uint8_t addr, uint8_t val, void *priv), void (*write_byte_cmd)(uint8_t addr, uint8_t cmd, uint8_t val, void *priv), void (*write_word_cmd)(uint8_t addr, uint8_t cmd, uint16_t val, void *priv), @@ -46,7 +46,7 @@ extern void smbus_handler(int set, uint8_t base, int size, uint8_t (*read_byte)(uint8_t addr, void *priv), uint8_t (*read_byte_cmd)(uint8_t addr, uint8_t cmd, void *priv), uint16_t (*read_word_cmd)(uint8_t addr, uint8_t cmd, void *priv), - uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv), + uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), void (*write_byte)(uint8_t addr, uint8_t val, void *priv), void (*write_byte_cmd)(uint8_t addr, uint8_t cmd, uint8_t val, void *priv), void (*write_word_cmd)(uint8_t addr, uint8_t cmd, uint16_t val, void *priv), @@ -57,7 +57,7 @@ extern uint8_t smbus_has_device(uint8_t addr); extern uint8_t smbus_read_byte(uint8_t addr); extern uint8_t smbus_read_byte_cmd(uint8_t addr, uint8_t cmd); extern uint16_t smbus_read_word_cmd(uint8_t addr, uint8_t cmd); -extern uint8_t smbus_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data); +extern uint8_t smbus_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len); extern void smbus_write_byte(uint8_t addr, uint8_t val); extern void smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val); extern void smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val); diff --git a/src/include/86box/spd.h b/src/include/86box/spd.h index c2549fe95..098fb3ed7 100644 --- a/src/include/86box/spd.h +++ b/src/include/86box/spd.h @@ -47,6 +47,16 @@ #define SPD_SDR_ATTR_VCC_HI_5 0x20 +typedef struct _spd_ { + const device_t *info; + uint8_t slot; + uint16_t size; + uint16_t row1; + uint16_t row2; + + uint8_t addr_register; +} spd_t; + typedef struct _spd_edo_ { uint8_t bytes_used, spd_size, mem_type, row_bits, col_bits, banks, @@ -72,7 +82,7 @@ typedef struct _spd_sdram_ { signal_level, tclk, tac, config, refresh_rate, sdram_width, ecc_width, - tccd, burst, banks, cas, cs, we, + tccd, burst, banks, cas, cslat, we, mod_attr, dev_attr, tclk2, tac2, tclk3, tac3, trp, trrd, trcd, tras, @@ -90,6 +100,9 @@ typedef struct _spd_sdram_ { } spd_sdram_t; +extern spd_t *spd_devices[SPD_MAX_SLOTS]; + + extern void spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size); diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 6c13e6542..401b4e305 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -114,7 +114,7 @@ machine_at_6bxc_init(const machine_t *model) device_add(&keyboard_ps2_pci_device); device_add(&um8669f_device); /*ITE 8671*/ device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0xF, 256); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); return ret; } @@ -269,7 +269,7 @@ machine_at_bf6_init(const machine_t *model) device_add(&keyboard_ps2_pci_device); device_add(&w83977ef_device); device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0xF, 256); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); return ret; } @@ -277,7 +277,12 @@ machine_at_bf6_init(const machine_t *model) int machine_at_p6sba_init(const machine_t *model) { - + /* + AMI 440BX Board. + doesn't like the i686 CPU's. + 10 -> D3 -> D1 POST. Probably KBC related. + */ + int ret; ret = bios_load_linear(L"roms/machines/p6sba/SBAB21.ROM", @@ -303,8 +308,35 @@ machine_at_p6sba_init(const machine_t *model) device_add(&w83977tf_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&intel_flash_bxt_device); - spd_register(SPD_TYPE_SDRAM, 0xF, 256); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + hwm_values_t machine_hwm = { + { /* fan speeds */ + 3000, /* Chassis */ + 3000, /* CPU */ + 3000, /* Power */ + 0 + }, { /* temperatures */ + 30, /* MB */ + 0, /* unused */ + 28, /* CPU */ + 0 + }, { /* voltages */ + 2050, /* VCORE (2.05V by default) */ + 0, /* unused */ + 3300, /* +3.3V */ + RESISTOR_DIVIDER(5000, 11, 16), /* +5V (divider values bruteforced) */ + RESISTOR_DIVIDER(12000, 28, 10), /* +12V (28K/10K divider suggested in the W83781D datasheet) */ + RESISTOR_DIVIDER(12000, 853, 347), /* -12V (divider values bruteforced) */ + RESISTOR_DIVIDER(5000, 1, 2), /* -5V (divider values bruteforced) */ + 0 + } + }; + if (model->cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type == CPU_PENTIUM2) + machine_hwm.voltages[0] = 2800; /* set higher VCORE (2.8V) for Klamath */ + hwm_set_values(machine_hwm); + device_add(&w83781d_device); + return ret; } @@ -339,7 +371,7 @@ machine_at_tsunamiatx_init(const machine_t *model) device_add(&pc87306_device); //PC87309 device_add(&keyboard_ps2_ami_pci_device); device_add(&intel_flash_bxt_device); - spd_register(SPD_TYPE_SDRAM, 0x3, 256); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); return ret; } diff --git a/src/machine/m_at_slot2.c b/src/machine/m_at_slot2.c index 00ac79442..1e220a000 100644 --- a/src/machine/m_at_slot2.c +++ b/src/machine/m_at_slot2.c @@ -46,7 +46,13 @@ int machine_at_s2dge_init(const machine_t *model) { - /* 440GX AMI Slot 2 motherboard */ + /* + 440GX AMI Slot 2 motherboard + + This board under a i686 CPU freezes on POST code D0. + According to the manual it has to do with the NMI which + seems to be related on the I/O APIC. Works fine under a VIA C3. + */ int ret; ret = bios_load_linear(L"roms/machines/s2dge/2gu7301.rom", @@ -67,13 +73,41 @@ machine_at_s2dge_init(const machine_t *model) pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&i440bx_device); /* i440GX */ - device_add(&piix4_device); + device_add(&piix4e_device); device_add(&keyboard_ps2_ami_pci_device); - device_add(&w83977f_device); + device_add(&w83977tf_device); device_add(&intel_flash_bxt_device); - spd_register(SPD_TYPE_SDRAM, 0xF, 256); + spd_register(SPD_TYPE_SDRAM, 0xF, 256); + hwm_values_t machine_hwm = { + { /* fan speeds */ + 3000, /* Chassis */ + 3000, /* CPU */ + 3000, /* Power */ + 0 + }, { /* temperatures */ + 30, /* MB */ + 0, /* unused */ + 28, /* CPU */ + 0 + }, { /* voltages */ + 2050, /* VCORE (2.05V by default) */ + 0, /* unused */ + 3300, /* +3.3V */ + RESISTOR_DIVIDER(5000, 11, 16), /* +5V (divider values bruteforced) */ + RESISTOR_DIVIDER(12000, 28, 10), /* +12V (28K/10K divider suggested in the W83781D datasheet) */ + RESISTOR_DIVIDER(12000, 853, 347), /* -12V (divider values bruteforced) */ + RESISTOR_DIVIDER(5000, 1, 2), /* -5V (divider values bruteforced) */ + 0 + } + }; + if (model->cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type == CPU_PENTIUM2) + machine_hwm.voltages[0] = 2800; /* set higher VCORE (2.8V) for Klamath */ + hwm_set_values(machine_hwm); + device_add(&w83781d_device); + return ret; } #endif \ No newline at end of file diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 1c33f6e4c..ed93d9266 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -65,13 +65,40 @@ machine_at_s370slm_init(const machine_t *model) pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - device_add(&i440bx_device); + device_add(&i440bx_device); /*i440LX*/ device_add(&piix4e_device); device_add(&w83977tf_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&intel_flash_bxt_device); - spd_register(SPD_TYPE_SDRAM, 0xF, 256); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + hwm_values_t machine_hwm = { + { /* fan speeds */ + 3000, /* Chassis */ + 3000, /* CPU */ + 3000, /* Power */ + 0 + }, { /* temperatures */ + 30, /* MB */ + 0, /* unused */ + 28, /* CPU */ + 0 + }, { /* voltages */ + 2050, /* VCORE (2.05V by default) */ + 0, /* unused */ + 3300, /* +3.3V */ + RESISTOR_DIVIDER(5000, 11, 16), /* +5V (divider values bruteforced) */ + RESISTOR_DIVIDER(12000, 28, 10), /* +12V (28K/10K divider suggested in the W83781D datasheet) */ + RESISTOR_DIVIDER(12000, 853, 347), /* -12V (divider values bruteforced) */ + RESISTOR_DIVIDER(5000, 1, 2), /* -5V (divider values bruteforced) */ + 0 + } + }; + if (model->cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type == CPU_PENTIUM2) + machine_hwm.voltages[0] = 2800; /* set higher VCORE (2.8V) for Klamath */ + hwm_set_values(machine_hwm); + device_add(&w83781d_device); + return ret; } #endif diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 02d0f653e..7be984c60 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -231,7 +231,7 @@ const machine_t machines[] = { /* 430FX */ { "[Socket 7-3V FX] ASUS P/I-P54TP4XE", "p54tp4xe", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL }, { "[Socket 7-3V FX] QDI Chariot", "chariot", MACHINE_CPUS_PENTIUM_S73VCH, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_chariot_init, NULL }, - { "[Socket 7-3V FX] MR 430FX clone", "mr586", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_mr586_init, NULL }, + { "[Socket 7-3V FX] MR 430FX clone", "mr586", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_PS2, 8, 128, 8, 127, machine_at_mr586_init, NULL }, { "[Socket 7-3V FX] Intel Advanced/ATX", "thor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL }, { "[Socket 7-3V FX] Intel Advanced/EV", "endeavor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device }, { "[Socket 7-3V FX] MR Intel Advanced/ATX", "mrthor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_mrthor_init, NULL }, @@ -314,15 +314,13 @@ const machine_t machines[] = { /* Slot 2 machines */ /* 440GX */ #if defined(DEV_BRANCH) && defined(NO_SIO) - /*The C3 is meant only for the board to boot due to AMI issues with i686. - Remove after that issue is resolved*/ { "[Slot 2 GX] Supermicro S2DGE", "s2dge", {{"Intel", cpus_Xeon}, {"Intel/PGA370", cpus_Celeron},{"VIA", cpus_Cyrix3},{"", NULL},{"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_s2dge_init, NULL }, #endif /* PGA370 machines */ /* 440LX */ #if defined(DEV_BRANCH) && defined(NO_SIO) - { "[Socket 370 BX] Supermicro S370SLM", "s370slm", {{"Intel", cpus_Celeron}, {"VIA", cpus_Cyrix3}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_s370slm_init, NULL }, + { "[Socket 370 BX] Supermicro S370SLM", "s370slm", {{"Intel", cpus_Celeron}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 255, machine_at_s370slm_init, NULL }, #endif /* 440BX */ { "[Socket 370 BX] ASUS CUBX", "cubx", {{"Intel", cpus_Celeron}, {"VIA", cpus_Cyrix3}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_cubx_init, NULL }, diff --git a/src/smbus.c b/src/smbus.c index d24435cc7..fdb98ea78 100644 --- a/src/smbus.c +++ b/src/smbus.c @@ -33,7 +33,7 @@ typedef struct _smbus_ { uint8_t (*read_byte)(uint8_t addr, void *priv); uint8_t (*read_byte_cmd)(uint8_t addr, uint8_t cmd, void *priv); uint16_t (*read_word_cmd)(uint8_t addr, uint8_t cmd, void *priv); - uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv); + uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv); void (*write_byte)(uint8_t addr, uint8_t val, void *priv); void (*write_byte_cmd)(uint8_t addr, uint8_t cmd, uint8_t val, void *priv); @@ -73,7 +73,7 @@ smbus_log(const char *fmt, ...) static uint8_t smbus_null_read_byte(uint8_t addr, void *priv) { smbus_log("SMBus: read_byte(%02x)\n", addr); return(0xff); } static uint8_t smbus_null_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv) { smbus_log("SMBus: read_byte_cmd(%02x, %02x)\n", addr, cmd); return(0xff); } static uint16_t smbus_null_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv) { smbus_log("SMBus: read_word_cmd(%02x, %02x)\n", addr, cmd); return(0xffff); } -static uint8_t smbus_null_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv) { smbus_log("SMBus: read_block_cmd(%02x, %02x)\n", addr, cmd); return(0x00); }; +static uint8_t smbus_null_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv) { smbus_log("SMBus: read_block_cmd(%02x, %02x)\n", addr, cmd); return(0x00); }; static void smbus_null_write_byte(uint8_t addr, uint8_t val, void *priv) { smbus_log("SMBus: write_byte(%02x, %02x)\n", addr, val); } static void smbus_null_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv) { smbus_log("SMBus: write_byte_cmd(%02x, %02x, %02x)\n", addr, cmd, val); } static void smbus_null_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv) { smbus_log("SMBus: write_word_cmd(%02x, %02x, %04x)\n", addr, cmd, val); } @@ -135,7 +135,7 @@ smbus_sethandler(uint8_t base, int size, uint8_t (*read_byte)(uint8_t addr, void *priv), uint8_t (*read_byte_cmd)(uint8_t addr, uint8_t cmd, void *priv), uint16_t (*read_word_cmd)(uint8_t addr, uint8_t cmd, void *priv), - uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv), + uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), void (*write_byte)(uint8_t addr, uint8_t val, void *priv), void (*write_byte_cmd)(uint8_t addr, uint8_t cmd, uint8_t val, void *priv), void (*write_word_cmd)(uint8_t addr, uint8_t cmd, uint16_t val, void *priv), @@ -180,7 +180,7 @@ smbus_removehandler(uint8_t base, int size, uint8_t (*read_byte)(uint8_t addr, void *priv), uint8_t (*read_byte_cmd)(uint8_t addr, uint8_t cmd, void *priv), uint16_t (*read_word_cmd)(uint8_t addr, uint8_t cmd, void *priv), - uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv), + uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), void (*write_byte)(uint8_t addr, uint8_t val, void *priv), void (*write_byte_cmd)(uint8_t addr, uint8_t cmd, uint8_t val, void *priv), void (*write_word_cmd)(uint8_t addr, uint8_t cmd, uint16_t val, void *priv), @@ -223,7 +223,7 @@ smbus_handler(int set, uint8_t base, int size, uint8_t (*read_byte)(uint8_t addr, void *priv), uint8_t (*read_byte_cmd)(uint8_t addr, uint8_t cmd, void *priv), uint16_t (*read_word_cmd)(uint8_t addr, uint8_t cmd, void *priv), - uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv), + uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), void (*write_byte)(uint8_t addr, uint8_t val, void *priv), void (*write_byte_cmd)(uint8_t addr, uint8_t cmd, uint8_t val, void *priv), void (*write_word_cmd)(uint8_t addr, uint8_t cmd, uint16_t val, void *priv), @@ -308,7 +308,7 @@ smbus_read_word_cmd(uint8_t addr, uint8_t cmd) } uint8_t -smbus_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data) +smbus_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len) { uint8_t ret = 0; smbus_t *p; @@ -318,7 +318,7 @@ smbus_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data) if (p) { while(p) { if (p->read_block_cmd) { - ret = MAX(ret, p->read_block_cmd(addr, cmd, data, p->priv)); + ret = MAX(ret, p->read_block_cmd(addr, cmd, data, len, p->priv)); found++; } p = p->next; diff --git a/src/smbus_piix4.c b/src/smbus_piix4.c index 8a1a0a762..ad8ff64d0 100644 --- a/src/smbus_piix4.c +++ b/src/smbus_piix4.c @@ -157,7 +157,7 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv) break; case 0x5: /* block R/W */ if (smbus_read) - dev->data0 = smbus_read_block_cmd(smbus_addr, dev->cmd, dev->data); + dev->data0 = smbus_read_block_cmd(smbus_addr, dev->cmd, dev->data, SMBUS_PIIX4_BLOCK_DATA_SIZE); else smbus_write_block_cmd(smbus_addr, dev->cmd, dev->data, dev->data0); dev->next_stat = 0x2; diff --git a/src/spd.c b/src/spd.c index 5b00c1178..da75403fb 100644 --- a/src/spd.c +++ b/src/spd.c @@ -27,16 +27,11 @@ #include <86box/spd.h> -#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define SPD_ROLLUP(x) ((x) >= 16 ? ((x) - 15) : (x)) -typedef struct _spd_ { - uint8_t slot; - uint8_t addr_register; -} spd_t; - - -device_t *spd_devices[SPD_MAX_SLOTS]; +spd_t *spd_devices[SPD_MAX_SLOTS]; uint8_t spd_data[SPD_MAX_SLOTS][SPD_DATA_SIZE]; @@ -44,7 +39,7 @@ static uint8_t spd_read_byte(uint8_t addr, void *priv); static uint8_t spd_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv); static void spd_write_byte(uint8_t addr, uint8_t val, void *priv); - +#define ENABLE_SPD_LOG 1 #ifdef ENABLE_SPD_LOG int spd_do_log = ENABLE_SPD_LOG; @@ -83,6 +78,24 @@ spd_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv) } +uint16_t +spd_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv) +{ + return (spd_read_byte_cmd(addr, cmd + 1, priv) << 8) | spd_read_byte_cmd(addr, cmd, priv); +} + + +uint8_t +spd_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv) +{ + uint8_t read = 0; + for (uint8_t i = cmd; i < len && i < SPD_DATA_SIZE; i++) { + data[read++] = spd_read_byte_cmd(addr, i, priv); + } + return read; +} + + void spd_write_byte(uint8_t addr, uint8_t val, void *priv) { @@ -99,7 +112,7 @@ spd_close(void *priv) spd_log("SPD: closing slot %d (SMBus %02Xh)\n", dev->slot, SPD_BASE_ADDR + dev->slot); smbus_removehandler(SPD_BASE_ADDR + dev->slot, 1, - spd_read_byte, spd_read_byte_cmd, NULL, NULL, + spd_read_byte, spd_read_byte_cmd, spd_read_word_cmd, spd_read_block_cmd, spd_write_byte, NULL, NULL, NULL, dev); @@ -110,17 +123,14 @@ spd_close(void *priv) static void * spd_init(const device_t *info) { - spd_t *dev = (spd_t *) malloc(sizeof(spd_t)); - memset(dev, 0, sizeof(spd_t)); - - dev->slot = info->local; + spd_t *dev = spd_devices[info->local]; spd_log("SPD: initializing slot %d (SMBus %02Xh)\n", dev->slot, SPD_BASE_ADDR + dev->slot); smbus_sethandler(SPD_BASE_ADDR + dev->slot, 1, - spd_read_byte, spd_read_byte_cmd, NULL, NULL, - spd_write_byte, NULL, NULL, NULL, - dev); + spd_read_byte, spd_read_byte_cmd, spd_read_word_cmd, spd_read_block_cmd, + spd_write_byte, NULL, NULL, NULL, + dev); return dev; } @@ -139,8 +149,8 @@ log2_ui16(uint16_t i) int comp_ui16_rev(const void *elem1, const void *elem2) { - uint16_t a = *((uint16_t *)elem1); - uint16_t b = *((uint16_t *)elem2); + uint16_t a = *((uint16_t *) elem1); + uint16_t b = *((uint16_t *) elem2); return ((a > b) ? -1 : ((a < b) ? 1 : 0)); } @@ -149,7 +159,8 @@ void spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size) { uint8_t slot, slot_count, vslot, next_empty_vslot, i, split; - uint16_t min_module_size, total_size, vslots[SPD_MAX_SLOTS]; + uint16_t min_module_size, total_size, vslots[SPD_MAX_SLOTS], asym; + device_t *info; spd_edo_t *edo_data; spd_sdram_t *sdram_data; @@ -192,8 +203,21 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size) } } - if (total_size > 0) /* did we populate everything? */ - spd_log("SPD: not enough RAM slots (%d) to cover memory (%d MB short)\n", slot_count, total_size); + /* did we populate all the RAM? */ + if (total_size) { + /* work backwards to add the missing RAM as asymmetric modules */ + vslot = slot_count - 1; + do { + asym = (1 << log2_ui16(MIN(total_size, vslots[vslot]))); + if (vslots[vslot] + asym <= max_module_size) { + vslots[vslot] += asym; + total_size -= asym; + } + } while (vslot-- > 0 && total_size); + + if (total_size) /* still not enough */ + spd_log("SPD: not enough RAM slots (%d) to cover memory (%d MB short)\n", slot_count, total_size); + } /* populate empty vslots by splitting modules... */ split = (total_size == 0); /* ...if possible */ @@ -201,8 +225,8 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size) /* look for a module to split */ split = 0; for (vslot = 0; vslot < slot_count; vslot++) { - if (vslots[vslot] < (min_module_size << 1)) - continue; /* no module here or module is too small to be split */ + if ((vslots[vslot] < (min_module_size << 1)) || (vslots[vslot] != (1 << log2_ui16(vslots[vslot])))) + continue; /* no module here, module is too small to be split, or asymmetric module */ /* find next empty vslot */ next_empty_vslot = 0; @@ -230,14 +254,28 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size) if (!(slot_mask & (1 << slot))) continue; /* slot disabled */ - spd_log("SPD: registering slot %d = vslot %d = %d MB\n", slot, vslot, vslots[vslot]); + info = (device_t *) malloc(sizeof(device_t)); + memset(info, 0, sizeof(device_t)); + info->name = "Serial Presence Detect ROM"; + info->local = slot; + info->init = spd_init; + info->close = spd_close; - spd_devices[slot] = (device_t *) malloc(sizeof(device_t)); - memset(spd_devices[slot], 0, sizeof(device_t)); - spd_devices[slot]->name = "Serial Presence Detect ROM"; - spd_devices[slot]->local = slot; - spd_devices[slot]->init = spd_init; - spd_devices[slot]->close = spd_close; + spd_devices[slot] = (spd_t *) malloc(sizeof(spd_t)); + memset(spd_devices[slot], 0, sizeof(spd_t)); + spd_devices[slot]->info = info; + spd_devices[slot]->slot = slot; + spd_devices[slot]->size = vslots[vslot]; + + /* determine the second row size, from which the first row size can be obtained */ + asym = (vslots[vslot] - (1 << log2_ui16(vslots[vslot]))); /* separate the powers of 2 */ + if (!asym) /* is the module asymmetric? */ + asym = (vslots[vslot] >> 1); /* symmetric, therefore divide by 2 */ + + spd_devices[slot]->row1 = (vslots[vslot] - asym); + spd_devices[slot]->row2 = asym; + + spd_log("SPD: registering slot %d = vslot %d = %d MB (%d/%d)\n", slot, vslot, vslots[vslot], spd_devices[slot]->row1, spd_devices[slot]->row2); switch (ram_type) { case SPD_TYPE_FPM: @@ -245,13 +283,18 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size) edo_data = (spd_edo_t *) &spd_data[slot]; memset(edo_data, 0, sizeof(spd_edo_t)); - /* FIXME: very little information about EDO SPD is available, - let alone software to interpret it correctly. */ + /* EDO SPD is specified by JEDEC and present in some modules, but + most utilities cannot interpret it correctly. SIV32 at least gets + the module capacities right, so it was used as a reference here. */ edo_data->bytes_used = 0x80; edo_data->spd_size = 0x08; edo_data->mem_type = ram_type; - edo_data->row_bits = 6 + log2_ui16(vslots[vslot]); + edo_data->row_bits = SPD_ROLLUP(7 + log2_ui16(spd_devices[slot]->row1)); /* first row */ edo_data->col_bits = 9; + if (spd_devices[slot]->row1 != spd_devices[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_devices[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; edo_data->data_width_lsb = 64; edo_data->signal_level = SPD_SIGNAL_LVTTL; @@ -261,9 +304,11 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size) edo_data->dram_width = 8; edo_data->spd_rev = 0x12; - sprintf(edo_data->part_no, "86Box-%s-%03dM", (ram_type == SPD_TYPE_FPM) ? "FPM" : "EDO", vslots[vslot]); + sprintf(edo_data->part_no, EMU_NAME "-%s-%03dM", (ram_type == SPD_TYPE_FPM) ? "FPM" : "EDO", vslots[vslot]); for (i = strlen(edo_data->part_no); i < sizeof(edo_data->part_no); i++) - edo_data->part_no[i] = ' '; + edo_data->part_no[i] = ' '; /* part number should be space-padded */ + edo_data->rev_code[0] = EMU_VERSION_MAJ; + edo_data->rev_code[1] = (((EMU_VERSION_MIN / 10) << 4) | (EMU_VERSION_MIN % 10)); edo_data->mfg_year = 20; edo_data->mfg_week = 17; @@ -280,8 +325,12 @@ 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 = 5 + log2_ui16(vslots[vslot]); + sdram_data->row_bits = SPD_ROLLUP(6 + log2_ui16(spd_devices[slot]->row1)); /* first row */ sdram_data->col_bits = 9; + if (spd_devices[slot]->row1 != spd_devices[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_devices[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; sdram_data->data_width_lsb = 64; sdram_data->signal_level = SPD_SIGNAL_LVTTL; @@ -292,20 +341,29 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size) sdram_data->tccd = 1; sdram_data->burst = SPD_SDR_BURST_PAGE | 1 | 2 | 4 | 8; sdram_data->banks = 4; - sdram_data->cas = sdram_data->cs = sdram_data->we = 0x7F; + sdram_data->cas = 0x1c; /* CAS 5/4/3 supported */ + sdram_data->cslat = sdram_data->we = 0x7f; sdram_data->dev_attr = SPD_SDR_ATTR_EARLY_RAS | SPD_SDR_ATTR_AUTO_PC | SPD_SDR_ATTR_PC_ALL | SPD_SDR_ATTR_W1R_BURST; sdram_data->tclk2 = 0xA0; /* 10 ns = 100 MHz */ sdram_data->tclk3 = 0xF0; /* 15 ns = 66.7 MHz */ sdram_data->tac2 = sdram_data->tac3 = 0x10; sdram_data->trp = sdram_data->trrd = sdram_data->trcd = sdram_data->tras = 1; - sdram_data->bank_density = 1 << (log2_ui16(vslots[vslot] >> 1) - 2); + if (spd_devices[slot]->row1 != spd_devices[slot]->row2) { + /* Utilities interpret bank_density a bit differently on asymmetric modules. */ + sdram_data->bank_density = (1 << (log2_ui16(spd_devices[slot]->row1 >> 1) - 2)); /* first row */ + sdram_data->bank_density |= (1 << (log2_ui16(spd_devices[slot]->row2 >> 1) - 2)); /* second row */ + } else { + sdram_data->bank_density = (1 << (log2_ui16(spd_devices[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; sdram_data->spd_rev = 0x12; - sprintf(sdram_data->part_no, "86Box-SDR-%03dM", vslots[vslot]); + sprintf(sdram_data->part_no, EMU_NAME "-SDR-%03dM", vslots[vslot]); for (i = strlen(sdram_data->part_no); i < sizeof(sdram_data->part_no); i++) - sdram_data->part_no[i] = ' '; + sdram_data->part_no[i] = ' '; /* part number should be space-padded */ + sdram_data->rev_code[0] = EMU_VERSION_MAJ; + sdram_data->rev_code[1] = (((EMU_VERSION_MIN / 10) << 4) | (EMU_VERSION_MIN % 10)); sdram_data->mfg_year = 20; sdram_data->mfg_week = 13; @@ -319,7 +377,7 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size) break; } - device_add(spd_devices[slot]); + device_add(info); vslot++; } } diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 068f8d6ed..3be96434c 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -281,13 +281,8 @@ FONT 9, "Segoe UI" BEGIN DEFPUSHBUTTON "OK",IDOK,129,94,71,12 ICON 100,IDC_ABOUT_ICON,7,7,20,20 -#ifdef RELEASE_BUILD - LTEXT "86Box v2.07 - An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, MoochMcGee, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2. See LICENSE for more information.", + LTEXT "86Box v" EMU_VERSION " - An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, MoochMcGee, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2. See LICENSE for more information.", IDC_ABOUT_ICON,54,7,146,73 -#else - LTEXT "86Box v2.10 - An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, MoochMcGee, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2. See LICENSE for more information.", - IDC_ABOUT_ICON,54,7,146,73 -#endif CONTROL "",IDC_ABOUT_ICON,"Static",SS_BLACKFRAME | SS_SUNKEN,0, 86,208,1 END @@ -1043,8 +1038,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,10,0,0 - PRODUCTVERSION 2,10,0,0 + FILEVERSION EMU_VERSION_MAJ,EMU_VERSION_MIN,0,0 + PRODUCTVERSION EMU_VERSION_MAJ,EMU_VERSION_MIN,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -1059,14 +1054,14 @@ BEGIN BEGIN BLOCK "040904b0" BEGIN - VALUE "CompanyName", "86Box\0" - VALUE "FileDescription", "86Box\0" - VALUE "FileVersion", "2.10\0" - VALUE "InternalName", "86Box\0" - VALUE "LegalCopyright", "Copyright © 2007-2020 86Box contributors\0" - VALUE "OriginalFilename", "86Box.exe\0" - VALUE "ProductName", "86Box Emulator\0" - VALUE "ProductVersion", "2.10\0" + VALUE "CompanyName", EMU_NAME "\0" + VALUE "FileDescription", EMU_NAME "\0" + VALUE "FileVersion", EMU_VERSION "\0" + VALUE "InternalName", EMU_NAME "\0" + VALUE "LegalCopyright", "Copyright © 2007-" COPYRIGHT_YEAR " " EMU_NAME " contributors\0" + VALUE "OriginalFilename", EMU_NAME ".exe\0" + VALUE "ProductName", EMU_NAME " Emulator\0" + VALUE "ProductVersion", EMU_VERSION "\0" END END BLOCK "VarFileInfo"