From 14935da7010c3497c405bf85bc237f5473d859ee Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Fri, 20 Mar 2020 21:21:37 -0300 Subject: [PATCH 01/14] Fix build with new dynarec disabled --- src/cpu_common/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu_common/cpu.c b/src/cpu_common/cpu.c index 84692d702..a7467d108 100644 --- a/src/cpu_common/cpu.c +++ b/src/cpu_common/cpu.c @@ -2295,11 +2295,11 @@ void cpu_ven_reset(void) case CPU_K6: amd_efer = amd_whcr = 0ULL; break; +#ifdef USE_NEW_DYNAREC case CPU_K6_2: amd_efer = amd_whcr = 0ULL; star = 0ULL; break; -#ifdef USE_NEW_DYNAREC case CPU_K6_2C: amd_efer = 2ULL; amd_whcr = star = 0ULL; From b508085f1321d6edc8a08b3245fd582ee80b27fa Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Fri, 20 Mar 2020 21:29:13 -0300 Subject: [PATCH 02/14] Fix KBC-related reboot loops on more recent AMI BIOSes --- src/keyboard_at.c | 56 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/src/keyboard_at.c b/src/keyboard_at.c index a3c12dcd4..6ee7fbd50 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -57,6 +57,8 @@ #define PS2_REFRESH_TIME (16 * TIMER_USEC) +#define RESET_DELAY_TIME (100 * 10) /* 600ms */ + #define CCB_UNUSED 0x80 #define CCB_TRANSLATE 0x40 #define CCB_PCMODE 0x20 @@ -95,7 +97,7 @@ typedef struct { uint8_t mem[0x100]; int out_new, out_delayed; - int last_irq; + int last_irq, reset_delay; uint32_t flags; @@ -568,6 +570,9 @@ static const scancode scancode_set3[512] = { }; +static void add_data_kbd(uint16_t val); + + #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; @@ -667,11 +672,17 @@ kbd_poll(void *priv) (mouse_queue_start != mouse_queue_end)) { dev->out_new = mouse_queue[mouse_queue_start] | 0x100; mouse_queue_start = (mouse_queue_start + 1) & 0xf; - } else if (!(dev->status&STAT_OFULL) && dev->out_new == -1 && + } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && !(dev->mem[0]&0x10) && (key_queue_start != key_queue_end)) { dev->out_new = key_queue[key_queue_start]; key_queue_start = (key_queue_start + 1) & 0xf; } + + if (dev->reset_delay) { + dev->reset_delay--; + if (!dev->reset_delay) + add_data_kbd(0xaa); + } } @@ -697,6 +708,9 @@ add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len) uint8_t or = 0; uint8_t send; + if (dev->reset_delay) + return; + translate = translate || (keyboard_mode & 0x40) || xt_mode; translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); @@ -744,6 +758,9 @@ add_data_kbd(uint16_t val) uint8_t fake_shift[4]; uint8_t num_lock = 0, shift_states = 0; + if (dev->reset_delay) + return; + translate = translate || (keyboard_mode & 0x40) || xt_mode; translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); @@ -1482,20 +1499,6 @@ write64_ami(void *priv, uint8_t val) dev->output_locked = 1; return 0; - case 0xca: /* read keyboard mode */ -#ifdef ENABLE_KEYBOARD_AT_LOG - kbd_log("ATkbd: AMI - read keyboard mode\n"); -#endif - add_data(dev, 0x00); /*ISA mode*/ - return 0; - - case 0xcb: /* set keyboard mode */ -#ifdef ENABLE_KEYBOARD_AT_LOG - kbd_log("ATkbd: AMI - set keyboard mode\n"); -#endif - dev->want60 = 1; - return 0; - case 0xef: /* ??? - sent by AMI486 */ #ifdef ENABLE_KEYBOARD_AT_LOG kbd_log("ATkbd: ??? - sent by AMI486\n"); @@ -1989,11 +1992,12 @@ do_command: #endif key_queue_start = key_queue_end = 0; /*Clear key queue*/ add_data_kbd(0xfa); - add_data_kbd(0xaa); /* Set scan code set to 2. */ keyboard_mode = (keyboard_mode & 0xfc) | 0x02; set_scancode_map(dev); + + dev->reset_delay = RESET_DELAY_TIME; break; default: @@ -2108,6 +2112,20 @@ do_command: set_enable_kbd(dev, 1); break; + case 0xca: /* read keyboard mode */ +#ifdef ENABLE_KEYBOARD_AT_LOG + kbd_log("ATkbd: AMI - read keyboard mode\n"); +#endif + add_data(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00); /*ISA mode*/ + break; + + case 0xcb: /* set keyboard mode */ +#ifdef ENABLE_KEYBOARD_AT_LOG + kbd_log("ATkbd: AMI - set keyboard mode\n"); +#endif + dev->want60 = 1; + break; + case 0xd0: /* read output port */ #ifdef ENABLE_KEYBOARD_AT_LOG kbd_log("ATkbd: read output port\n"); @@ -2192,6 +2210,8 @@ kbd_read(uint16_t port, void *priv) atkbd_t *dev = (atkbd_t *)priv; uint8_t ret = 0xff; + sub_cycles(ISA_CYCLES(8)); + if (((dev->flags & KBC_VEN_MASK) == KBC_VEN_XI8088) && (port == 0x63)) port = 0x61; @@ -2602,4 +2622,4 @@ uint8_t keyboard_at_get_mouse_scan(void) { return(mouse_scan ? 0x10 : 0x00); -} +} \ No newline at end of file From 18562b5f7d63e6cf4ebed79f8609f7ddbc220c6a Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Fri, 20 Mar 2020 23:27:23 -0300 Subject: [PATCH 03/14] ASUS P2B-LS board --- src/machine/m_at_socket8.c | 35 ++++++++++++++++++++++++++++++++++- src/machine/machine.h | 1 + src/machine/machine_table.c | 1 + 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 16e03b0ea..b53f8d623 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -114,7 +114,7 @@ machine_at_6abx3_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -137,4 +137,37 @@ machine_at_6abx3_init(const machine_t *model) } +int +machine_at_p2bls_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/p2bls/1014ls.003", + 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(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, 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(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x04, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83977tf_device); + device_add(&sst_flash_39sf020_device); + + return ret; +} + + #endif diff --git a/src/machine/machine.h b/src/machine/machine.h index 74b214200..adf1beb70 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -306,6 +306,7 @@ extern int machine_at_i440fx_init(const machine_t *); extern int machine_at_s1668_init(const machine_t *); extern int machine_at_6abx3_init(const machine_t *); +extern int machine_at_p2bls_init(const machine_t *); #endif /* m_at_t3100e.c */ diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index d5728de43..afa24ad43 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -238,6 +238,7 @@ const machine_t machines[] = { { "[Socket 8 FX] Tyan Titan-Pro ATX", "tpatx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_s1668_init, NULL }, { "[Slot 1 BX] Lucky Star 6ABX3", "6abx3", {{"Intel", cpus_PentiumII}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_6abx3_init, NULL }, + { "[Slot 1 BX] ASUS P2B-LS", "p2bls", {{"Intel", cpus_PentiumII}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_p2bls_init, NULL }, #endif { NULL, NULL, {{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}}, 0, 0, 0, 0, 0, NULL, NULL } }; From b999cce72300369c72c02a5088dc9b534f6e92de Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 22 Mar 2020 01:17:49 +0100 Subject: [PATCH 04/14] Some fixes to fix PIIX3 machines, fatal's on BIOS'es accessing the OPL, and RAM limits on 430TX machines. --- src/intel_piix.c | 9 ++++----- src/machine/m_at_socket8.c | 2 +- src/machine/machine_table.c | 8 ++++---- src/sound/snd_opl_backend.c | 12 +----------- 4 files changed, 10 insertions(+), 21 deletions(-) diff --git a/src/intel_piix.c b/src/intel_piix.c index dd504cf25..f3aa3aef3 100644 --- a/src/intel_piix.c +++ b/src/intel_piix.c @@ -953,10 +953,9 @@ piix_reset_hard(piix_t *dev) nvr_at_handler(0, 0x0072, dev->nvr); nvr_wp_set(0, 0, dev->nvr); nvr_wp_set(0, 1, dev->nvr); - } else - nvr_at_handler(1, 0x0072, dev->nvr); - nvr_at_handler(1, 0x0074, dev->nvr); - nvr_at_handler(1, 0x0076, dev->nvr); + nvr_at_handler(1, 0x0074, dev->nvr); + nvr_at_handler(1, 0x0076, dev->nvr); + } /* Clear all 4 functions' arrays and set their vendor and device ID's. */ for (i = 0; i < 4; i++) { @@ -1078,7 +1077,7 @@ static void dev->bm[1] = device_add_inst(&sff8038i_device, 2); } - if (dev->type >= 3) + if (dev->type > 3) dev->nvr = device_add(&piix4_nvr_device); piix_reset_hard(dev); diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 16e03b0ea..083663874 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -114,7 +114,7 @@ machine_at_6abx3_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index d5728de43..26cc76e16 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -226,10 +226,10 @@ const machine_t machines[] = { { "[Socket 7 VX] Jetway J656VXD", "j656vxd", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_j656vxd_init, NULL }, { "[Socket 7 VX] Shuttle HOT-557", "430vx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL }, - { "[Socket 7 TX] Acorp 5TX52", "5tx52", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 255, machine_at_5tx52_init, NULL }, - { "[Socket 7 TX] ASUS TXP4", "txp4", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 255, machine_at_txp4_init, NULL }, - { "[Socket 7 TX] Intel YM430TX", "ym430tx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 255, machine_at_ym430tx_init, NULL }, - { "[Socket 7 TX] San-LI/Superpower SP-586TX","sp586tx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 255, machine_at_sp586tx_init, NULL }, + { "[Socket 7 TX] Acorp 5TX52", "5tx52", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 255, machine_at_5tx52_init, NULL }, + { "[Socket 7 TX] ASUS TXP4", "txp4", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 255, machine_at_txp4_init, NULL }, + { "[Socket 7 TX] Intel YM430TX", "ym430tx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 255, machine_at_ym430tx_init, NULL }, + { "[Socket 7 TX] San-LI/Superpower SP-586TX","sp586tx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 255, machine_at_sp586tx_init, NULL }, { "[Super Socket 7] FIC VA-503+", "ficva503p", MACHINE_CPUS_PENTIUM_SS7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 255, machine_at_mvp3_init, NULL }, diff --git a/src/sound/snd_opl_backend.c b/src/sound/snd_opl_backend.c index b2673fae0..2e8ae1df6 100644 --- a/src/sound/snd_opl_backend.c +++ b/src/sound/snd_opl_backend.c @@ -134,21 +134,11 @@ opl_write(int nr, uint16_t addr, uint8_t val) uint8_t opl_read(int nr, uint16_t addr) { - FILE *f; - int i; - if (!(addr & 1)) return (opl[nr].status & opl[nr].status_mask) | (opl[nr].is_opl3 ? 0 : 0x06); - if (opl[nr].is_opl3 && ((addr & 3) == 3)) { - f = fopen("c:\\emu_dev\\awe32seg.dmp", "wb"); - for (i = 0; i < 65536; i++) - fputc(readmembl(cs + i), f); - fclose(f); - - fatal("[%04X:%08X] (%08X) Read 00 from %04X\n", CS, cpu_state.pc, cs + cpu_state.pc, addr); + if (opl[nr].is_opl3 && ((addr & 3) == 3)) return 0x00; - } return opl[nr].is_opl3 ? 0 : 0xff; } From 6a111545a11c294f339742c6e66e776f58e5cc80 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 22 Mar 2020 23:12:02 +0100 Subject: [PATCH 05/14] ZIP and (SCSI) CD-ROM code now round the maximum transfer size to the nearest sector size for disk access commands, fixes CD-ROM booting on later ASUS BIOS'es. --- src/disk/zip.c | 6 ++++++ src/scsi/scsi_cdrom.c | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/disk/zip.c b/src/disk/zip.c index e0fc5d783..429c68dab 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -815,8 +815,14 @@ zip_update_request_length(zip_t *dev, int len, int block_len) /* For media access commands, make sure the requested DRQ length matches the block length. */ switch (dev->current_cdb[0]) { case 0x08: + case 0x0a: case 0x28: + case 0x2a: case 0xa8: + case 0xaa: + /* Round it to the nearest 2048 bytes. */ + dev->max_transfer_len = (dev->max_transfer_len >> 9) << 9; + /* Make sure total length is not bigger than sum of the lengths of all the requested blocks. */ bt = (dev->requested_blocks * block_len); diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index ccb936901..1c9c1cab4 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -562,6 +562,10 @@ scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, int block_len) case 0x08: case 0x28: case 0xa8: + /* Round it to the nearest 2048 bytes. */ + dev->max_transfer_len = (dev->max_transfer_len >> 11) << 11; + /* FALLTHROUGH */ + case 0xb9: case 0xbe: /* Make sure total length is not bigger than sum of the lengths of From dd70542d785c0b261fdfb07403b9166bf8a7c379 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sun, 22 Mar 2020 22:11:55 -0300 Subject: [PATCH 06/14] SMBus support + Winbond W83781D hardware monitor --- src/hwm.c | 36 +++ src/hwm.h | 38 +++ src/hwm_w83781d.c | 482 +++++++++++++++++++++++++++++++++++++ src/intel_piix.c | 153 +++++++++++- src/machine/m_at_socket8.c | 29 +++ src/smbus.c | 410 +++++++++++++++++++++++++++++++ src/smbus.h | 67 ++++++ src/win/Makefile.mingw | 3 +- src/win/Makefile_ndr.mingw | 3 +- 9 files changed, 1214 insertions(+), 7 deletions(-) create mode 100644 src/hwm.c create mode 100644 src/hwm.h create mode 100644 src/hwm_w83781d.c create mode 100644 src/smbus.c create mode 100644 src/smbus.h diff --git a/src/hwm.c b/src/hwm.c new file mode 100644 index 000000000..b3142c7a4 --- /dev/null +++ b/src/hwm.c @@ -0,0 +1,36 @@ +/* + * 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. + * + * Common functions for hardware monitor chips. + * + * Version: @(#)hwm.c 1.0.0 2020/03/22 + * + * Author: RichardG, + * Copyright 2020 RichardG. + */ + +#include +#include "device.h" +#include "hwm.h" + + +hwm_values_t hwm_values; + + +void +hwm_set_values(hwm_values_t new_values) +{ + hwm_values = new_values; +} + + +hwm_values_t* +hwm_get_values() +{ + return &hwm_values; +} diff --git a/src/hwm.h b/src/hwm.h new file mode 100644 index 000000000..c5d482fb7 --- /dev/null +++ b/src/hwm.h @@ -0,0 +1,38 @@ +/* + * 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 the hardware monitor chips. + * + * Version: @(#)hwm.h 1.0.0 2020/03/21 + * + * Author: RichardG, + * Copyright 2020 RichardG. + */ +#ifndef EMU_HWM_H +# define EMU_HWM_H + + +#define VDIV(v, r1, r2) (((v) * (r2)) / ((r1) + (r2))) + + +typedef struct _hwm_values_ { + uint16_t fans[4]; + uint8_t temperatures[4]; + uint8_t voltages[8]; +} hwm_values_t; + + +extern void hwm_set_values(hwm_values_t new_values); +extern hwm_values_t* hwm_get_values(); + + +extern const device_t w83781d_device; +extern const device_t as99127f_device; + + +#endif /*EMU_HWM_H*/ diff --git a/src/hwm_w83781d.c b/src/hwm_w83781d.c new file mode 100644 index 000000000..1f6b3ab26 --- /dev/null +++ b/src/hwm_w83781d.c @@ -0,0 +1,482 @@ +/* + * 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 Winbond W83781D hardware monitoring chip. + * + * Version: @(#)hwm_w83781d.c 1.0.0 2020/03/21 + * + * Author: RichardG, + * Copyright 2020 RichardG. + */ +#include +#include +#include +#include +#include +#include "86box.h" +#include "device.h" +#include "86box_io.h" +#include "smbus.h" +#include "hwm.h" + + +#define W83781D_SMBUS 0x10000 +#define W83781D_AS99127F 0x20000 +#define W83781D_VENDOR_ID ((dev->local & W83781D_AS99127F) ? 0x12C3 : 0x5CA3) + +#define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a))) +#define W83781D_RPM_TO_REG(r, d) CLAMP(1350000 / (r * d), 1, 255) +#define W83781D_TEMP_TO_REG(t) ((t) * 8) << 5 + + +typedef struct { + uint32_t local; + hwm_values_t* values; + + uint8_t regs[64]; + uint8_t regs_bank1[6]; + uint8_t regs_bank2[6]; + uint8_t addr_register; + uint8_t data_register; + + uint8_t smbus_addr_main; + uint8_t smbus_addr_temp2; + uint8_t smbus_addr_temp3; + uint8_t hbacs; + uint8_t active_bank; +} w83781d_t; + + +static uint8_t w83781d_isa_read(uint16_t port, void *priv); +static uint8_t w83781d_smbus_read_byte(uint8_t addr, void *priv); +static uint8_t w83781d_smbus_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv); +static uint16_t w83781d_smbus_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv); +static uint8_t w83781d_read(w83781d_t *dev, uint8_t reg, uint8_t bank); +static void w83781d_isa_write(uint16_t port, uint8_t val, void *priv); +static void w83781d_smbus_write_byte(uint8_t addr, uint8_t val, void *priv); +static void w83781d_smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv); +static void w83781d_smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv); +static uint8_t w83781d_write(w83781d_t *dev, uint8_t reg, uint8_t val, uint8_t bank); +static void w83781d_reset(w83781d_t *dev, uint8_t initialization); + + +static void +w83781d_remap(w83781d_t *dev) +{ + if (!(dev->local & W83781D_SMBUS)) return; + + smbus_removehandler(0x00, 0x80, + w83781d_smbus_read_byte, w83781d_smbus_read_byte_cmd, w83781d_smbus_read_word_cmd, NULL, + w83781d_smbus_write_byte, w83781d_smbus_write_byte_cmd, w83781d_smbus_write_word_cmd, NULL, + dev); + + if (dev->smbus_addr_main) smbus_sethandler(dev->smbus_addr_main, 1, + w83781d_smbus_read_byte, w83781d_smbus_read_byte_cmd, w83781d_smbus_read_word_cmd, NULL, + w83781d_smbus_write_byte, w83781d_smbus_write_byte_cmd, w83781d_smbus_write_word_cmd, NULL, + dev); + + if (dev->smbus_addr_temp2) smbus_sethandler(dev->smbus_addr_temp2, 1, + w83781d_smbus_read_byte, w83781d_smbus_read_byte_cmd, w83781d_smbus_read_word_cmd, NULL, + w83781d_smbus_write_byte, w83781d_smbus_write_byte_cmd, w83781d_smbus_write_word_cmd, NULL, + dev); + + if (dev->smbus_addr_temp3) smbus_sethandler(dev->smbus_addr_temp3, 1, + w83781d_smbus_read_byte, w83781d_smbus_read_byte_cmd, w83781d_smbus_read_word_cmd, NULL, + w83781d_smbus_write_byte, w83781d_smbus_write_byte_cmd, w83781d_smbus_write_word_cmd, NULL, + dev); +} + + +static uint8_t +w83781d_isa_read(uint16_t port, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + uint8_t ret = 0xFF; + + switch (port - (dev->local & 0xFFFF)) { + case 0x0: + ret = dev->addr_register & 0x7F; + break; + case 0x1: + ret = w83781d_read(dev, dev->addr_register, dev->active_bank); + + if (dev->active_bank == 0 && + (dev->addr_register == 0x41 || dev->addr_register == 0x43 || dev->addr_register == 0x45 || dev->addr_register == 0x56 || + (dev->addr_register >= 0x60 && dev->addr_register < 0x7F))) { + /* auto-increment registers */ + dev->addr_register++; + } + break; + } + + return ret; +} + + +static uint8_t +w83781d_smbus_read_byte(uint8_t addr, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + + return w83781d_read(dev, dev->addr_register, 0); +} + + +static uint8_t +w83781d_smbus_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + + return w83781d_read(dev, cmd, 0); +} + + +static uint16_t +w83781d_smbus_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + uint8_t rethi = 0; + uint8_t retlo = 0; + uint8_t bank = 0; + + if (addr == dev->smbus_addr_temp2 || addr == dev->smbus_addr_temp3) { + if (addr == dev->smbus_addr_temp2) + bank = 2; + else + bank = 3; + + switch (cmd & 0x3) { + case 0x0: + rethi = w83781d_read(dev, 0x50, bank); + retlo = w83781d_read(dev, 0x51, bank); + break; + case 0x1: + rethi = retlo = w83781d_read(dev, 0x52, bank); + break; + case 0x2: + rethi = w83781d_read(dev, 0x53, bank); + retlo = w83781d_read(dev, 0x54, bank); + break; + case 0x3: + rethi = w83781d_read(dev, 0x55, bank); + retlo = w83781d_read(dev, 0x56, bank); + break; + } + + return (retlo << 8) | rethi; /* byte-swapped for some reason */ + } + + return w83781d_read(dev, cmd, bank); +} + + +static uint8_t +w83781d_read(w83781d_t *dev, uint8_t reg, uint8_t bank) +{ + uint8_t ret = 0; + + if ((reg >> 4) == 0x5 && bank != 0) { + /* bank-switched temperature registers */ + if (bank == 1) + ret = dev->regs_bank1[reg - 0x50]; + else + ret = dev->regs_bank2[reg - 0x50]; + } else { + /* regular registers */ + if (reg == 0x4F) /* special case for two-byte vendor ID register */ + ret = dev->hbacs ? (W83781D_VENDOR_ID >> 8) : (W83781D_VENDOR_ID & 0xFF); + else if (reg >= 0x60) /* read auto-increment value RAM registers from their non-auto-increment locations */ + ret = dev->regs[reg - 0x40]; + else + ret = dev->regs[reg - 0x20]; + } + + return ret; +} + + +static void +w83781d_isa_write(uint16_t port, uint8_t val, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + + switch (port - (dev->local & 0xFFFF)) { + case 0x0: + dev->addr_register = val & 0x7F; + break; + case 0x1: + w83781d_write(dev, dev->addr_register, val, dev->active_bank); + + if (dev->active_bank == 0 && + (dev->addr_register == 0x41 || dev->addr_register == 0x43 || dev->addr_register == 0x45 || dev->addr_register == 0x56 || + (dev->addr_register >= 0x60 && dev->addr_register < 0x7F))) { + /* auto-increment registers */ + dev->addr_register++; + } + break; + } +} + + +static void +w83781d_smbus_write_byte(uint8_t addr, uint8_t val, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + + dev->addr_register = val; +} + + +static void +w83781d_smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + + w83781d_write(dev, cmd, val, 0); +} + + +static void +w83781d_smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + uint8_t valhi = (val >> 8); + uint8_t vallo = (val & 0xFF); + uint8_t bank = 0; + + if (addr == dev->smbus_addr_temp2 || addr == dev->smbus_addr_temp3) { + if (addr == dev->smbus_addr_temp2) + bank = 2; + else + bank = 3; + + switch (cmd & 0x3) { + case 0x0: + w83781d_write(dev, 0x50, valhi, bank); + w83781d_write(dev, 0x51, vallo, bank); + break; + case 0x1: + w83781d_write(dev, 0x52, vallo, bank); + break; + case 0x2: + w83781d_write(dev, 0x53, valhi, bank); + w83781d_write(dev, 0x54, vallo, bank); + break; + case 0x3: + w83781d_write(dev, 0x55, valhi, bank); + w83781d_write(dev, 0x56, vallo, bank); + break; + break; + } + return; + } + + w83781d_write(dev, cmd, vallo, bank); +} + + +static uint8_t +w83781d_write(w83781d_t *dev, uint8_t reg, uint8_t val, uint8_t bank) +{ + uint8_t remap = 0; + + if ((reg >> 4) == 0x5 && bank != 0) { + /* bank-switched temperature registers */ + switch (reg) { + case 0x50: case 0x51: + /* read-only registers */ + return 0; + } + + if (bank == 1) + dev->regs_bank1[reg - 0x50] = val; + else + dev->regs_bank2[reg - 0x50] = val; + + return 1; + } + + /* regular registers */ + switch (reg) { + case 0x41: case 0x42: case 0x4F: case 0x58: + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2A: + case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6A: + /* read-only registers */ + return 0; + } + + if (reg >= 0x60) /* write auto-increment value RAM registers to their non-auto-increment locations */ + dev->regs[reg - 0x40] = val; + else + dev->regs[reg - 0x20] = val; + + switch (reg) { + case 0x40: + if (val >> 7) { + /* INITIALIZATION bit set: reset all registers except main SMBus address */ + w83781d_reset(dev, 1); + } + break; + case 0x47: + /* update FAN1/FAN2 values to match the new divisor */ + dev->regs[0x08] = W83781D_RPM_TO_REG(dev->values->fans[0], 1 << ((dev->regs[0x27] >> 4) & 0x3)); + dev->regs[0x09] = W83781D_RPM_TO_REG(dev->values->fans[1], 1 << ((dev->regs[0x27] >> 6) & 0x3)); + break; + case 0x48: + if (dev->local & W83781D_SMBUS) { + dev->smbus_addr_main = (dev->regs[0x28] & 0x7F); + remap = 1; + } + break; + case 0x4A: + if (dev->local & W83781D_SMBUS) { + /* DIS_T2 and DIS_T3 bits can disable those interfaces */ + if ((dev->regs[0x2A] >> 3) & 0x1) + dev->smbus_addr_temp2 = 0x00; + else + dev->smbus_addr_temp2 = 0x48 + (dev->regs[0x2A] & 0x7); + if (dev->regs[0x2A] >> 7) + dev->smbus_addr_temp3 = 0x00; + else + dev->smbus_addr_temp3 = 0x48 + ((dev->regs[0x2A] >> 4) & 0x7); + remap = 1; + } + break; + case 0x4B: + /* update FAN3 value to match the new divisor */ + dev->regs[0x0A] = W83781D_RPM_TO_REG(dev->values->fans[2], 1 << ((dev->regs[0x2B] >> 6) & 0x3)); + break; + case 0x4E: + dev->hbacs = (dev->regs[0x2E] & 0x80); + /* FIXME: Winbond's datasheet does not specify how BANKSEL[0:2] work */ + if (dev->regs[0x2E] & 0x1) + dev->active_bank = 0; + else if (dev->regs[0x2E] & 0x2) + dev->active_bank = 1; + else if (dev->regs[0x2E] & 0x4) + dev->active_bank = 2; + break; + } + + if (remap) + w83781d_remap(dev); + + return 1; +} + + +static void +w83781d_reset(w83781d_t *dev, uint8_t initialization) +{ + memset(dev->regs, 0, 64); + memset(dev->regs_bank1, 0, 6); + memset(dev->regs_bank2, 0, 6); + + /* WARNING: Array elements are register - 0x20. */ + uint8_t i; + for (i = 0; i <= 6; i++) + dev->regs[i] = dev->values->voltages[i]; + dev->regs[0x07] = dev->values->temperatures[0]; + for (i = 0; i <= 2; i++) + dev->regs[0x08 + i] = W83781D_RPM_TO_REG(dev->values->fans[i], 2); + dev->regs[0x20] = 0x01; + dev->regs[0x26] = 0x40; + dev->regs[0x27] = 0x50; + if (dev->local & W83781D_SMBUS) { + if (!initialization) /* don't reset main SMBus address if the reset was triggered by the INITIALIZATION bit */ + dev->smbus_addr_main = 0x2D; + dev->regs[0x28] = dev->smbus_addr_main; + dev->regs[0x2A] = 0x01; + dev->smbus_addr_temp2 = 0x48 + (dev->regs[0x2A] & 0x7); + dev->smbus_addr_temp3 = 0x48 + ((dev->regs[0x2A] >> 4) & 0x7); + } else { + dev->regs[0x28] = 0x00; + dev->regs[0x2A] = 0x88; + dev->smbus_addr_temp2 = dev->smbus_addr_temp3 = 0x00; + } + dev->regs[0x29] = 0x02; + dev->regs[0x2B] = 0x44; + dev->regs[0x2C] = 0x01; + dev->regs[0x2D] = 0x15; + dev->regs[0x2E] = 0x80; + dev->hbacs = (dev->regs[0x2E] & 0x80); + dev->regs[0x2F] = W83781D_VENDOR_ID >> 8; + dev->regs[0x37] = 0x80; + dev->regs[0x38] = (dev->local & W83781D_AS99127F) ? 0x31 : 0x10; + + /* WARNING: Array elements are register - 0x50. */ + uint16_t temp; + temp = W83781D_TEMP_TO_REG(dev->values->temperatures[1]); + dev->regs_bank1[0x0] = temp >> 8; + dev->regs_bank1[0x1] = temp & 0xFF; + dev->regs_bank1[0x3] = 0x4B; + dev->regs_bank1[0x5] = 0x50; + temp = W83781D_TEMP_TO_REG(dev->values->temperatures[2]); + dev->regs_bank2[0x0] = temp >> 8; + dev->regs_bank2[0x1] = temp & 0xFF; + dev->regs_bank2[0x3] = 0x4B; + dev->regs_bank2[0x5] = 0x50; + + w83781d_remap(dev); +} + + +static void +w83781d_close(void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + + uint16_t isa_io = dev->local & 0xFFFF; + if (isa_io) + io_removehandler(isa_io, 2, w83781d_isa_read, NULL, NULL, w83781d_isa_write, NULL, NULL, dev); + + free(dev); +} + + +static void * +w83781d_init(const device_t *info) +{ + w83781d_t *dev = (w83781d_t *) malloc(sizeof(w83781d_t)); + memset(dev, 0, sizeof(w83781d_t)); + + dev->local = info->local; + dev->values = hwm_get_values(); + w83781d_reset(dev, 0); + + uint16_t isa_io = dev->local & 0xFFFF; + if (isa_io) + io_sethandler(isa_io, 2, w83781d_isa_read, NULL, NULL, w83781d_isa_write, NULL, NULL, dev); + + return dev; +} + + +const device_t w83781d_device = { + "Winbond W83781D Hardware Monitor", + DEVICE_ISA, + 0x295 | W83781D_SMBUS, + w83781d_init, w83781d_close, NULL, + NULL, NULL, NULL, + NULL +}; + + +/* + * ASUS rebadged version of the W83781D. + * Some claim it's SMBus-only, yet the BIOS clearly reads most values over ISA, + * except TEMP3 (CPU Temperature) which is read over SMBus. + */ +const device_t as99127f_device = { + "ASUS AS99127F Hardware Monitor", + DEVICE_ISA, + 0x295 | W83781D_SMBUS | W83781D_AS99127F, + w83781d_init, w83781d_close, NULL, + NULL, NULL, NULL, + NULL +}; diff --git a/src/intel_piix.c b/src/intel_piix.c index dd504cf25..3e2abeda2 100644 --- a/src/intel_piix.c +++ b/src/intel_piix.c @@ -46,6 +46,7 @@ #include "hdc_ide_sff8038i.h" #include "zip.h" #include "machine.h" +#include "smbus.h" #include "piix.h" @@ -87,11 +88,12 @@ typedef struct typedef struct { - uint8_t stat, ctl, cmd, addr, + uint8_t stat, next_stat, ctl, cmd, addr, data0, data1, index, data[32]; -} smbus_t; + pc_timer_t command_timer; +} piix_smbus_t; typedef struct @@ -107,7 +109,7 @@ typedef struct sff8038i_t *bm[2]; ddma_t ddma[2]; power_t power; - smbus_t smbus; + piix_smbus_t smbus; nvr_t * nvr; } piix_t; @@ -457,17 +459,145 @@ power_update_io_mapping(piix_t *dev) static uint8_t -smbus_reg_read(uint16_t addr, void *p) +smbus_reg_read(uint16_t addr, void *priv) { + piix_t *dev = (piix_t *) priv; uint8_t ret = 0x00; + switch (addr - dev->smbus_io_base) { + case 0x00: + ret = dev->smbus.stat; + break; + case 0x02: + dev->smbus.index = 0; + ret = dev->smbus.ctl; + break; + case 0x03: + ret = dev->smbus.cmd; + break; + case 0x04: + ret = dev->smbus.addr; + break; + case 0x05: + ret = dev->smbus.data0; + break; + case 0x06: + ret = dev->smbus.data1; + break; + case 0x07: + ret = dev->smbus.data[dev->smbus.index++]; + if (dev->smbus.index > 31) + dev->smbus.index = 0; + break; + } + + // pclog("smbus_reg_read %02x %02x\n", addr - dev->smbus_io_base, ret); + return ret; } static void -smbus_reg_write(uint16_t addr, uint8_t val, void *p) +smbus_reg_write(uint16_t addr, uint8_t val, void *priv) { + piix_t *dev = (piix_t *) priv; + uint8_t smbus_addr; + uint8_t smbus_read; + uint16_t temp; + + // pclog("smbus_reg_write %02x %02x\n", addr - dev->smbus_io_base, val); + + dev->smbus.next_stat = 0; + switch (addr - dev->smbus_io_base) { + case 0x00: + /* some status bits are reset by writing 1 to them */ + for (smbus_addr = 0x02; smbus_addr <= 0x10; smbus_addr = smbus_addr << 1) { + if (val & smbus_addr) + dev->smbus.stat = dev->smbus.stat & ~smbus_addr; + } + break; + case 0x02: + dev->smbus.ctl = val & ~(0x40); /* START always reads 0 */ + if (val & 0x40) { /* dispatch command if START is set */ + smbus_addr = (dev->smbus.addr >> 1); + if (!smbus_has_device(smbus_addr)) { + /* raise DEV_ERR if no device is at this address */ + dev->smbus.next_stat = 0x4; + break; + } + smbus_read = (dev->smbus.addr & 0x01); + + switch ((val >> 2) & 0x7) { + case 0x0: /* quick R/W */ + dev->smbus.next_stat = 0x2; + break; + case 0x1: /* byte R/W */ + if (smbus_read) + dev->smbus.data0 = smbus_read_byte(smbus_addr); + else + smbus_write_byte(smbus_addr, dev->smbus.data0); + dev->smbus.next_stat = 0x2; + break; + case 0x2: /* byte data R/W */ + if (smbus_read) + dev->smbus.data0 = smbus_read_byte_cmd(smbus_addr, dev->smbus.cmd); + else + smbus_write_byte_cmd(smbus_addr, dev->smbus.cmd, dev->smbus.data0); + dev->smbus.next_stat = 0x2; + break; + case 0x3: /* word data R/W */ + if (smbus_read) { + temp = smbus_read_word_cmd(smbus_addr, dev->smbus.cmd); + dev->smbus.data0 = (temp & 0xFF); + dev->smbus.data1 = (temp >> 8); + } else { + temp = (dev->smbus.data1 << 8) | dev->smbus.data0; + smbus_write_word_cmd(smbus_addr, dev->smbus.cmd, temp); + } + dev->smbus.next_stat = 0x2; + break; + case 0x5: /* block R/W */ + if (smbus_read) + dev->smbus.data0 = smbus_read_block_cmd(smbus_addr, dev->smbus.cmd, dev->smbus.data); + else + smbus_write_block_cmd(smbus_addr, dev->smbus.cmd, dev->smbus.data, dev->smbus.data0); + dev->smbus.next_stat = 0x2; + break; + } + } + break; + case 0x03: + dev->smbus.cmd = val; + break; + case 0x04: + dev->smbus.addr = val; + break; + case 0x05: + dev->smbus.data0 = val; + break; + case 0x06: + dev->smbus.data1 = val; + break; + case 0x07: + dev->smbus.data[dev->smbus.index++] = val; + if (dev->smbus.index > 31) + dev->smbus.index = 0; + break; + } + + if (dev->smbus.next_stat) { + dev->smbus.stat = 0x1; + timer_disable(&dev->smbus.command_timer); + timer_set_delay_u64(&dev->smbus.command_timer, 10 * TIMER_USEC); + } +} + + +static void +smbus_inter(void *priv) +{ + piix_t *dev = (piix_t *) priv; + dev->smbus.stat = dev->smbus.next_stat; } @@ -1174,6 +1304,19 @@ static void /* Bit 2: 0 = On-board audio absent, 1 = On-board audio present. */ dev->board_config[1] = 0x64; + smbus_init(); + dev->smbus.stat = 0; + dev->smbus.ctl = 0; + dev->smbus.cmd = 0; + dev->smbus.addr = 0; + dev->smbus.data0 = 0; + dev->smbus.data1 = 0; + dev->smbus.index = 0; + int i; + for (i = 0; i < 32; i++) + dev->smbus.data[i] = 0; + timer_add(&dev->smbus.command_timer, smbus_inter, dev, 0); + return dev; } diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index b53f8d623..a86bc9419 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -34,7 +34,9 @@ #include "piix.h" #include "sio.h" #include "sst_flash.h" +#include "hwm.h" #include "video.h" +#include "cpu.h" #include "machine.h" @@ -166,6 +168,33 @@ machine_at_p2bls_init(const machine_t *model) device_add(&w83977tf_device); device_add(&sst_flash_39sf020_device); + hwm_values_t machine_hwm = { + { /* fan speeds */ + 3000, /* Chassis */ + 3000, /* CPU */ + 3000, /* Power */ + 0 + }, { /* temperatures */ + 30, /* MB */ + 0, /* unused */ + 27, /* CPU */ + 0 + }, { /* voltages (divisors other than 16 = unclear how that number was achieved) */ + 2800 / 16, /* VCORE (2.8V by default) */ + 0, /* unused */ + 3300 / 16, /* +3.3V */ + 5000 / 27, /* +5V */ + VDIV(12000, 28, 10) / 16, /* +12V (with 28K/10K resistor divider suggested in the W83781D datasheet) */ + 12000 / 55, /* -12V */ + 5000 / 24, /* -5V */ + 0 + } + }; + if (model->cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type == CPU_PENTIUM2D) + machine_hwm.voltages[0] = 2050 / 16; /* set lower VCORE (2.05V) for Deschutes */ + hwm_set_values(machine_hwm); + device_add(&as99127f_device); + return ret; } diff --git a/src/smbus.c b/src/smbus.c new file mode 100644 index 000000000..171d4fad5 --- /dev/null +++ b/src/smbus.c @@ -0,0 +1,410 @@ +/* + * 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. + * + * Implement SMBus (System Management Bus) and its operations. + * + * Version: @(#)smbus.c 1.0.0 2020/03/21 + * + * Authors: RichardG, + * + * Copyright 2020 RichardG. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "86box.h" +#include "smbus.h" + + +#define NADDRS 128 /* SMBus supports 128 addresses */ +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + + +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); + + 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); + void (*write_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv); + + void *priv; + + struct _smbus_ *prev, *next; +} smbus_t; + +int smbus_initialized = 0; +smbus_t *smbus[NADDRS], *smbus_last[NADDRS]; + +#define ENABLE_SMBUS_LOG 1 +#ifdef ENABLE_SMBUS_LOG +int smbus_do_log = ENABLE_SMBUS_LOG; + + +static void +smbus_log(const char *fmt, ...) +{ + va_list ap; + + if (smbus_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define smbus_log(fmt, ...) +#endif + + +#ifdef ENABLE_SMBUS_LOG +static uint8_t smbus_null_read_byte(uint8_t addr, void *priv) { smbus_log("SMBus: read_byte(%02x)\n", addr); return(0xff); } +static uint8_t smbus_null_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv) { smbus_log("SMBus: read_byte_cmd(%02x, %02x)\n", addr, cmd); return(0xff); } +static uint16_t smbus_null_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv) { smbus_log("SMBus: read_word_cmd(%02x, %02x)\n", addr, cmd); return(0xffff); } +static uint8_t smbus_null_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv) { smbus_log("SMBus: read_block_cmd(%02x, %02x)\n", addr, cmd); return(0x00); }; +static void smbus_null_write_byte(uint8_t addr, uint8_t val, void *priv) { smbus_log("SMBus: write_byte(%02x, %02x)\n", addr, val); } +static void smbus_null_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv) { smbus_log("SMBus: write_byte_cmd(%02x, %02x, %02x)\n", addr, cmd, val); } +static void smbus_null_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv) { smbus_log("SMBus: write_word_cmd(%02x, %02x, %04x)\n", addr, cmd, val); } +static void smbus_null_write_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv) { smbus_log("SMBus: write_block_cmd(%02x, %02x, %02x)\n", addr, cmd, len); } +#endif + + +void +smbus_init(void) +{ + int c; + smbus_t *p, *q; + + if (!smbus_initialized) { + for (c=0; cprev; + free(p); + p = q; + } + p = NULL; + } + +#ifdef ENABLE_SMBUS_LOG + /* smbus[c] should be the only handler, pointing at the NULL catch handler. */ + p = (smbus_t *) malloc(sizeof(smbus_t)); + memset(p, 0, sizeof(smbus_t)); + smbus[c] = smbus_last[c] = p; + p->next = NULL; + p->prev = NULL; + p->read_byte = smbus_null_read_byte; + p->read_byte_cmd = smbus_null_read_byte_cmd; + p->read_word_cmd = smbus_null_read_word_cmd; + p->read_block_cmd = smbus_null_read_block_cmd; + p->write_byte = smbus_null_write_byte; + p->write_byte_cmd = smbus_null_write_byte_cmd; + p->write_word_cmd = smbus_null_write_word_cmd; + p->write_block_cmd = smbus_null_write_block_cmd; + p->priv = NULL; +#else + /* smbus[c] should be NULL. */ + smbus[c] = smbus_last[c] = NULL; +#endif + } +} + + +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), + 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), + void (*write_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), + void *priv) +{ + int c; + smbus_t *p, *q = NULL; + + for (c = 0; c < size; c++) { + p = smbus_last[base + c]; + q = (smbus_t *) malloc(sizeof(smbus_t)); + memset(q, 0, sizeof(smbus_t)); + if (p) { + p->next = q; + q->prev = p; + } else { + smbus[base + c] = q; + q->prev = NULL; + } + + q->read_byte = read_byte; + q->read_byte_cmd = read_byte_cmd; + q->read_word_cmd = read_word_cmd; + q->read_block_cmd = read_block_cmd; + + q->write_byte = write_byte; + q->write_byte_cmd = write_byte_cmd; + q->write_word_cmd = write_word_cmd; + q->write_block_cmd = write_block_cmd; + + q->priv = priv; + q->next = NULL; + + smbus_last[base + c] = q; + } +} + + +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), + 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), + void (*write_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), + void *priv) +{ + int c; + smbus_t *p; + + for (c = 0; c < size; c++) { + p = smbus[base + c]; + if (!p) + continue; + while(p) { + if ((p->read_byte == read_byte) && (p->read_byte_cmd == read_byte_cmd) && + (p->read_word_cmd == read_word_cmd) && (p->read_block_cmd == read_block_cmd) && + (p->write_byte == write_byte) && (p->write_byte_cmd == write_byte_cmd) && + (p->write_word_cmd == write_word_cmd) && (p->write_block_cmd == write_block_cmd) && + (p->priv == priv)) { + if (p->prev) + p->prev->next = p->next; + else + smbus[base + c] = p->next; + if (p->next) + p->next->prev = p->prev; + else + smbus_last[base + c] = p->prev; + free(p); + p = NULL; + break; + } + p = p->next; + } + } +} + + +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), + 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), + void (*write_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), + void *priv) +{ + if (set) + smbus_sethandler(base, size, read_byte, read_byte_cmd, read_word_cmd, read_block_cmd, write_byte, write_byte_cmd, write_word_cmd, write_block_cmd, priv); + else + smbus_removehandler(base, size, read_byte, read_byte_cmd, read_word_cmd, read_block_cmd, write_byte, write_byte_cmd, write_word_cmd, write_block_cmd, priv); +} + + +uint8_t +smbus_has_device(uint8_t addr) +{ + return(!!smbus[addr]); +} + + +uint8_t +smbus_read_byte(uint8_t addr) +{ + uint8_t ret = 0xff; + smbus_t *p; + int found = 0; + + p = smbus[addr]; + if (p) { + while(p) { + if (p->read_byte) { + ret &= p->read_byte(addr, p->priv); + found++; + } + p = p->next; + } + } + + return(ret); +} + +uint8_t +smbus_read_byte_cmd(uint8_t addr, uint8_t cmd) +{ + uint8_t ret = 0xff; + smbus_t *p; + int found = 0; + + p = smbus[addr]; + if (p) { + while(p) { + if (p->read_byte_cmd) { + ret &= p->read_byte_cmd(addr, cmd, p->priv); + found++; + } + p = p->next; + } + } + + return(ret); +} + +uint16_t +smbus_read_word_cmd(uint8_t addr, uint8_t cmd) +{ + uint16_t ret = 0xffff; + smbus_t *p; + int found = 0; + + p = smbus[addr]; + if (p) { + while(p) { + if (p->read_word_cmd) { + ret &= p->read_word_cmd(addr, cmd, p->priv); + found++; + } + p = p->next; + } + } + + return(ret); +} + +uint8_t +smbus_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data) +{ + uint8_t ret = 0; + smbus_t *p; + int found = 0; + + p = smbus[addr]; + if (p) { + while(p) { + if (p->read_block_cmd) { + ret = MAX(ret, p->read_block_cmd(addr, cmd, data, p->priv)); + found++; + } + p = p->next; + } + } + + return(ret); +} + + +void +smbus_write_byte(uint8_t addr, uint8_t val) +{ + smbus_t *p; + int found = 0; + + if (smbus[addr]) { + p = smbus[addr]; + while(p) { + if (p->write_byte) { + p->write_byte(addr, val, p->priv); + found++; + } + p = p->next; + } + } + + return; +} + +void +smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val) +{ + smbus_t *p; + int found = 0; + + if (smbus[addr]) { + p = smbus[addr]; + while(p) { + if (p->write_byte_cmd) { + p->write_byte_cmd(addr, cmd, val, p->priv); + found++; + } + p = p->next; + } + } + + return; +} + +void +smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val) +{ + smbus_t *p; + int found = 0; + + if (smbus[addr]) { + p = smbus[addr]; + while(p) { + if (p->write_word_cmd) { + p->write_word_cmd(addr, cmd, val, p->priv); + found++; + } + p = p->next; + } + } + + return; +} + +void +smbus_write_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len) +{ + smbus_t *p; + int found = 0; + + p = smbus[addr]; + if (p) { + while(p) { + if (p->write_block_cmd) { + p->write_block_cmd(addr, cmd, data, len, p->priv); + found++; + } + p = p->next; + } + } + + return; +} diff --git a/src/smbus.h b/src/smbus.h new file mode 100644 index 000000000..a4fec4a5c --- /dev/null +++ b/src/smbus.h @@ -0,0 +1,67 @@ +/* + * 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 the SMBus handler. + * + * Version: @(#)smbus.h 1.0.0 2020/03/21 + * + * Authors: RichardG, + * + * Copyright 2020 RichardG. + */ +#ifndef EMU_SMBUS_H +# define EMU_SMBUS_H + + +extern void smbus_init(void); + +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), + 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), + void (*write_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), + void *priv); + +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), + 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), + void (*write_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), + void *priv); + +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), + 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), + void (*write_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), + void *priv); + +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 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); +extern void smbus_write_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len); + + +#endif /*EMU_SMBUS_H*/ diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index d4d7ecc0b..6e4587712 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -597,7 +597,7 @@ MCHOBJ := machine.o machine_table.o \ m_at_286_386sx.o m_at_386dx_486.o \ m_at_socket4_5.o m_at_socket7_s7.o -DEVOBJ := bugger.o ibm_5161.o isamem.o isartc.o lpt.o $(SERIAL) \ +DEVOBJ := bugger.o hwm.o hwm_w83781d.o ibm_5161.o isamem.o isartc.o lpt.o $(SERIAL) \ sio_acc3221.o \ sio_fdc37c66x.o sio_fdc37c669.o \ sio_fdc37c93x.o \ @@ -605,6 +605,7 @@ DEVOBJ := bugger.o ibm_5161.o isamem.o isartc.o lpt.o $(SERIAL) \ sio_w83787f.o \ sio_w83877f.o sio_w83977f.o \ sio_um8669f.o \ + smbus.o \ keyboard.o \ keyboard_xt.o keyboard_at.o \ gameport.o \ diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw index 27588540a..ca7bed3ee 100644 --- a/src/win/Makefile_ndr.mingw +++ b/src/win/Makefile_ndr.mingw @@ -602,7 +602,7 @@ MCHOBJ := machine.o machine_table.o \ m_at_286_386sx.o m_at_386dx_486.o \ m_at_socket4_5.o m_at_socket7_s7.o -DEVOBJ := bugger.o ibm_5161.o isamem.o isartc.o lpt.o $(SERIAL) \ +DEVOBJ := bugger.o hwm.o hwm_w83781d.o ibm_5161.o isamem.o isartc.o lpt.o $(SERIAL) \ sio_acc3221.o \ sio_fdc37c66x.o sio_fdc37c669.o \ sio_fdc37c93x.o \ @@ -610,6 +610,7 @@ DEVOBJ := bugger.o ibm_5161.o isamem.o isartc.o lpt.o $(SERIAL) \ sio_w83787f.o \ sio_w83877f.o sio_w83977f.o \ sio_um8669f.o \ + smbus.o \ keyboard.o \ keyboard_xt.o keyboard_at.o \ gameport.o \ From 2c610dc5ceca07cc0c0ddc0698e0cb446938eadf Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sun, 22 Mar 2020 22:17:08 -0300 Subject: [PATCH 07/14] Remove unnecessary include --- src/hwm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hwm.c b/src/hwm.c index b3142c7a4..7f3ac49d6 100644 --- a/src/hwm.c +++ b/src/hwm.c @@ -14,7 +14,6 @@ * Copyright 2020 RichardG. */ -#include #include "device.h" #include "hwm.h" From b833f39496f9bef605bed6826e986cfd8948ff7d Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 23 Mar 2020 02:37:06 +0100 Subject: [PATCH 08/14] ROM read and Winbond fixes, also added the Winbond 83977EF. --- src/rom.c | 6 +++--- src/sio.h | 1 + src/sio_w83877f.c | 1 - src/sio_w83977f.c | 46 +++++++++++++++++++++++++++++++--------------- 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/rom.c b/src/rom.c index 174ca0479..1853fb3f0 100644 --- a/src/rom.c +++ b/src/rom.c @@ -121,7 +121,7 @@ rom_read(uint32_t addr, void *priv) return 0xff; if (addr >= (rom->mapping.base + rom->sz)) return 0xff; - return(rom->rom[addr & rom->mask]); + return(rom->rom[(addr - rom->mapping.base) & rom->mask]); } @@ -139,7 +139,7 @@ rom_readw(uint32_t addr, void *priv) return 0xffff; if (addr >= (rom->mapping.base + rom->sz)) return 0xffff; - return(*(uint16_t *)&rom->rom[addr & rom->mask]); + return(*(uint16_t *)&rom->rom[(addr - rom->mapping.base) & rom->mask]); } @@ -157,7 +157,7 @@ rom_readl(uint32_t addr, void *priv) return 0xffffffff; if (addr >= (rom->mapping.base + rom->sz)) return 0xffffffff; - return(*(uint32_t *)&rom->rom[addr & rom->mask]); + return(*(uint32_t *)&rom->rom[(addr - rom->mapping.base) & rom->mask]); } diff --git a/src/sio.h b/src/sio.h index fc6c2bd61..6009545ee 100644 --- a/src/sio.h +++ b/src/sio.h @@ -35,6 +35,7 @@ extern const device_t w83877tf_device; extern const device_t w83877tf_acorp_device; extern const device_t w83977f_device; extern const device_t w83977tf_device; +extern const device_t w83977ef_device; #endif /*EMU_SIO_H*/ diff --git a/src/sio_w83877f.c b/src/sio_w83877f.c index dadce5a6c..c9304e7db 100644 --- a/src/sio_w83877f.c +++ b/src/sio_w83877f.c @@ -253,7 +253,6 @@ w83877f_write(uint16_t port, uint8_t val, void *priv) return; } else if ((port == 0x252) || (port == 0x3f1)) { if (dev->locked) { - pclog("dev->locked\n"); if (dev->rw_locked) return; if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27)) diff --git a/src/sio_w83977f.c b/src/sio_w83977f.c index 286aa074a..770ce2c7a 100644 --- a/src/sio_w83977f.c +++ b/src/sio_w83977f.c @@ -88,7 +88,6 @@ w83977f_fdc_handler(w83977f_t *dev) fdc_remove(dev->fdc); - pclog("fdc: %02X %02X %04X\n", dev->dev_regs[0][0x00], dev->regs[0x22], io_base); if ((dev->dev_regs[0][0x00] & 0x01) && (dev->regs[0x22] & 0x01) && (io_base >= 0x100) && (io_base <= 0xff8)) fdc_set_base(dev->fdc, io_base); @@ -153,8 +152,6 @@ w83977f_write(uint16_t port, uint8_t val, void *priv) uint8_t valxor = 0; uint8_t ld = dev->regs[7]; - pclog("W83977F Write: %04X %02X\n", port, val); - if (index) { if ((val == 0x87) && !dev->locked) { if (dev->tries) { @@ -191,8 +188,8 @@ w83977f_write(uint16_t port, uint8_t val, void *priv) switch (dev->cur_reg) { case 0x02: - if (valxor & 0x02) - softresetx86(); + /* if (valxor & 0x02) + softresetx86(); */ break; case 0x22: if (valxor & 0x20) @@ -205,8 +202,11 @@ w83977f_write(uint16_t port, uint8_t val, void *priv) w83977f_fdc_handler(dev); break; case 0x26: + if (valxor & 0x40) + w83977f_remap(dev); if (valxor & 0x20) dev->rw_locked = (val & 0x20) ? 1 : 0; + break; case 0x30: if (valxor & 0x01) switch (ld) { case 0x00: @@ -329,8 +329,6 @@ w83977f_read(uint16_t port, void *priv) } } - pclog("W83977F Read: %04X %02X\n", port, ret); - return ret; } @@ -344,8 +342,13 @@ w83977f_reset(w83977f_t *dev) for (i = 0; i < 256; i++) memset(dev->dev_regs[i], 0, 208); - dev->regs[0x20] = 0x97; - dev->regs[0x21] = dev->type ? 0x73 : 0x71; + if (dev->type < 2) { + dev->regs[0x20] = 0x97; + dev->regs[0x21] = dev->type ? 0x73 : 0x71; + } else { + dev->regs[0x20] = 0x52; + dev->regs[0x21] = 0xf0; + } dev->regs[0x22] = 0xff; dev->regs[0x24] = dev->type ? 0x84 : 0xa4; @@ -368,9 +371,9 @@ w83977f_reset(w83977f_t *dev) dev->dev_regs[1][0x30] = 0x03; dev->dev_regs[1][0x31] = 0x78; dev->dev_regs[1][0x40] = 0x07; if (!dev->type) - dev->dev_regs[1][0x41] = 0x02; /* Read-only */ + dev->dev_regs[1][0x41] = 0x01 /*0x02*/; /* Read-only */ dev->dev_regs[1][0x44] = 0x04; - dev->dev_regs[1][0xc0] = 0x3c; /* The datasheet says default is 3f, but also default is priner mode. */ + dev->dev_regs[1][0xc0] = 0x3c; /* The datasheet says default is 3f, but also default is printer mode. */ /* Logical Device 2 (UART A) */ dev->dev_regs[2][0x00] = 0x01; @@ -404,6 +407,7 @@ w83977f_reset(w83977f_t *dev) if (!dev->type) dev->dev_regs[5][0x01] = 0x02; dev->dev_regs[5][0x30] = 0x00; dev->dev_regs[5][0x31] = 0x60; + dev->dev_regs[5][0x32] = 0x00; dev->dev_regs[5][0x33] = 0x64; dev->dev_regs[5][0x40] = 0x01; if (!dev->type) dev->dev_regs[5][0x41] = 0x02; /* Read-only */ @@ -448,10 +452,12 @@ w83977f_reset(w83977f_t *dev) /* Logical Device 9 (Auxiliary I/O Part III) */ if (dev->type) { - dev->dev_regs[7][0xb0] = 0x01; dev->dev_regs[7][0xb1] = 0x01; - dev->dev_regs[7][0xb2] = 0x01; dev->dev_regs[7][0xb3] = 0x01; - dev->dev_regs[7][0xb4] = 0x01; dev->dev_regs[7][0xb5] = 0x01; - dev->dev_regs[7][0xb6] = 0x01; dev->dev_regs[7][0xb7] = 0x01; + dev->dev_regs[9][0xb0] = 0x01; dev->dev_regs[9][0xb1] = 0x01; + dev->dev_regs[9][0xb2] = 0x01; dev->dev_regs[9][0xb3] = 0x01; + dev->dev_regs[9][0xb4] = 0x01; dev->dev_regs[9][0xb5] = 0x01; + dev->dev_regs[9][0xb6] = 0x01; dev->dev_regs[9][0xb7] = 0x01; + + dev->dev_regs[10][0xc0] = 0x8f; } fdc_reset(dev->fdc); @@ -517,3 +523,13 @@ const device_t w83977tf_device = { NULL, NULL, NULL, NULL }; + + +const device_t w83977ef_device = { + "Winbond W83977TF Super I/O", + 0, + 2, + w83977f_init, w83977f_close, NULL, + NULL, NULL, NULL, + NULL +}; From ae1f1529ea74543780d06b3e7cda7ee6ed827fac Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 23 Mar 2020 02:38:03 +0100 Subject: [PATCH 09/14] The P2B now correctly uses the W83877EF. --- src/machine/m_at_socket8.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index b53f8d623..02afc849b 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * Implementation of Socket 8 machines. + * Implementation of Socket 8 and Slot 1 machines. * * Version: @(#)m_at_socket8.c 1.0.0 2019/05/16 * @@ -163,7 +163,7 @@ machine_at_p2bls_init(const machine_t *model) device_add(&i440bx_device); device_add(&piix4_device); device_add(&keyboard_ps2_pci_device); - device_add(&w83977tf_device); + device_add(&w83977ef_device); device_add(&sst_flash_39sf020_device); return ret; From b1aea66e4101563041bdcc13e924f1f694aaac73 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 23 Mar 2020 02:41:18 +0100 Subject: [PATCH 10/14] Aded optional PCI slot logging to detect unassigned slots (used for detecting what slot the southbridge should use, for example). --- src/pci.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/pci.c b/src/pci.c index 4e7eb1eba..ada976629 100644 --- a/src/pci.c +++ b/src/pci.c @@ -127,7 +127,15 @@ pci_write(uint16_t port, uint8_t val, void *priv) pci_log("Writing to PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); pci_cards[slot].write(pci_func, pci_index | (port & 3), val, pci_cards[slot].priv); } +#ifdef ENABLE_PCI_LOG + else + pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif } +#ifdef ENABLE_PCI_LOG + else + pci_log("Writing to unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif } break; @@ -150,7 +158,15 @@ pci_read(uint16_t port, void *priv) if (slot != 0xff) { if (pci_cards[slot].read) return pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv); +#ifdef ENABLE_PCI_LOG + else + pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif } +#ifdef ENABLE_PCI_LOG + else + pci_log("Reading from unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif } return 0xff; @@ -237,10 +253,15 @@ pci_type2_write(uint16_t port, uint8_t val, void *priv) if (slot != 0xff) { if (pci_cards[slot].write) pci_cards[slot].write(pci_func, pci_index | (port & 3), val, pci_cards[slot].priv); +#ifdef ENABLE_PCI_LOG else - pclog("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); - } else - pclog("Writing to unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); + pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif + } +#ifdef ENABLE_PCI_LOG + else + pci_log("Writing to unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif } } } @@ -265,10 +286,15 @@ pci_type2_read(uint16_t port, void *priv) if (slot != 0xff) { if (pci_cards[slot].read) return pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv); +#ifdef ENABLE_PCI_LOG else - pclog("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); - } else - pclog("Reading from unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); + pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif + } +#ifdef ENABLE_PCI_LOG + else + pci_log("Reading from unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif } return 0xff; @@ -649,7 +675,6 @@ void trc_write(uint16_t port, uint8_t val, void *priv) { pci_log("TRC Write: %02X\n", val); - pclog("[%04X:%08X] TRC Write: %02X\n", CS, cpu_state.pc, val); if (!(trc_reg & 4) && (val & 4)) trc_reset(val); From 449118db21f49ff39485b4cd825b5c727f0b1707 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 23 Mar 2020 02:44:11 +0100 Subject: [PATCH 11/14] SST flash fixes - the implementation of the 29EE0*0 is now correct (BIOS flashers and CIH work). --- src/sst_flash.c | 196 +++++++++++++++++++++++++++++------------------- 1 file changed, 119 insertions(+), 77 deletions(-) diff --git a/src/sst_flash.c b/src/sst_flash.c index 724a3e724..7cb3e3292 100644 --- a/src/sst_flash.c +++ b/src/sst_flash.c @@ -34,18 +34,20 @@ typedef struct sst_t { - uint8_t id, is_39, page_bytes, pad; + uint8_t id, is_39, page_bytes, sdp; int command_state, id_mode, - erase, dirty; + dirty; - uint32_t size, mask; + uint32_t size, mask, + page_mask, page_base; + uint8_t page_buffer[128]; uint8_t *array; mem_mapping_t mapping[8], mapping_h[8]; - pc_timer_t page_load_timer; + pc_timer_t page_write_timer; } sst_t; @@ -53,6 +55,7 @@ static wchar_t flash_path[1024]; #define SST_CHIP_ERASE 0x10 /* Both 29 and 39, 6th cycle */ +#define SST_SDP_DISABLE 0x20 /* Only 29, Software data protect disable and write - treat as write */ #define SST_SECTOR_ERASE 0x30 /* Only 39, 6th cycle */ #define SST_SET_ID_MODE_ALT 0x60 /* Only 29, 6th cycle */ #define SST_ERASE 0x80 /* Both 29 and 39 */ @@ -74,63 +77,82 @@ static wchar_t flash_path[1024]; static void -sst_new_command(sst_t *dev, uint8_t val) +sst_sector_erase(sst_t *dev, uint32_t addr) { - switch (val) { + memset(&dev->array[addr & (dev->mask & ~0xfff)], 0xff, 4096); + dev->dirty = 1; +} + + +static void +sst_new_command(sst_t *dev, uint32_t addr, uint8_t val) +{ + if (dev->command_state == 5) switch (val) { case SST_CHIP_ERASE: - if (dev->erase) - memset(dev->array, 0xff, 0x20000); + memset(dev->array, 0xff, 0x20000); dev->command_state = 0; - dev->erase = 0; break; - case SST_ERASE: + case SST_SDP_DISABLE: + if (!dev->is_39) + dev->sdp = 0; dev->command_state = 0; - dev->erase = 1; break; - case SST_SET_ID_MODE: - if (!dev->id_mode) - dev->id_mode = 1; + case SST_SECTOR_ERASE: + if (dev->is_39) + sst_sector_erase(dev, addr); dev->command_state = 0; - dev->erase = 0; break; case SST_SET_ID_MODE_ALT: - if (!dev->is_39 && dev->erase && !dev->id_mode) - dev->id_mode = 1; + dev->id_mode = 1; dev->command_state = 0; - dev->erase = 0; - break; - - case SST_BYTE_PROGRAM: - dev->command_state = 3; - if (!dev->is_39) { - dev->page_bytes = 0; - timer_set_delay_u64(&dev->page_load_timer, 100 * TIMER_USEC); - } - dev->erase = 0; - break; - - case SST_CLEAR_ID_MODE: - if (dev->id_mode) - dev->id_mode = 0; - dev->command_state = 0; - dev->erase = 0; break; default: dev->command_state = 0; - dev->erase = 0; + break; + } else switch (val) { + case SST_ERASE: + dev->command_state = 3; + break; + + case SST_SET_ID_MODE: + dev->id_mode = 1; + dev->command_state = 0; + break; + + case SST_BYTE_PROGRAM: + if (!dev->is_39) { + memset(dev->page_buffer, 0xff, 128); + dev->page_bytes = 0; + timer_on_auto(&dev->page_write_timer, 210.0); + } + dev->command_state = 6; + break; + + case SST_CLEAR_ID_MODE: + dev->id_mode = 0; + dev->command_state = 0; + break; + + default: + dev->command_state = 0; + break; } } static void -sst_sector_erase(sst_t *dev, uint32_t addr) +sst_page_write(void *priv) { - memset(&dev->array[addr & (dev->mask & ~0xfff)], 0xff, 4096); + sst_t *dev = (sst_t *) priv; + + memcpy(&(dev->array[dev->page_base]), dev->page_buffer, 128); dev->dirty = 1; + dev->page_bytes = 0; + dev->command_state = 0; } @@ -148,6 +170,19 @@ sst_read_id(uint32_t addr, void *p) } +static void +sst_buf_write(sst_t *dev, uint32_t addr, uint8_t val) +{ + dev->page_buffer[addr & 0x0000007f] = val; + timer_disable(&dev->page_write_timer); + dev->page_bytes++; + if (dev->page_bytes >= 128) + sst_page_write(dev); + else + timer_set_delay_u64(&dev->page_write_timer, 210 * TIMER_USEC); +} + + static void sst_write(uint32_t addr, uint8_t val, void *p) { @@ -155,44 +190,55 @@ sst_write(uint32_t addr, uint8_t val, void *p) switch (dev->command_state) { case 0: - /* 1st Bus Write Cycle */ - if ((val == 0xf0) && dev->is_39) { + case 3: + /* 1st and 4th Bus Write Cycle */ + if ((val == 0xf0) && dev->is_39 && (dev->command_state == 0)) { if (dev->id_mode) dev->id_mode = 0; - } else if ((addr & 0xffff) == 0x5555 && val == 0xaa) - dev->command_state = 1; - else dev->command_state = 0; + } else if (((addr & 0x7fff) == 0x5555) && (val == 0xaa)) + dev->command_state++; + else { + if (!dev->is_39 && !dev->sdp && (dev->command_state == 0)) { + /* 29 series, software data protection off, start loading the page. */ + dev->page_base = addr & dev->page_mask; /* First byte, A7 onwards of its address are the page mask. */ + dev->command_state = 7; + sst_buf_write(dev, addr, val); + } + dev->command_state = 0; + } break; case 1: - /* 2nd Bus Write Cycle */ - if ((addr & 0xffff) == 0x2aaa && val == 0x55) - dev->command_state = 2; + case 4: + /* 2nd and 5th Bus Write Cycle */ + if (((addr & 0x7fff) == 0x2aaa) && (val == 0x55)) + dev->command_state++; else dev->command_state = 0; break; case 2: - /* 3rd Bus Write Cycle */ - if ((addr & 0xffff) == 0x5555) - sst_new_command(dev, val); - else if (dev->is_39 && (val == SST_SECTOR_ERASE) && dev->erase) { - sst_sector_erase(dev, addr); - dev->command_state = 0; - } else + case 5: + /* 3rd and 6th Bus Write Cycle */ + if ((addr & 0x7fff) == 0x5555) + sst_new_command(dev, addr, val); + else dev->command_state = 0; break; - case 3: - dev->array[addr & dev->mask] = val; - if (!dev->is_39) { - timer_disable(&dev->page_load_timer); - if (dev->page_bytes == 0) - timer_set_delay_u64(&dev->page_load_timer, 100 * TIMER_USEC); - else - timer_set_delay_u64(&dev->page_load_timer, 200 * TIMER_USEC); - dev->page_bytes++; - } else + case 6: + /* Page Load Cycle (29) / Data Write Cycle (39SF) */ + if (dev->is_39) { + dev->array[addr & dev->mask] = val; dev->command_state = 0; - dev->dirty = 1; + dev->dirty = 1; + } else { + dev->page_base = addr & dev->page_mask; /* First byte, A7 onwards of its address are the page mask. */ + dev->command_state++; + sst_buf_write(dev, addr, val); + } + break; + case 7: + if (!dev->is_39 && ((addr & dev->page_mask) == dev->page_base)) + sst_buf_write(dev, addr, val); break; } } @@ -255,15 +301,6 @@ sst_readl(uint32_t addr, void *p) } -static void -sst_page_load(void *priv) -{ - sst_t *dev = (sst_t *) priv; - - dev->command_state = 0; -} - - static void sst_add_mappings(sst_t *dev) { @@ -331,6 +368,8 @@ sst_init(const device_t *info) else dev->size = 0x20000; dev->mask = dev->size - 1; + dev->page_mask = dev->mask & 0xffffff80; /* Filter out A0-A6. */ + dev->sdp = 1; sst_add_mappings(dev); @@ -339,13 +378,14 @@ sst_init(const device_t *info) if (fread(&(dev->array[0x00000]), 1, dev->size, f) != dev->size) fatal("Less than %i bytes read from the SST Flash ROM file\n", dev->size); fclose(f); - } + } else + dev->dirty = 1; /* It is by definition dirty on creation. */ free(flash_name); free(machine_name); if (!dev->is_39) - timer_add(&dev->page_load_timer, sst_page_load, dev, 0); + timer_add(&dev->page_write_timer, sst_page_write, dev, 0); return dev; } @@ -357,9 +397,11 @@ sst_close(void *p) FILE *f; sst_t *dev = (sst_t *)p; - f = nvr_fopen(flash_path, L"wb"); - fwrite(&(dev->array[0x00000]), dev->size, 1, f); - fclose(f); + if (dev->dirty) { + f = nvr_fopen(flash_path, L"wb"); + fwrite(&(dev->array[0x00000]), dev->size, 1, f); + fclose(f); + } free(dev->array); dev->array = NULL; From 7a354ac7a86e696d60d58f3f28c669c96f4ae875 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 23 Mar 2020 02:45:48 +0100 Subject: [PATCH 12/14] Keyboard_at.c newline. --- src/keyboard_at.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 6ee7fbd50..dfaf1d9ca 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -2622,4 +2622,4 @@ uint8_t keyboard_at_get_mouse_scan(void) { return(mouse_scan ? 0x10 : 0x00); -} \ No newline at end of file +} From df7f6dde8a114c07c54b93b03754d4974c2cb6cc Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 23 Mar 2020 02:50:55 +0100 Subject: [PATCH 13/14] Slight file cleanup and removed some wrong code from intel_flash.c. --- src/intel_flash - Cópia.c | 561 ------------------ src/intel_flash.c | 12 +- src/intel_piix - Cópia.c | 1131 ------------------------------------- 3 files changed, 1 insertion(+), 1703 deletions(-) delete mode 100644 src/intel_flash - Cópia.c delete mode 100644 src/intel_piix - Cópia.c diff --git a/src/intel_flash - Cópia.c b/src/intel_flash - Cópia.c deleted file mode 100644 index cb08eb44b..000000000 --- a/src/intel_flash - Cópia.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Implementation of the Intel 1 Mbit and 2 Mbit, 8-bit and - * 16-bit flash devices. - * - * Version: @(#)intel_flash.c 1.0.19 2019/06/25 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - */ -#include -#include -#include -#include -#include -#include "86box.h" -#include "device.h" -#include "mem.h" -#include "machine.h" -#include "timer.h" -#include "nvr.h" -#include "plat.h" - - -#define FLAG_BYTEMODE 4 -#define FLAG_WORD 4 -#define FLAG_BXB 2 -#define FLAG_INV_A16 1 - - -enum -{ - BLOCK_MAIN1, - BLOCK_MAIN2, - BLOCK_DATA1, - BLOCK_DATA2, - BLOCK_BOOT, - BLOCKS_NUM -}; - -enum -{ - CMD_READ_ARRAY = 0xff, - CMD_IID = 0x90, - CMD_READ_STATUS = 0x70, - CMD_CLEAR_STATUS = 0x50, - CMD_ERASE_SETUP = 0x20, - CMD_ERASE_CONFIRM = 0xd0, - CMD_ERASE_SUSPEND = 0xb0, - CMD_PROGRAM_SETUP = 0x40, - CMD_PROGRAM_SETUP_ALT = 0x10 -}; - - -typedef struct flash_t -{ - uint8_t command, status, - pad, flags, - *array; - - uint16_t flash_id, pad16; - - uint32_t program_addr, - block_start[BLOCKS_NUM], block_end[BLOCKS_NUM], - block_len[BLOCKS_NUM]; - - mem_mapping_t mapping[4], mapping_h[8]; -} flash_t; - - -static wchar_t flash_path[1024]; - - -static uint16_t flash_readw(uint32_t addr, void *p); - - -static uint8_t -flash_read(uint32_t addr, void *p) -{ - flash_t *dev = (flash_t *) p; - uint8_t ret = 0xff; - - if (dev->flags & FLAG_WORD) - return flash_readw(addr, p) & 0xff; - - if (dev->flags & FLAG_INV_A16) - addr ^= 0x10000; - addr &= biosmask; - - switch (dev->command) { - case CMD_READ_ARRAY: - default: - ret = dev->array[addr]; - break; - - case CMD_IID: - /* Yes, & 2 is correct for the 100BX/200BX in BYTE mode. */ - if (addr & 1) - ret = dev->flash_id & 0xff; - else - ret = 0x89; - // pclog("id b %i: %02X\n", addr & 1, ret); - break; - - case CMD_READ_STATUS: - ret = dev->status; - break; - } - -#if 0 - if ((dev->command & 0x0f) && (dev->command != 0xff)) - ret = dev->status; -#endif - - return ret; -} - - -static uint16_t -flash_readw(uint32_t addr, void *p) -{ - flash_t *dev = (flash_t *) p; - uint16_t *q; - uint16_t ret = 0xffff; - - if (!(dev->flags & FLAG_WORD)) - return flash_read(addr, p) | (flash_read(addr + 1, p) << 8); - - if (dev->flags & FLAG_INV_A16) - addr ^= 0x10000; - addr &= biosmask; - - if (dev->flags & FLAG_WORD) - addr &= 0xfffffffe; - - q = (uint16_t *)&(dev->array[addr]); - ret = *q; - - switch (dev->command) { - case CMD_READ_ARRAY: - default: - break; - - case CMD_IID: - // pclog("id w %i: %02X\n", addr & 2, ret); - if (addr & 2) - ret = dev->flash_id; - else - ret = 0x0089; - break; - - case CMD_READ_STATUS: - ret = dev->status; - break; - } - - return ret; -} - - -static uint32_t -flash_readl(uint32_t addr, void *p) -{ - flash_t *dev = (flash_t *)p; - uint32_t *q; - - if (dev->flags & FLAG_INV_A16) - addr ^= 0x10000; - addr &= biosmask; - - q = (uint32_t *)&(dev->array[addr]); - - return *q; - // return flash_readw(addr, p) | (flash_readw(addr + 2, p) << 16); -} - - -static void flash_writew(uint32_t addr, uint16_t val, void *p); - - -static void -flash_write(uint32_t addr, uint8_t val, void *p) -{ - flash_t *dev = (flash_t *) p; - int i; - uint32_t bb_mask = biosmask & 0xffffe000; - uint32_t o = addr; - if (biosmask == 0x3ffff) - bb_mask &= 0xffffc000; - - if (dev->flags & FLAG_WORD) { - flash_writew(addr, val, p); - return; - } - - if (dev->flags & FLAG_INV_A16) - addr ^= 0x10000; - addr &= biosmask; - - if ((addr >= 0x2e400) && (addr <= 0x2e43f)) { - dev->array[addr] = val; - return; - } - - switch (dev->command) { - case CMD_ERASE_SETUP: - if (val == CMD_ERASE_CONFIRM) { - for (i = 0; i < 3; i++) { - if ((addr >= dev->block_start[i]) && (addr <= dev->block_end[i])) - memset(&(dev->array[dev->block_start[i]]), 0xff, dev->block_len[i]); - } - - dev->status = 0x80; - } - dev->command = CMD_READ_STATUS; - break; - - case CMD_PROGRAM_SETUP: - case CMD_PROGRAM_SETUP_ALT: - if (((addr & bb_mask) != (dev->block_start[4] & bb_mask)) && (addr == dev->program_addr)) - dev->array[addr] = val; - dev->command = CMD_READ_STATUS; - dev->status = 0x80; - break; - - default: - dev->command = val; - // pclog("[%04X:%08X] (%08X, %02X) [%08X] command b = %02X\n", CS, cpu_state.pc, cpu_state.seg_cs.base, opcode, o, dev->command); -#if 0 - if (val == 0x93) { - FILE *f = fopen("d:\\queen\\86boxnew\\mem.dmp", "wb"); - for (i = 0; i < 1114096; i++) - fputc(mem_readb_phys(i), f); - fclose(f); - f = fopen("d:\\queen\\86boxnew\\highbios.dmp", "wb"); - for (i = 0; i < 524288; i++) - fputc(mem_readb_phys(i + 0xfff80000), f); - fclose(f); - fatal("Fo' shizzle da nizzle\n"); - } -#endif - switch (val) { - case CMD_CLEAR_STATUS: - dev->status = 0; - break; - case CMD_PROGRAM_SETUP: - case CMD_PROGRAM_SETUP_ALT: - dev->program_addr = addr; - break; - } - } -} - - -static void -flash_writew(uint32_t addr, uint16_t val, void *p) -{ - flash_t *dev = (flash_t *) p; - int i; - uint32_t bb_mask = biosmask & 0xffffe000; - if (biosmask == 0x3ffff) - bb_mask &= 0xffffc000; - - if (!(dev->flags & FLAG_WORD)) { - // flash_write(addr, val & 0xff, p); - // flash_write(addr + 1, (val >> 8) & 0xff, p); - return; - } - - if (dev->flags & FLAG_INV_A16) - addr ^= 0x10000; - addr &= biosmask; - - if (dev->flags & FLAG_WORD) switch (dev->command) { - case CMD_ERASE_SETUP: - if (val == CMD_ERASE_CONFIRM) { - for (i = 0; i < 3; i++) { - if ((addr >= dev->block_start[i]) && (addr <= dev->block_end[i])) - memset(&(dev->array[dev->block_start[i]]), 0xff, dev->block_len[i]); - } - - dev->status = 0x80; - } - dev->command = CMD_READ_STATUS; - break; - - case CMD_PROGRAM_SETUP: - case CMD_PROGRAM_SETUP_ALT: - if (((addr & bb_mask) != (dev->block_start[4] & bb_mask)) && (addr == dev->program_addr)) - *(uint16_t *) (&dev->array[addr]) = val; - dev->command = CMD_READ_STATUS; - dev->status = 0x80; - break; - - default: - dev->command = val & 0xff; - // pclog("command w = %02X\n", dev->command); - switch (val) { - case CMD_CLEAR_STATUS: - dev->status = 0; - break; - case CMD_PROGRAM_SETUP: - case CMD_PROGRAM_SETUP_ALT: - dev->program_addr = addr; - break; - } - } -} - - -static void -flash_writel(uint32_t addr, uint32_t val, void *p) -{ - flash_writew(addr, val & 0xffff, p); - flash_writew(addr + 2, (val >> 16) & 0xffff, p); -} - - -static void -intel_flash_add_mappings(flash_t *dev) -{ - int max = 2, i = 0; - uint32_t base, fbase; - uint32_t sub = 0x20000; - - if (biosmask == 0x3ffff) { - sub = 0x40000; - max = 4; - } - - for (i = 0; i < max; i++) { - if (biosmask == 0x3ffff) - base = 0xc0000 + (i << 16); - else - base = 0xe0000 + (i << 16); - fbase = base & biosmask; - if (dev->flags & FLAG_INV_A16) - fbase ^= 0x10000; - - memcpy(&dev->array[fbase], &rom[base & biosmask], 0x10000); - - if ((max == 2) || (i >= 2)) { - mem_mapping_add(&(dev->mapping[i]), base, 0x10000, - flash_read, flash_readw, flash_readl, - flash_write, flash_writew, flash_writel, - dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); - } - mem_mapping_add(&(dev->mapping_h[i]), (base | 0xfff00000) - sub, 0x10000, - flash_read, flash_readw, flash_readl, - flash_write, flash_writew, flash_writel, - dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); - mem_mapping_add(&(dev->mapping_h[i + 4]), (base | 0xfff00000), 0x10000, - flash_read, flash_readw, flash_readl, - flash_write, flash_writew, flash_writel, - dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); - } -} - - -static void * -intel_flash_init(const device_t *info) -{ - FILE *f; - int l; - flash_t *dev; - wchar_t *machine_name, *flash_name; - uint8_t type = info->local & 0xff; - - dev = malloc(sizeof(flash_t)); - memset(dev, 0, sizeof(flash_t)); - - l = strlen(machine_get_internal_name_ex(machine))+1; - machine_name = (wchar_t *) malloc(l * sizeof(wchar_t)); - mbstowcs(machine_name, machine_get_internal_name_ex(machine), l); - l = wcslen(machine_name)+5; - flash_name = (wchar_t *)malloc(l*sizeof(wchar_t)); - swprintf(flash_name, l, L"%ls.bin", machine_name); - - if (wcslen(flash_name) <= 1024) - wcscpy(flash_path, flash_name); - else - wcsncpy(flash_path, flash_name, 1024); - - dev->flags = info->local & 0xff; - - mem_mapping_disable(&bios_mapping); - mem_mapping_disable(&bios_high_mapping); - - dev->array = (uint8_t *) malloc(biosmask + 1); - memset(dev->array, 0xff, biosmask + 1); - - if (biosmask == 0x3ffff) { - if (dev->flags & FLAG_WORD) - dev->flash_id = (dev->flags & FLAG_BXB) ? 0x2275 : 0x2274; - else - dev->flash_id = (dev->flags & FLAG_BXB) ? 0x7D : 0x7C; - - /* The block lengths are the same both flash types. */ - dev->block_len[BLOCK_MAIN1] = 0x20000; - dev->block_len[BLOCK_MAIN2] = 0x18000; - dev->block_len[BLOCK_DATA1] = 0x02000; - dev->block_len[BLOCK_DATA2] = 0x02000; - dev->block_len[BLOCK_BOOT] = 0x04000; - - if (dev->flags & FLAG_BXB) { /* 28F002BX-B/28F200BX-B */ - dev->block_start[BLOCK_MAIN1] = 0x20000; /* MAIN BLOCK 1 */ - dev->block_end[BLOCK_MAIN1] = 0x3ffff; - dev->block_start[BLOCK_MAIN2] = 0x08000; /* MAIN BLOCK 2 */ - dev->block_end[BLOCK_MAIN2] = 0x1ffff; - dev->block_start[BLOCK_DATA1] = 0x06000; /* DATA AREA 1 BLOCK */ - dev->block_end[BLOCK_DATA1] = 0x07fff; - dev->block_start[BLOCK_DATA2] = 0x04000; /* DATA AREA 2 BLOCK */ - dev->block_end[BLOCK_DATA2] = 0x05fff; - dev->block_start[BLOCK_BOOT] = 0x00000; /* BOOT BLOCK */ - dev->block_end[BLOCK_BOOT] = 0x03fff; - } else { /* 28F002BX-T/28F200BX-T */ - dev->block_start[BLOCK_MAIN1] = 0x00000; /* MAIN BLOCK 1 */ - dev->block_end[BLOCK_MAIN1] = 0x1ffff; - dev->block_start[BLOCK_MAIN2] = 0x20000; /* MAIN BLOCK 2 */ - dev->block_end[BLOCK_MAIN2] = 0x37fff; - dev->block_start[BLOCK_DATA1] = 0x38000; /* DATA AREA 1 BLOCK */ - dev->block_end[BLOCK_DATA1] = 0x39fff; - dev->block_start[BLOCK_DATA2] = 0x3a000; /* DATA AREA 2 BLOCK */ - dev->block_end[BLOCK_DATA2] = 0x3bfff; - dev->block_start[BLOCK_BOOT] = 0x3c000; /* BOOT BLOCK */ - dev->block_end[BLOCK_BOOT] = 0x3ffff; - } - } else { - dev->flash_id = (type & FLAG_BXB) ? 0x95 : 0x94; - - /* The block lengths are the same both flash types. */ - dev->block_len[BLOCK_MAIN1] = 0x1c000; - dev->block_len[BLOCK_MAIN2] = 0x00000; - dev->block_len[BLOCK_DATA1] = 0x01000; - dev->block_len[BLOCK_DATA2] = 0x01000; - dev->block_len[BLOCK_BOOT] = 0x02000; - - if (dev->flags & FLAG_BXB) { /* 28F001BX-B/28F100BX-B */ - dev->block_start[BLOCK_MAIN1] = 0x04000; /* MAIN BLOCK 1 */ - dev->block_end[BLOCK_MAIN1] = 0x1ffff; - dev->block_start[BLOCK_MAIN2] = 0xfffff; /* MAIN BLOCK 2 */ - dev->block_end[BLOCK_MAIN2] = 0xfffff; - dev->block_start[BLOCK_DATA1] = 0x02000; /* DATA AREA 1 BLOCK */ - dev->block_end[BLOCK_DATA1] = 0x02fff; - dev->block_start[BLOCK_DATA2] = 0x03000; /* DATA AREA 2 BLOCK */ - dev->block_end[BLOCK_DATA2] = 0x03fff; - dev->block_start[BLOCK_BOOT] = 0x00000; /* BOOT BLOCK */ - dev->block_end[BLOCK_BOOT] = 0x01fff; - } else { /* 28F001BX-T/28F100BX-T */ - dev->block_start[BLOCK_MAIN1] = 0x00000; /* MAIN BLOCK 1 */ - dev->block_end[BLOCK_MAIN1] = 0x1bfff; - dev->block_start[BLOCK_MAIN2] = 0xfffff; /* MAIN BLOCK 2 */ - dev->block_end[BLOCK_MAIN2] = 0xfffff; - dev->block_start[BLOCK_DATA1] = 0x1c000; /* DATA AREA 1 BLOCK */ - dev->block_end[BLOCK_DATA1] = 0x1cfff; - dev->block_start[BLOCK_DATA2] = 0x1d000; /* DATA AREA 2 BLOCK */ - dev->block_end[BLOCK_DATA2] = 0x1dfff; - dev->block_start[BLOCK_BOOT] = 0x1e000; /* BOOT BLOCK */ - dev->block_end[BLOCK_BOOT] = 0x1ffff; - } - } - - intel_flash_add_mappings(dev); - - dev->command = CMD_READ_ARRAY; - dev->status = 0; - - f = nvr_fopen(flash_path, L"rb"); - if (f) { - fread(&(dev->array[dev->block_start[BLOCK_MAIN1]]), dev->block_len[BLOCK_MAIN1], 1, f); - if (dev->block_len[BLOCK_MAIN2]) - fread(&(dev->array[dev->block_start[BLOCK_MAIN2]]), dev->block_len[BLOCK_MAIN2], 1, f); - fread(&(dev->array[dev->block_start[BLOCK_DATA1]]), dev->block_len[BLOCK_DATA1], 1, f); - fread(&(dev->array[dev->block_start[BLOCK_DATA2]]), dev->block_len[BLOCK_DATA2], 1, f); - fclose(f); - } - - free(flash_name); - free(machine_name); - - if (dev->flags & FLAG_WORD) - dev->flags &= ~FLAG_WORD; - - return dev; -} - - -static void -intel_flash_close(void *p) -{ - FILE *f; - flash_t *dev = (flash_t *)p; - - f = nvr_fopen(flash_path, L"wb"); - fwrite(&(dev->array[dev->block_start[BLOCK_MAIN1]]), dev->block_len[BLOCK_MAIN1], 1, f); - if (dev->block_len[BLOCK_MAIN2]) - fwrite(&(dev->array[dev->block_start[BLOCK_MAIN2]]), dev->block_len[BLOCK_MAIN2], 1, f); - fwrite(&(dev->array[dev->block_start[BLOCK_DATA1]]), dev->block_len[BLOCK_DATA1], 1, f); - fwrite(&(dev->array[dev->block_start[BLOCK_DATA2]]), dev->block_len[BLOCK_DATA2], 1, f); - fclose(f); - - free(dev); -} - - -/* For AMI BIOS'es - Intel 28F001BXT with A16 pin inverted. */ -const device_t intel_flash_bxt_ami_device = -{ - "Intel 28F001BXT/28F002BXT Flash BIOS", - 0, - FLAG_INV_A16, - intel_flash_init, - intel_flash_close, - NULL, - NULL, NULL, NULL, NULL -}; - - -#if defined(DEV_BRANCH) && defined(USE_TC430HX) -const device_t intel_flash_bxtw_ami_device = -{ - "Intel 28F100BXT/28F200BXT Flash BIOS", - 0, - FLAG_INV_A16 | FLAG_WORD, - intel_flash_init, - intel_flash_close, - NULL, - NULL, NULL, NULL, NULL -}; -#endif - - -const device_t intel_flash_bxt_device = -{ - "Intel 28F001BXT/28F002BXT Flash BIOS", - 0, 0, - intel_flash_init, - intel_flash_close, - NULL, - NULL, NULL, NULL, NULL -}; - - -const device_t intel_flash_bxb_device = -{ - "Intel 28F001BXB/28F002BXB Flash BIOS", - 0, FLAG_BXB, - intel_flash_init, - intel_flash_close, - NULL, - NULL, NULL, NULL, NULL -}; diff --git a/src/intel_flash.c b/src/intel_flash.c index 59dd16cc4..396899621 100644 --- a/src/intel_flash.c +++ b/src/intel_flash.c @@ -90,11 +90,6 @@ flash_read(uint32_t addr, void *p) addr &= biosmask; switch (dev->command) { - case 0x00: - case 0x93: - ret = 0xff; - break; - case CMD_READ_ARRAY: default: ret = dev->array[addr]; @@ -102,7 +97,7 @@ flash_read(uint32_t addr, void *p) case CMD_IID: if (addr & 1) - ret = dev->flash_id & 0xff; + ret = dev->flash_id & 0xff; else ret = 0x89; break; @@ -134,11 +129,6 @@ flash_readw(uint32_t addr, void *p) ret = *q; if (dev->flags & FLAG_WORD) switch (dev->command) { - case 0x00: - case 0x93: - ret = 0xffff; - break; - case CMD_READ_ARRAY: default: break; diff --git a/src/intel_piix - Cópia.c b/src/intel_piix - Cópia.c deleted file mode 100644 index bc7aa2173..000000000 --- a/src/intel_piix - Cópia.c +++ /dev/null @@ -1,1131 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * Emulation of the Intel PIIX and PIIX3 Xcelerators. - * - * PRD format : - * word 0 - base address - * word 1 - bits 1-15 = byte count, bit 31 = end of transfer - * - * Version: @(#)intel_piix.c 1.0.23 2020/01/24 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "86box.h" -#include "cdrom.h" -#include "cpu.h" -#include "scsi_device.h" -#include "scsi_cdrom.h" -#include "dma.h" -#include "86box_io.h" -#include "device.h" -#include "apm.h" -#include "keyboard.h" -#include "mem.h" -#include "timer.h" -#include "nvr.h" -#include "pci.h" -#include "pic.h" -#include "port_92.h" -#include "hdc.h" -#include "hdc_ide.h" -#include "hdc_ide_sff8038i.h" -#include "zip.h" -#include "machine.h" -#include "piix.h" - - -#define ACPI_TIMER_FREQ 3579545 - - -typedef struct -{ - uint16_t io_base; - int base_channel; -} ddma_t; - - -typedef struct -{ - int type; - uint8_t cur_readout_reg, - readout_regs[256], - regs[256], regs_ide[256], - regs_usb[256], regs_power[256]; - sff8038i_t *bm[2]; - ddma_t ddma[2]; - nvr_t * nvr; - - struct - { - uint16_t io_base; - } usb; - - struct - { - uint16_t io_base; - } power; -} piix_t; - - -#ifdef ENABLE_PIIX_LOG -int piix_do_log = ENABLE_PIIX_LOG; - - -static void -piix_log(const char *fmt, ...) -{ - va_list ap; - - if (piix_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define piix_log(fmt, ...) -#endif - - -static void -piix_bus_master_handlers(piix_t *dev, uint16_t old_base) -{ - uint16_t base; - - base = (dev->regs_ide[0x20] & 0xf0) | (dev->regs_ide[0x21] << 8); - - sff_bus_master_handlers(dev->bm[0], old_base, base, (dev->regs_ide[0x04] & 1)); - sff_bus_master_handlers(dev->bm[1], old_base + 8, base + 8, (dev->regs_ide[0x04] & 1)); -} - - -static uint8_t -kbc_alias_reg_read(uint16_t addr, void *p) -{ - uint8_t ret = inb(0x61); - - return ret; -} - - -static void -kbc_alias_reg_write(uint16_t addr, uint8_t val, void *p) -{ - outb(0x61, val); -} - - -static void -kbc_alias_update_io_mapping(piix_t *dev) -{ - io_removehandler(0x0063, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); - io_removehandler(0x0065, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); - io_removehandler(0x0067, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); - - if (dev->regs[0x4e] & 0x08) { - io_sethandler(0x0063, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); - io_sethandler(0x0065, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); - io_sethandler(0x0067, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); - } -} - - -static uint8_t -ddma_reg_read(uint16_t addr, void *p) -{ - ddma_t *dev = (ddma_t *) p; - uint8_t ret = 0xff; - int rel_ch = (addr & 0x30) >> 4; - int ch = dev->base_channel + rel_ch; - int dmab = (ch >= 4) ? 0xc0 : 0x00; - - switch (addr & 0x0f) { - case 0x00: - ret = dma[ch].ac & 0xff; - break; - case 0x01: - ret = (dma[ch].ac >> 8) & 0xff; - break; - case 0x02: - ret = dma[ch].page; - break; - case 0x04: - ret = dma[ch].cc & 0xff; - break; - case 0x05: - ret = (dma[ch].cc >> 8) & 0xff; - break; - case 0x09: - ret = inb(dmab + 0x08); - break; - } - - return ret; -} - - -static void -ddma_reg_write(uint16_t addr, uint8_t val, void *p) -{ - ddma_t *dev = (ddma_t *) p; - int rel_ch = (addr & 0x30) >> 4; - int ch = dev->base_channel + rel_ch; - int page_regs[4] = { 7, 3, 1, 2 }; - int i, dmab = (ch >= 4) ? 0xc0 : 0x00; - - switch (addr & 0x0f) { - case 0x00: - dma[ch].ab = (dma[ch].ab & 0xffff00) | val; - dma[ch].ac = dma[ch].ab; - break; - case 0x01: - dma[ch].ab = (dma[ch].ab & 0xff00ff) | (val << 8); - dma[ch].ac = dma[ch].ab; - break; - case 0x02: - if (ch >= 4) - outb(0x88 + page_regs[rel_ch], val); - else - outb(0x80 + page_regs[rel_ch], val); - break; - case 0x04: - dma[ch].cb = (dma[ch].cb & 0xffff00) | val; - dma[ch].cc = dma[ch].cb; - break; - case 0x05: - dma[ch].cb = (dma[ch].cb & 0xff00ff) | (val << 8); - dma[ch].cc = dma[ch].cb; - break; - case 0x08: - outb(dmab + 0x08, val); - break; - case 0x09: - outb(dmab + 0x09, val); - break; - case 0x0a: - outb(dmab + 0x0a, val); - break; - case 0x0b: - outb(dmab + 0x0b, val); - break; - case 0x0d: - outb(dmab + 0x0d, val); - break; - case 0x0e: - for (i = 0; i < 4; i++) - outb(dmab + 0x0a, i); - break; - case 0x0f: - outb(dmab + 0x0a, (val << 2) | rel_ch); - break; - } -} - - -static void -ddma_update_io_mapping(piix_t *dev, int n) -{ - int base_reg = 0x92 + (n << 1); - - if (dev->ddma[n].io_base != 0x0000) - io_removehandler(dev->usb.io_base, 0x40, ddma_reg_read, NULL, NULL, ddma_reg_write, NULL, NULL, &dev->ddma[n]); - - dev->ddma[n].io_base = (dev->regs[base_reg] & ~0x3f) | (dev->regs[base_reg + 1] << 8); - - if (dev->ddma[n].io_base != 0x0000) - io_sethandler(dev->ddma[n].io_base, 0x40, ddma_reg_read, NULL, NULL, ddma_reg_write, NULL, NULL, &dev->ddma[n]); -} - - -static uint8_t -usb_reg_read(uint16_t addr, void *p) -{ - uint8_t ret = 0xff; - - switch (addr & 0x1f) { - case 0x10: case 0x11: case 0x12: case 0x13: - /* Port status */ - ret = 0x00; - break; - } - - return ret; -} - - -static void -usb_reg_write(uint16_t addr, uint8_t val, void *p) -{ -} - - -static void -usb_update_io_mapping(piix_t *dev) -{ - if (dev->usb.io_base != 0x0000) - io_removehandler(dev->usb.io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, dev); - - dev->usb.io_base = (dev->regs_usb[0x20] & ~0x1f) | (dev->regs_usb[0x21] << 8); - - if ((dev->regs_usb[PCI_REG_COMMAND] & PCI_COMMAND_IO) && (dev->usb.io_base != 0x0000)) - io_sethandler(dev->usb.io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, dev); -} - - -static uint8_t -power_reg_read(uint16_t addr, void *p) -{ - uint32_t timer; - uint8_t ret = 0xff; - - switch (addr & 0x3f) { - case 0x08: case 0x09: case 0x0a: case 0x0b: - /* ACPI timer */ - timer = (tsc * ACPI_TIMER_FREQ) / machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed; - timer &= 0x00ffffff; - ret = (timer >> (8 * (addr & 3))) & 0xff; - break; - } - - return ret; -} - - -static void -power_reg_write(uint16_t addr, uint8_t val, void *p) -{ -} - - -static void -power_update_io_mapping(piix_t *dev) -{ - if (dev->power.io_base != 0x0000) - io_removehandler(dev->power.io_base, 0x40, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); - - dev->power.io_base = (dev->regs_power[0x41] << 8) | (dev->regs_power[0x40] & 0xc0); - - if ((dev->regs_power[PCI_REG_COMMAND] & PCI_COMMAND_IO) && (dev->regs_power[0x80] & 0x01) && (dev->power.io_base != 0x0000)) - io_sethandler(dev->power.io_base, 0x100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); -} - - -static void -piix_write(int func, int addr, uint8_t val, void *priv) -{ - piix_t *dev = (piix_t *) priv; - int type = dev->type & 0xff; - uint8_t valxor; - uint16_t old_base; - - if ((func > 0) && (dev->type & 0x100)) /* PB640's PIIX has no IDE part. */ - return; - - if ((func > 1) && ((type & 0xff) < 3)) /* PIIX has no USB part. */ - return; - - if ((func > 2) && ((type & 0xff) < 4)) /* PIIX and PIIX3 have no Power Management part. */ - return; - - if (func > 3) - return; - - old_base = (dev->regs_ide[0x20] & 0xf0) | (dev->regs_ide[0x21] << 8); - - pclog("PIIX function %i write: %02X to %02X\n", func, val, addr); - - if (func == 3) { /* Power Management */ - /* Read-only addresses */ - if ((addr < 4) || (addr == 5) || (addr == 6) || ((addr >= 8) && (addr < 0x3c)) || - ((addr >= 0x3c) && (addr < 0x40)) || (addr == 0x53) || - ((addr >= 0x81) && (addr < 0x90)) || ((addr >= 0x94) && (addr < 0xd2)) || - (addr > 0xd6)) - return; - - switch (addr) { - case 0x04: - dev->regs_power[0x04] = val & 0x01; - power_update_io_mapping(dev); - break; - case 0x07: - dev->regs_power[0x07] = val & 0x0e; - break; - - case 0x3c: - dev->regs_power[0x3c] = val; - break; - - case 0x40: - dev->regs_power[0x20] = (val & ~0x3f) | 1; - power_update_io_mapping(dev); - break; - case 0x41: - dev->regs_power[0x21] = val; - power_update_io_mapping(dev); - break; - - case 0x80: - dev->regs_power[0x80] = val & 0x01; - power_update_io_mapping(dev); - break; - - default: - dev->regs_power[addr] = val; - break; - } - } else if (func == 2) { /* USB */ - /* Read-only addresses */ - if ((addr < 4) || (addr == 5) || (addr == 6) || ((addr >= 8) && (addr < 0xd)) || - ((addr >= 0xe) && (addr < 0x20)) || ((addr >= 0x22) && (addr < 0x3c)) || - ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x42) && (addr < 0x44)) || - ((addr >= 0x46) && (addr < 0xc0)) || (addr >= 0xc2)) - return; - - switch (addr) { - case 0x04: - dev->regs_usb[0x04] = val & 0x97; - usb_update_io_mapping(dev); - break; - case 0x07: - dev->regs_usb[0x07] = val & 0x7f; - break; - - case 0x20: - dev->regs_usb[0x20] = (val & ~0x1f) | 1; - usb_update_io_mapping(dev); - break; - case 0x21: - dev->regs_usb[0x21] = val; - usb_update_io_mapping(dev); - break; - - case 0xff: - if (type >= 4) { - dev->regs_usb[addr] = val & 0x10; - nvr_at_handler(0, 0x0070, dev->nvr); - if ((dev->regs[0xcb] & 0x01) && (dev->regs_usb[0xff] & 0x10)) - nvr_at_handler(1, 0x0070, dev->nvr); - } - break; - - default: - dev->regs_usb[addr] = val; - break; - } - } else if (func == 1) { /* IDE */ - piix_log("PIIX IDE write: %02X %02X\n", addr, val); - valxor = val ^ dev->regs_ide[addr]; - - switch (addr) { - case 0x04: - pclog("04 write: %02X\n", val); - dev->regs_ide[0x04] = (val & 5); - if (valxor & 0x01) { - ide_pri_disable(); - ide_sec_disable(); - if (val & 0x01) { - // pclog("04: I/O enabled\n"); - if (dev->regs_ide[0x41] & 0x80) { - // pclog("04: PRI enabled\n"); - ide_pri_enable(); - } - if (dev->regs_ide[0x43] & 0x80) { - // pclog("04: SEC enabled\n"); - ide_sec_enable(); - } - } else - // pclog("04: I/O disabled\n"); - - piix_bus_master_handlers(dev, old_base); - } - break; - case 0x07: - dev->regs_ide[0x07] = (dev->regs_ide[0x07] & 0xf9) | (val & 0x06); - if (val & 0x20) - dev->regs_ide[0x07] &= 0xdf; - if (val & 0x10) - dev->regs_ide[0x07] &= 0xef; - if (val & 0x08) - dev->regs_ide[0x07] &= 0xf7; - if (val & 0x04) - dev->regs_ide[0x07] &= 0xfb; - break; - case 0x0d: - dev->regs_ide[0x0d] = val & 0xf0; - break; - - case 0x20: - dev->regs_ide[0x20] = (val & 0xf0) | 1; - if (valxor) - piix_bus_master_handlers(dev, old_base); - break; - case 0x21: - dev->regs_ide[0x21] = val; - if (valxor) - piix_bus_master_handlers(dev, old_base); - break; - - case 0x40: - dev->regs_ide[0x40] = val; - break; - case 0x41: - dev->regs_ide[0x41] = val & ((type >= 3) ? 0xf3 : 0xb3); - if (valxor & 0x80) { - ide_pri_disable(); - if ((val & 0x80) && (dev->regs_ide[0x04] & 0x01)) - ide_pri_enable(); - } - break; - case 0x42: - dev->regs_ide[0x42] = val; - break; - case 0x43: - dev->regs_ide[0x43] = val & ((type >= 3) ? 0xf3 : 0xb3); - if (valxor & 0x80) { - ide_sec_disable(); - if ((val & 0x80) && (dev->regs_ide[0x04] & 0x01)) - ide_sec_enable(); - } - break; - case 0x44: - if (type >= 3) dev->regs_ide[0x44] = val; - break; - case 0x48: - case 0x4a: case 0x4b: - if (type >= 4) dev->regs_ide[addr] = val; - break; - } - } else { - piix_log("PIIX writing value %02X to register %02X\n", val, addr); - valxor = val ^ dev->regs[addr]; - - if ((addr >= 0x0f) && (addr < 0x4c)) - return; - - if ((addr >= 0xa0) && (addr < 0xb0) && (type == 4)) - return; - - switch (addr) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0e: - return; - - case 0x07: - dev->regs[0x07] = (dev->regs[0x07] & 0xf9) | (val & 0x06); - if ((val & 0x40) && (type >= 3)) - dev->regs[0x07] &= 0xbf; - if (val & 0x20) - dev->regs[0x07] &= 0xdf; - if (val & 0x10) - dev->regs[0x07] &= 0xef; - if (val & 0x08) - dev->regs[0x07] &= 0xf7; - if (val & 0x04) - dev->regs[0x07] &= 0xfb; - return; - break; - case 0x4c: - if (valxor) { - if (type >= 3) - dma_alias_remove(); - else - dma_alias_remove_piix(); - if (!(val & 0x80)) - dma_alias_set(); - } - break; - case 0x4e: - keyboard_at_set_mouse_scan((val & 0x10) ? 1 : 0); - if (type >= 4) - kbc_alias_update_io_mapping(dev); - break; - case 0x60: - piix_log("Set IRQ routing: INT A -> %02X\n", val); - if (val & 0x80) - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTA, val & 0xf); - break; - case 0x61: - piix_log("Set IRQ routing: INT B -> %02X\n", val); - if (val & 0x80) - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTB, val & 0xf); - break; - case 0x62: - piix_log("Set IRQ routing: INT C -> %02X\n", val); - if (val & 0x80) - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTC, val & 0xf); - break; - case 0x63: - piix_log("Set IRQ routing: INT D -> %02X\n", val); - if (val & 0x80) - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTD, val & 0xf); - break; - case 0x6a: - if (dev->type == 3) - dev->regs[addr] = (val & 0xFD) | (dev->regs[addr] | 2); - else - dev->regs[addr] = (val & 0xFC) | (dev->regs[addr] | 3); - return; - case 0x70: - piix_log("Set MIRQ routing: MIRQ0 -> %02X\n", val); - if (type < 4) { - if (val & 0x80) - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); - else - pci_set_mirq_routing(PCI_MIRQ0, val & 0xf); - } - break; - piix_log("MIRQ0 is %s\n", (val & 0x20) ? "disabled" : "enabled"); - case 0x71: - if (type < 3) { - piix_log("Set MIRQ routing: MIRQ1 -> %02X\n", val); - if (val & 0x80) - pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); - else - pci_set_mirq_routing(PCI_MIRQ1, val & 0xf); - } - break; - case 0x92: case 0x93: case 0x94: case 0x95: - if (type == 4) - ddma_update_io_mapping(dev, (addr >> 2) & 1); - break; - case 0xcb: - if (type == 4) { - nvr_at_handler(0, 0x0070, dev->nvr); - nvr_at_handler(0, 0x0072, dev->nvr); - - if ((val & 0x01) && (dev->regs_usb[0xff] & 0x10)) - nvr_at_handler(1, 0x0070, dev->nvr); - if (val & 0x04) - nvr_at_handler(1, 0x0072, dev->nvr); - - nvr_wp_set(!!(val & 0x08), 0, dev->nvr); - nvr_wp_set(!!(val & 0x10), 1, dev->nvr); - } - break; - } - - dev->regs[addr] = val; - } -} - - -static uint8_t -piix_read(int func, int addr, void *priv) -{ - piix_t *dev = (piix_t *) priv; - int type = dev->type & 0xff; - int ret = 0xff, ignore = 0; - - if ((func > 0) && (dev->type & 0x100)) /* PB640's PIIX has no IDE part. */ - ignore = 1; - - if ((func > 1) && ((type & 0xff) < 3)) /* PIIX has no USB part. */ - ignore = 1; - - if ((func > 2) && ((type & 0xff) < 4)) /* PIIX and PIIX3 have no Power Management part. */ - ignore = 1; - - if (func > 3) - ignore = 1; - - if (!ignore) { - ret = 0x00; - - if (func == 3) /* Power Management */ - ret = dev->regs_power[addr]; - else if (func == 2) /* USB */ - ret = dev->regs_usb[addr]; - else if (func == 1) switch (addr) { /* IDE */ - case 0x05: case 0x22: case 0x23: - ret = 0x00; - break; - case 0x06: - ret = 0x80; - break; - default: - ret = dev->regs_ide[addr]; - break; - } else if (func == 0) switch (addr) { - case 0x04: - ret = (dev->regs[addr] & 0x80) | ((dev->type & 0x100) ? 0x0f : 0x07); - break; - case 0x05: - if (type >= 3) - ret = dev->regs[addr] & 1; - else - ret = 0; - break; - case 0x06: - ret = dev->regs[addr] & 0x80; - break; - case 0x07: - if (type >= 3) - ret = dev->regs[addr]; - else { - if (dev->type & 0x100) - ret = dev->regs[addr] & 0x02; - else - ret = dev->regs[addr] & 0x3E; - } - break; - caer 0x4e: - ret = (dev->regs[addr] & 0xef) | keyboard_at_get_mouse_scan(); - case 0x60: case 0x61: case 0x62: cae 0x63: - ret = dev->regs[addr] & 0x8f; - break; - case 0x69: - ret = dev->regs[addr] & 0xfe; - break; - case 0x6a: - if (dev->type == 3) - ret = dev->regs[addr] & 0xD1; - else - ret = dev->regs[addr] & 0x07; - break; - case 0x6b: - if (dev->type == 3) - ret = dev->regs[addr] & 0x80; - else - ret = 0x00; - break; - case 0x70: - if (type < 4) - ret = dev->regs[addr] & ((type >= 3) ? 0xef : 0xcf); - else - ret = 0x00; - break; - case 0x71: - if (type < 3) - ret = dev->regs[addr] & 0xcf; - else - ret = 0x00; - break; - case 0x76: case 0x77: - if (dev->type == 3) - ret = dev->regs[addr] & 0x87; - else - ret = dev->regs[addr] & 0x8F; - break; - case 0x80: - if (dev->type == 3) - ret = dev->regs[addr] & 0x7f; - else if (dev->type == 1) - ret = 0x00; - break; - case 0x82: - if (dev->type == 3) - ret = dev->regs[addr] & 0x0f; - else - ret = 0x00; - break; - case 0xa0: - ret = dev->regs[addr] & 0x1f; - break; - case 0xa3: - if (dev->type == 3) - ret = dev->regs[addr] & 1; - else - ret = 0x00; - break; - case 0xa7: - if (dev->type == 3) - ret = dev->regs[addr]; - else - ret = dev->regs[addr] & 0xef; - break; - case 0xab: - if (dev->type == 3) - ret = dev->regs[addr]; - else - ret = dev->regs[addr] & 0xfe; - break; - default: - ret = dev->regs[addr]; - break; - } - } - - pclog("PIIX function %i read: %02X from %02X\n", func, ret, addr); - - return ret; -} - - -static void -board_write(uint16_t port, uint8_t val, void *priv) -{ - piix_t *dev = (piix_t *) priv; - - // pclog("board write %02X at %04X\n", val, port); - - if (port == 0x00e0) - dev->cur_readout_reg = val; - else if (port == 0x00e1) - dev->readout_regs[dev->cur_readout_reg] = val; -} - - -static uint8_t -board_read(uint16_t port, void *priv) -{ - piix_t *dev = (piix_t *) priv; - uint8_t ret = 0xff; - - if (port == 0x00e0) - ret = dev->cur_readout_reg; - else if (port == 0x00e1) - ret = dev->readout_regs[dev->cur_readout_reg]; - - // pclog("board read %02X at %04X\n", ret, port); - - return ret; -} - - -static void -piix_reset_hard(void *priv) -{ - piix_t *piix = (piix_t *) priv; - int type = (piix->type & 0xff); - - uint16_t old_base = (piix->regs_ide[0x20] & 0xf0) | (piix->regs_ide[0x21] << 8); - - if (!(piix->type & 0x100)) { /* PB640's PIIX has no IDE part. */ - sff_bus_master_reset(piix->bm[0], old_base); - sff_bus_master_reset(piix->bm[1], old_base + 8); - - if (type == 4) { - sff_set_irq_mode(piix->bm[0], 0); - sff_set_irq_mode(piix->bm[1], 0); - } - - pclog("piix_reset_hard()\n"); - ide_pri_disable(); - ide_sec_disable(); - } - - if (type == 4) { - nvr_at_handler(0, 0x0072, piix->nvr); - nvr_wp_set(0, 0, piix->nvr); - nvr_wp_set(0, 1, piix->nvr); - } - - memset(piix->regs, 0, 256); - memset(piix->regs_ide, 0, 256); - memset(piix->regs_usb, 0, 256); - memset(piix->regs_power, 0, 256); - - piix->regs[0x00] = 0x86; piix->regs[0x01] = 0x80; /*Intel*/ - if (type == 4) { - piix->regs[0x02] = 0x10; piix->regs[0x03] = 0x71; /*82371AB (PIIX4)*/ - } else if (type == 3) { - piix->regs[0x02] = 0x00; piix->regs[0x03] = 0x70; /*82371SB (PIIX3)*/ - } else { - piix->regs[0x02] = 0x2e; piix->regs[0x03] = 0x12; /*82371FB (PIIX)*/ - } - if (piix->type & 0x100) - piix->regs[0x04] = 0x06; - else - piix->regs[0x04] = 0x07; - piix->regs[0x05] = 0x00; - piix->regs[0x06] = 0x80; piix->regs[0x07] = 0x02; - if (piix->type & 0x100) - piix->regs[0x08] = 0x02; /*A0 stepping*/ - else - piix->regs[0x08] = 0x00; /*A0 stepping*/ - piix->regs[0x09] = 0x00; piix->regs[0x0a] = 0x01; piix->regs[0x0b] = 0x06; - if (piix->type & 0x100) - piix->regs[0x0e] = 0x00; /*Single-function device*/ - else - piix->regs[0x0e] = 0x80; /*Multi-function device*/ - piix->regs[0x4c] = 0x4d; - piix->regs[0x4e] = 0x03; - if (type >= 3) - piix->regs[0x4f] = 0x00; - piix->regs[0x60] = piix->regs[0x61] = piix->regs[0x62] = piix->regs[0x63] = 0x80; - if (type == 4) - piix->regs[0x64] = 0x10; - piix->regs[0x69] = 0x02; - if (type < 4) - piix->regs[0x70] = 0xc0; - if (type < 3) - piix->regs[0x71] = 0xc0; - piix->regs[0x76] = piix->regs[0x77] = 0x0c; - piix->regs[0x78] = 0x02; piix->regs[0x79] = 0x00; - if (type == 3) { - piix->regs[0x80] = piix->regs[0x82] = 0x00; - } - piix->regs[0xa0] = 0x08; - piix->regs[0xa2] = piix->regs[0xa3] = 0x00; - piix->regs[0xa4] = piix->regs[0xa5] = piix->regs[0xa6] = piix->regs[0xa7] = 0x00; - piix->regs[0xa8] = 0x0f; - piix->regs[0xaa] = piix->regs[0xab] = 0x00; - piix->regs[0xac] = 0x00; - piix->regs[0xae] = 0x00; - if (type == 4) - piix->regs[0xcb] = 0x21; - - piix->regs_ide[0x00] = 0x86; piix->regs_ide[0x01] = 0x80; /*Intel*/ - if (type == 4) { - piix->regs_ide[0x02] = 0x11; piix->regs_ide[0x03] = 0x71; /*82371AB (PIIX4)*/ - } else if (type == 3) { - piix->regs_ide[0x02] = 0x10; piix->regs_ide[0x03] = 0x70; /*82371SB (PIIX3)*/ - } else { - piix->regs_ide[0x02] = 0x30; piix->regs_ide[0x03] = 0x12; /*82371FB (PIIX)*/ - } - piix->regs_ide[0x04] = 0x00; piix->regs_ide[0x05] = 0x00; - piix->regs_ide[0x06] = 0x80; piix->regs_ide[0x07] = 0x02; - piix->regs_ide[0x08] = 0x00; - piix->regs_ide[0x09] = 0x80; piix->regs_ide[0x0a] = 0x01; piix->regs_ide[0x0b] = 0x01; - piix->regs_ide[0x0d] = 0x00; - piix->regs_ide[0x0e] = 0x00; - piix->regs_ide[0x20] = 0x01; piix->regs_ide[0x21] = piix->regs_ide[0x22] = piix->regs_ide[0x23] = 0x00; /*Bus master interface base address*/ - piix->regs_ide[0x40] = piix->regs_ide[0x42] = 0x00; - piix->regs_ide[0x41] = piix->regs_ide[0x43] = 0x00; - if (type >= 3) - piix->regs_ide[0x44] = 0x00; - if (type == 4) { - piix->regs_ide[0x48] = piix->regs_ide[0x4a] = - piix->regs_ide[0x4b] = 0x00; - } - - if (type >= 3) { - piix->regs_usb[0x00] = 0x86; piix->regs_usb[0x01] = 0x80; /*Intel*/ - if (type == 4) { - piix->regs_usb[0x02] = 0x12; piix->regs_usb[0x03] = 0x71; /*82371AB (PIIX4)*/ - } else { - piix->regs_usb[0x02] = 0x20; piix->regs_usb[0x03] = 0x70; /*82371SB (PIIX3)*/ - } - piix->regs_usb[0x04] = 0x00; piix->regs_usb[0x05] = 0x00; - piix->regs_usb[0x06] = 0x00; piix->regs_usb[0x07] = 0x02; - piix->regs_usb[0x0a] = 0x03; - piix->regs_usb[0x0b] = 0x0c; - piix->regs_usb[0x0d] = 0x16; - piix->regs_usb[0x20] = 0x01; - piix->regs_usb[0x21] = 0x03; - piix->regs_usb[0x3d] = 0x04; - - piix->regs_usb[0x60] = 0x10; - piix->regs_usb[0xc1] = 0x20; - } - - if (type == 4) { - piix->regs_power[0x00] = 0x86; piix->regs_power[0x01] = 0x80; /*Intel*/ - piix->regs_power[0x02] = 0x13; piix->regs_power[0x03] = 0x71; /*82371AB (PIIX4)*/ - piix->regs_power[0x04] = 0x00; piix->regs_power[0x05] = 0x00; - piix->regs_power[0x06] = 0x80; piix->regs_power[0x07] = 0x02; - piix->regs_power[0x08] = 0x00; /*Initial Stepping=00h*/ - piix->regs_power[0x0a] = 0x80; - piix->regs_power[0x0b] = 0x06; - piix->regs_power[0x3d] = 0x01; - piix->regs_power[0x40] = 0x01; - piix->regs_power[0x90] = 0x01; - } - - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - - if (type < 4) - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); - if (type < 3) - pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); -} - - -static void -piix_close(void *p) -{ - piix_t *piix = (piix_t *)p; - - free(piix); -} - - -static void -*piix_init(const device_t *info) -{ - piix_t *piix = (piix_t *) malloc(sizeof(piix_t)); - int type; - memset(piix, 0, sizeof(piix_t)); - - pci_add_card(7, piix_read, piix_write, piix); - - piix->type = info->local; - type = (piix->type & 0xff); - - device_add(&apm_device); - - if (!(piix->type & 0x100)) { /* PB640's PIIX has no IDE part. */ - piix->bm[0] = device_add_inst(&sff8038i_device, 1); - piix->bm[1] = device_add_inst(&sff8038i_device, 2); - } - - if (type == 4) - piix->nvr = device_add(&piix4_nvr_device); - - piix_reset_hard(piix); - - device_add(&port_92_pci_device); - - dma_alias_set(); - - if (type < 4) - pci_enable_mirq(0); - if (type < 3) - pci_enable_mirq(1); - - piix->readout_regs[1] = 0x40; - - /* Port E1 register 01 (TODO: Find how multipliers > 3.0 are defined): - - Bit 6: 1 = can boot, 0 = no; - Bit 7, 1 = multiplier (00 = 2.5, 01 = 2.0, 10 = 3.0, 11 = 1.5); - Bit 5, 4 = bus speed (00 = 50 MHz, 01 = 66 MHz, 10 = 60 MHz, 11 = ????): - Bit 7, 5, 4, 1: 0000 = 125 MHz, 0010 = 166 MHz, 0100 = 150 MHz, 0110 = ??? MHz; - 0001 = 100 MHz, 0011 = 133 MHz, 0101 = 120 MHz, 0111 = ??? MHz; - 1000 = 150 MHz, 1010 = 200 MHz, 1100 = 180 MHz, 1110 = ??? MHz; - 1001 = 75 MHz, 1011 = 100 MHz, 1101 = 90 MHz, 1111 = ??? MHz */ - - switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].pci_speed) { - case 20000000: - piix->readout_regs[1] |= 0x30; - break; - case 25000000: - default: - piix->readout_regs[1] |= 0x00; - break; - case 30000000: - piix->readout_regs[1] |= 0x20; - break; - case 33333333: - piix->readout_regs[1] |= 0x10; - break; - } - - switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed) { - case 75000000: - piix->readout_regs[1] |= 0x82; /* 50 MHz * 1.5 multiplier */ - break; - case 90000000: - piix->readout_regs[1] |= 0x82; /* 60 MHz * 1.5 multiplier */ - break; - case 100000000: - if ((piix->readout_regs[1] & 0x30) == 0x10) - piix->readout_regs[1] |= 0x82; /* 66 MHz * 1.5 multiplier */ - else - piix->readout_regs[1] |= 0x02; /* 50 MHz * 2.0 multiplier */ - break; - case 12000000: - piix->readout_regs[1] |= 0x02; /* 60 MHz * 2.0 multiplier */ - break; - case 125000000: - piix->readout_regs[1] |= 0x00; /* 50 MHz * 2.5 multiplier */ - break; - case 133333333: - piix->readout_regs[1] |= 0x02; /* 66 MHz * 2.0 multiplier */ - break; - case 150000000: - if ((piix->readout_regs[1] & 0x30) == 0x20) - piix->readout_regs[1] |= 0x00; /* 60 MHz * 2.5 multiplier */ - else - piix->readout_regs[1] |= 0x80; /* 50 MHz * 3.0 multiplier */ - break; - case 166666666: - piix->readout_regs[1] |= 0x00; /* 66 MHz * 2.5 multiplier */ - break; - case 180000000: - piix->readout_regs[1] |= 0x80; /* 60 MHz * 3.0 multiplier */ - break; - case 200000000: - piix->readout_regs[1] |= 0x80; /* 66 MHz * 3.0 multiplier */ - break; - } - - io_sethandler(0x0078, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, piix); - io_sethandler(0x00e0, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, piix); - - return piix; -} - - -const device_t piix_device = -{ - "Intel 82371FB (PIIX)", - DEVICE_PCI, - 1, - piix_init, - piix_close, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -const device_t piix_pb640_device = -{ - "Intel 82371FB (PIIX) (PB640)", - DEVICE_PCI, - 0x101, - piix_init, - piix_close, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -const device_t piix3_device = -{ - "Intel 82371SB (PIIX3)", - DEVICE_PCI, - 3, - piix_init, - piix_close, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -const device_t piix4_device = -{ - "Intel 82371AB (PIIX4)", - DEVICE_PCI, - 4, - piix_init, - piix_close, - NULL, - NULL, - NULL, - NULL, - NULL -}; From 5bd2120151f587b6384cd479f131a02ade0f7e91 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 23 Mar 2020 02:59:50 +0100 Subject: [PATCH 14/14] Merged my PIIX changes (except for the SMBUS port from Bochs which has been superseded by RichardG's implementation). --- src/intel_piix.c | 135 +++++++++++++++++++++++------------------------ 1 file changed, 66 insertions(+), 69 deletions(-) diff --git a/src/intel_piix.c b/src/intel_piix.c index 5bc14302f..96ecb5c80 100644 --- a/src/intel_piix.c +++ b/src/intel_piix.c @@ -142,12 +142,18 @@ void do_irq(piix_t *dev, int func, int level) return; if (level) { - // pci_set_irq(dev->pci_slot, dev->regs[func][0x3d]); +#ifdef WRONG_SPEC + pci_set_irq(dev->pci_slot, dev->regs[func][0x3d]); +#else picintlevel(1 << 9); +#endif piix_log("Raising IRQ...\n"); } else { - // pci_clear_irq(dev->pci_slot, dev->regs[func][0x3d]); +#ifdef WRONG_SPEC + pci_clear_irq(dev->pci_slot, dev->regs[func][0x3d]); +#else picintc(1 << 9); +#endif piix_log("Lowering IRQ...\n"); } } @@ -369,7 +375,7 @@ power_reg_readl(uint16_t addr, void *p) break; } - // pclog("ACPI: Read L %08X from %04X\n", ret, addr); + piix_log("ACPI: Read L %08X from %04X\n", ret, addr); return ret; } @@ -394,7 +400,7 @@ power_reg_readw(uint16_t addr, void *p) break; } - // pclog("ACPI: Read W %08X from %04X\n", ret, addr); + piix_log("ACPI: Read W %08X from %04X\n", ret, addr); return ret; } @@ -411,11 +417,11 @@ power_reg_read(uint16_t addr, void *p) switch (addr & 0x3f) { case 0x30: case 0x31: case 0x32: ret = dev->power.gporeg[addr & 0x03]; - // pclog("ACPI: Read B %02X from GPIREG %01X\n", ret, addr & 0x03); + piix_log("ACPI: Read B %02X from GPIREG %01X\n", ret, addr & 0x03); break; case 0x34: case 0x35: case 0x36: case 0x37: ret = dev->power.gporeg[addr & 0x03]; - // pclog("ACPI: Read B %02X from GPOREG %01X\n", ret, addr & 0x03); + piix_log("ACPI: Read B %02X from GPOREG %01X\n", ret, addr & 0x03); break; default: ret16 = power_reg_readw(addr, p); @@ -435,7 +441,7 @@ power_reg_write(uint16_t addr, uint8_t val, void *p) { piix_t *dev = (piix_t *) p; - // pclog("ACPI: Write %02X to %04X\n", val, addr); + piix_log("ACPI: Write %02X to %04X\n", val, addr); switch (addr & 0x3f) { case 0x34: case 0x35: case 0x36: case 0x37: @@ -491,7 +497,7 @@ smbus_reg_read(uint16_t addr, void *priv) break; } - // pclog("smbus_reg_read %02x %02x\n", addr - dev->smbus_io_base, ret); + piix_log("smbus_reg_read %02x %02x\n", addr - dev->smbus_io_base, ret); return ret; } @@ -505,7 +511,7 @@ smbus_reg_write(uint16_t addr, uint8_t val, void *priv) uint8_t smbus_read; uint16_t temp; - // pclog("smbus_reg_write %02x %02x\n", addr - dev->smbus_io_base, val); + piix_log("smbus_reg_write %02x %02x\n", addr - dev->smbus_io_base, val); dev->smbus.next_stat = 0; switch (addr - dev->smbus_io_base) { @@ -624,7 +630,7 @@ piix_write(int func, int addr, uint8_t val, void *priv) if (func > dev->max_func) return; - // pclog("PIIX function %i write: %02X to %02X\n", func, val, addr); + piix_log("PIIX function %i write: %02X to %02X\n", func, val, addr); fregs = (uint8_t *) dev->regs[func]; if (func == 0) switch (addr) { @@ -847,6 +853,10 @@ piix_write(int func, int addr, uint8_t val, void *priv) fregs[0x21] = val; piix_ide_bm_handlers(dev); break; + case 0x3c: + piix_log("IDE IRQ write: %02X\n", val); + fregs[0x3c] = val; + break; case 0x40: case 0x42: fregs[addr] = val; break; @@ -1014,7 +1024,7 @@ piix_read(int func, int addr, void *priv) fregs = (uint8_t *) dev->regs[func]; ret = fregs[addr]; - // pclog("PIIX function %i read: %02X from %02X\n", func, ret, addr); + piix_log("PIIX function %i read: %02X from %02X\n", func, ret, addr); } return ret; @@ -1074,7 +1084,9 @@ piix_reset_hard(piix_t *dev) sff_set_irq_mode(dev->bm[1], 0); } - // pclog("piix_reset_hard()\n"); +#ifdef ENABLE_PIIX_LOG + piix_log("piix_reset_hard()\n"); +#endif ide_pri_disable(); ide_sec_disable(); } @@ -1097,7 +1109,7 @@ piix_reset_hard(piix_t *dev) /* Function 0: PCI to ISA Bridge */ fregs = (uint8_t *) dev->regs[0]; - // pclog("PIIX Function 0: 8086:%02X%02X\n", fregs[0x03], fregs[0x02]); + piix_log("PIIX Function 0: 8086:%02X%02X\n", fregs[0x03], fregs[0x02]); fregs[0x04] = (dev->type > 0) ? 0x07 : 0x06; /* Check the value for the PB640 PIIX. */ fregs[0x06] = 0x80; fregs[0x07] = 0x02; fregs[0x08] = (dev->type > 0) ? 0x00 : 0x02; /* Should normal PIIX alos return 0x02? */ @@ -1123,7 +1135,7 @@ piix_reset_hard(piix_t *dev) /* Function 1: IDE */ if (dev->type > 0) { fregs = (uint8_t *) dev->regs[1]; - // pclog("PIIX Function 1: 8086:%02X%02X\n", fregs[0x03], fregs[0x02]); + piix_log("PIIX Function 1: 8086:%02X%02X\n", fregs[0x03], fregs[0x02]); fregs[0x04] = (dev->type > 3) ? 0x05 : 0x07; fregs[0x06] = 0x80; fregs[0x07] = 0x02; fregs[0x09] = 0x80; @@ -1135,7 +1147,7 @@ piix_reset_hard(piix_t *dev) /* Function 2: USB */ if (dev->type > 2) { fregs = (uint8_t *) dev->regs[2]; - // pclog("PIIX Function 2: 8086:%02X%02X\n", fregs[0x03], fregs[0x02]); + piix_log("PIIX Function 2: 8086:%02X%02X\n", fregs[0x03], fregs[0x02]); fregs[0x04] = 0x05; fregs[0x06] = 0x80; fregs[0x07] = 0x02; fregs[0x0a] = 0x03; fregs[0x0b] = 0x0c; @@ -1151,11 +1163,13 @@ piix_reset_hard(piix_t *dev) /* Function 3: Power Management */ if (dev->type > 3) { fregs = (uint8_t *) dev->regs[3]; - // pclog("PIIX Function 3: 8086:%02X%02X\n", fregs[0x03], fregs[0x02]); + piix_log("PIIX Function 3: 8086:%02X%02X\n", fregs[0x03], fregs[0x02]); fregs[0x06] = 0x80; fregs[0x07] = 0x02; fregs[0x0a] = 0x80; fregs[0x0b] = 0x06; /* NOTE: The Specification Update says this should default to 0x00 and be read-only. */ - // fregs[0x3d] = 0x01; +#ifdef WRONG_SPEC + fregs[0x3d] = 0x01; +#endif fregs[0x40] = 0x01; fregs[0x90] = 0x01; dev->max_func = 3; @@ -1171,12 +1185,14 @@ piix_reset_hard(piix_t *dev) if (dev->type < 3) pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); +#ifdef WRONG_SPEC if (dev->type == 4) { dev->power.gporeg[0] = 0xff; dev->power.gporeg[1] = 0xbf; dev->power.gporeg[2] = 0xff; dev->power.gporeg[3] = 0x7f; } +#endif } @@ -1192,6 +1208,8 @@ piix_close(void *p) static void *piix_init(const device_t *info) { + int i; + piix_t *dev = (piix_t *) malloc(sizeof(piix_t)); memset(dev, 0, sizeof(piix_t)); @@ -1200,7 +1218,7 @@ static void dev->func0_id = info->local >> 16; dev->pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, piix_read, piix_write, dev); - // pclog("PIIX%i: Added to slot: %02X\n", dev->type, dev->pci_slot); + piix_log("PIIX%i: Added to slot: %02X\n", dev->type, dev->pci_slot); if (dev->type > 0) { /* PB640's PIIX has no IDE part. */ dev->bm[0] = device_add_inst(&sff8038i_device, 1); @@ -1243,65 +1261,45 @@ static void else if (cpu_busspeed > 0x60000000) dev->readout_regs[1] |= 0x10; -#if 0 - switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed) { - case 75000000: - dev->readout_regs[1] |= 0x82; /* 50 MHz * 1.5 multiplier */ - break; - case 90000000: - dev->readout_regs[1] |= 0x82; /* 60 MHz * 1.5 multiplier */ - break; - case 100000000: - if ((dev->readout_regs[1] & 0x30) == 0x10) - dev->readout_regs[1] |= 0x82; /* 66 MHz * 1.5 multiplier */ - else - dev->readout_regs[1] |= 0x02; /* 50 MHz * 2.0 multiplier */ - break; - case 12000000: - dev->readout_regs[1] |= 0x02; /* 60 MHz * 2.0 multiplier */ - break; - case 125000000: - dev->readout_regs[1] |= 0x00; /* 50 MHz * 2.5 multiplier */ - break; - case 133333333: - dev->readout_regs[1] |= 0x02; /* 66 MHz * 2.0 multiplier */ - break; - case 150000000: - if ((dev->readout_regs[1] & 0x30) == 0x20) - dev->readout_regs[1] |= 0x00; /* 60 MHz * 2.5 multiplier */ - else - dev->readout_regs[1] |= 0x80; /* 50 MHz * 3.0 multiplier */ - break; - case 166666666: - dev->readout_regs[1] |= 0x00; /* 66 MHz * 2.5 multiplier */ - break; - case 180000000: - dev->readout_regs[1] |= 0x80; /* 60 MHz * 3.0 multiplier */ - break; - case 200000000: - dev->readout_regs[1] |= 0x80; /* 66 MHz * 3.0 multiplier */ - break; - } -#else - if (cpu_dmulti <= 1.5) - dev->readout_regs[1] |= 0x82; - else if ((cpu_dmulti > 1.5) && (cpu_dmulti <= 2.0)) - dev->readout_regs[1] |= 0x02; - else if ((cpu_dmulti > 2.0) && (cpu_dmulti <= 2.5)) - dev->readout_regs[1] |= 0x00; - else if (cpu_dmulti > 2.5) - dev->readout_regs[1] |= 0x80; -#endif + if (cpu_dmulti <= 1.5) + dev->readout_regs[1] |= 0x82; + else if ((cpu_dmulti > 1.5) && (cpu_dmulti <= 2.0)) + dev->readout_regs[1] |= 0x02; + else if ((cpu_dmulti > 2.0) && (cpu_dmulti <= 2.5)) + dev->readout_regs[1] |= 0x00; + else if (cpu_dmulti > 2.5) + dev->readout_regs[1] |= 0x80; io_sethandler(0x0078, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); io_sethandler(0x00e0, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); dev->board_config[0] = 0xff; /* Register 0x0079: */ + /* Bit 7: 0 = Keep password, 0 = Clear password. */ /* Bit 6: 0 = NVRAM cleared by jumper, 1 = NVRAM normal. */ /* Bit 5: 0 = CMOS Setup disabled, 1 = CMOS Setup enabled. */ + /* Bit 4: External CPU clock (Switch 8). */ + /* Bit 3: External CPU clock (Switch 7). */ + /* 50 MHz: Switch 7 = Off, Switch 8 = Off. */ + /* 60 MHz: Switch 7 = On, Switch 8 = Off. */ + /* 66 MHz: Switch 7 = Off, Switch 8 = On. */ /* Bit 2: 0 = On-board audio absent, 1 = On-board audio present. */ - dev->board_config[1] = 0x64; + /* Bit 0: 0 = 1.5x multiplier, 0 = 2x multiplier. */ + dev->board_config[1] = 0xe0; + if ((cpu_s->rspeed == 75000000) && (cpu_busspeed == 50000000)) + dev->board_config[1] |= 0x01; + else if ((cpu_s->rspeed == 90000000) && (cpu_busspeed == 60000000)) + dev->board_config[1] |= (0x01 | 0x08); + else if ((cpu_s->rspeed == 100000000) && (cpu_busspeed == 50000000)) + dev->board_config[1] |= 0x00; + else if ((cpu_s->rspeed == 100000000) && (cpu_busspeed == 66666666)) + dev->board_config[1] |= (0x01 | 0x10); + else if ((cpu_s->rspeed == 120000000) && (cpu_busspeed == 60000000)) + dev->board_config[1] |= 0x08; + else if ((cpu_s->rspeed == 133333333) && (cpu_busspeed == 66666666)) + dev->board_config[1] |= 0x10; + else + dev->board_config[1] |= 0x10; /* TODO: how are the overdrive processors configured? */ smbus_init(); dev->smbus.stat = 0; @@ -1311,7 +1309,6 @@ static void dev->smbus.data0 = 0; dev->smbus.data1 = 0; dev->smbus.index = 0; - int i; for (i = 0; i < 32; i++) dev->smbus.data[i] = 0; timer_add(&dev->smbus.command_timer, smbus_inter, dev, 0);