diff --git a/src/devices/bus/isa/isa.cpp b/src/devices/bus/isa/isa.cpp index 91907e4a9f8..ac1d7c59651 100644 --- a/src/devices/bus/isa/isa.cpp +++ b/src/devices/bus/isa/isa.cpp @@ -43,10 +43,13 @@ void isa8_slot_device::device_start() { device_isa8_card_interface *dev = dynamic_cast(get_card_device()); const device_isa16_card_interface *intf; + device_t *isadev = m_owner->subdevice(m_isa_tag); if (get_card_device() && get_card_device()->interface(intf)) fatalerror("ISA16 device in ISA8 slot\n"); - if (dev) dev->set_isabus(m_owner->subdevice(m_isa_tag)); + if (dev) dev->set_isabus(isadev); + // tell isa bus that there is one slot with the specified tag + dynamic_cast(isadev)->add_slot(tag()); } @@ -76,7 +79,10 @@ isa16_slot_device::isa16_slot_device(const machine_config &mconfig, const char * void isa16_slot_device::device_start() { device_isa8_card_interface *dev = dynamic_cast(get_card_device()); - if (dev) dev->set_isabus(m_owner->subdevice(m_isa_tag)); + device_t *isadev = m_owner->subdevice(m_isa_tag); + if (dev) dev->set_isabus(isadev); + // tell isa bus that there is one slot with the specified tag + dynamic_cast(isadev)->add_slot(tag()); } @@ -176,6 +182,28 @@ void isa8_device::set_dma_channel(uint8_t channel, device_isa8_card_interface *d m_dma_eop[channel] = do_eop; } +void isa8_device::add_slot(const char *tag) +{ + device_t *dev = subdevice(tag); + //printf(tag); + add_slot(dynamic_cast(dev)); +} + +void isa8_device::add_slot(device_slot_interface *slot) +{ + m_slot_list.push_front(slot); +} + +void isa8_device::remap(int space_id, offs_t start, offs_t end) +{ + for (device_slot_interface *sl : m_slot_list) + { + device_t *dev = sl->get_card_device(); + device_isa8_card_interface *isadev = dynamic_cast(dev); + isadev->remap(space_id, start, end); + } +} + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- @@ -554,6 +582,26 @@ void isa16_device::dack16_w(int line,uint16_t data) return dynamic_cast(m_dma_device[line])->dack16_w(line,data); } +void isa16_device::remap(int space_id, offs_t start, offs_t end) +{ + for (device_slot_interface *sl : m_slot_list) + { + device_t *dev = sl->get_card_device(); + + if (dev) + { + device_isa8_card_interface *isadev8 = dynamic_cast(dev); + device_isa16_card_interface *isadev16 = dynamic_cast(dev); + + if (isadev16) + isadev16->remap(space_id, start, end); + else + if (isadev8) + isadev8->remap(space_id, start, end); + } + } +} + //------------------------------------------------- // device_isa16_card_interface - constructor //------------------------------------------------- diff --git a/src/devices/bus/isa/isa.h b/src/devices/bus/isa/isa.h index a8046423e61..afb94068aec 100644 --- a/src/devices/bus/isa/isa.h +++ b/src/devices/bus/isa/isa.h @@ -67,6 +67,7 @@ #pragma once +#include //************************************************************************** @@ -256,6 +257,10 @@ public: virtual void set_dma_channel(uint8_t channel, device_isa8_card_interface *dev, bool do_eop); + void add_slot(const char *tag); + void add_slot(device_slot_interface *slot); + virtual void remap(int space_id, offs_t start, offs_t end); + const address_space_config m_mem_config, m_io_config, m_mem16_config, m_io16_config; protected: @@ -288,6 +293,7 @@ protected: device_isa8_card_interface *m_dma_device[8]; bool m_dma_eop[8]; bool m_nmi_enabled; + std::forward_list m_slot_list; private: devcb_write_line m_write_iochck; @@ -316,6 +322,8 @@ public: virtual void dack_w(int line,uint8_t data); virtual void eop_w(int state); + virtual void remap(int space_id, offs_t start, offs_t end) {} + // inline configuration void set_isabus(device_t *isa_device) { m_isa_dev = isa_device; } @@ -382,6 +390,7 @@ public: uint16_t dack16_r(int line); void dack16_w(int line,uint16_t data); + virtual void remap(int space_id, offs_t start, offs_t end) override; // 16 bit accessors for ISA-defined address spaces DECLARE_READ16_MEMBER(mem16_r); diff --git a/src/devices/bus/isa/svga_tseng.cpp b/src/devices/bus/isa/svga_tseng.cpp index 73dbcb1af7c..b5b99399fb8 100644 --- a/src/devices/bus/isa/svga_tseng.cpp +++ b/src/devices/bus/isa/svga_tseng.cpp @@ -74,12 +74,8 @@ void isa8_svga_et4k_device::device_start() m_vga = subdevice("vga"); m_isa->install_rom(this, 0xc0000, 0xc7fff, "et4000", "et4000"); - - m_isa->install_device(0x3b0, 0x3bf, read8_delegate(FUNC(tseng_vga_device::port_03b0_r),m_vga), write8_delegate(FUNC(tseng_vga_device::port_03b0_w),m_vga)); - m_isa->install_device(0x3c0, 0x3cf, read8_delegate(FUNC(tseng_vga_device::port_03c0_r),m_vga), write8_delegate(FUNC(tseng_vga_device::port_03c0_w),m_vga)); - m_isa->install_device(0x3d0, 0x3df, read8_delegate(FUNC(tseng_vga_device::port_03d0_r),m_vga), write8_delegate(FUNC(tseng_vga_device::port_03d0_w),m_vga)); - - m_isa->install_memory(0xa0000, 0xbffff, read8_delegate(FUNC(tseng_vga_device::mem_r),m_vga), write8_delegate(FUNC(tseng_vga_device::mem_w),m_vga)); + map_io(); + map_ram(); } //------------------------------------------------- @@ -89,3 +85,26 @@ void isa8_svga_et4k_device::device_start() void isa8_svga_et4k_device::device_reset() { } + +//------------------------------------------------- +// remap - remap ram since something +// could have unmapped it +//------------------------------------------------- + +void isa8_svga_et4k_device::remap(int space_id, offs_t start, offs_t end) +{ + if (space_id == AS_PROGRAM) + map_ram(); +} + +void isa8_svga_et4k_device::map_io() +{ + m_isa->install_device(0x3b0, 0x3bf, read8_delegate(FUNC(tseng_vga_device::port_03b0_r), m_vga), write8_delegate(FUNC(tseng_vga_device::port_03b0_w), m_vga)); + m_isa->install_device(0x3c0, 0x3cf, read8_delegate(FUNC(tseng_vga_device::port_03c0_r), m_vga), write8_delegate(FUNC(tseng_vga_device::port_03c0_w), m_vga)); + m_isa->install_device(0x3d0, 0x3df, read8_delegate(FUNC(tseng_vga_device::port_03d0_r), m_vga), write8_delegate(FUNC(tseng_vga_device::port_03d0_w), m_vga)); +} + +void isa8_svga_et4k_device::map_ram() +{ + m_isa->install_memory(0xa0000, 0xbffff, read8_delegate(FUNC(tseng_vga_device::mem_r), m_vga), write8_delegate(FUNC(tseng_vga_device::mem_w), m_vga)); +} diff --git a/src/devices/bus/isa/svga_tseng.h b/src/devices/bus/isa/svga_tseng.h index 13805bad615..6fe70d06fff 100644 --- a/src/devices/bus/isa/svga_tseng.h +++ b/src/devices/bus/isa/svga_tseng.h @@ -24,6 +24,8 @@ public: DECLARE_READ8_MEMBER(input_port_0_r); + virtual void remap(int space_id, offs_t start, offs_t end) override; + protected: // device-level overrides virtual void device_start() override; @@ -34,6 +36,8 @@ protected: virtual const tiny_rom_entry *device_rom_region() const override; private: + void map_io(); + void map_ram(); tseng_vga_device *m_vga; }; diff --git a/src/devices/bus/lpci/i82371ab.cpp b/src/devices/bus/lpci/i82371ab.cpp index df44ac6c1d1..ef32506481a 100644 --- a/src/devices/bus/lpci/i82371ab.cpp +++ b/src/devices/bus/lpci/i82371ab.cpp @@ -210,6 +210,11 @@ void i82371ab_device::pci_write(pci_bus_device *pcibus, int function, int offset } } +void i82371ab_device::remap(int space_id, offs_t start, offs_t end) +{ + m_isabus->remap(space_id, start, end); +} + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- diff --git a/src/devices/bus/lpci/i82371ab.h b/src/devices/bus/lpci/i82371ab.h index 776ae8d00d5..5080c135145 100644 --- a/src/devices/bus/lpci/i82371ab.h +++ b/src/devices/bus/lpci/i82371ab.h @@ -28,6 +28,8 @@ public: virtual uint32_t pci_read(pci_bus_device *pcibus, int function, int offset, uint32_t mem_mask) override; virtual void pci_write(pci_bus_device *pcibus, int function, int offset, uint32_t data, uint32_t mem_mask) override; + virtual void remap(int space_id, offs_t start, offs_t end) override; + protected: // device-level overrides virtual void device_start() override; diff --git a/src/devices/bus/lpci/i82371sb.cpp b/src/devices/bus/lpci/i82371sb.cpp index e30640440e8..738c725f530 100644 --- a/src/devices/bus/lpci/i82371sb.cpp +++ b/src/devices/bus/lpci/i82371sb.cpp @@ -31,7 +31,13 @@ DEFINE_DEVICE_TYPE(I82371SB, i82371sb_device, "i82371sb", "Intel 82371SB") i82371sb_device::i82371sb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : southbridge_device(mconfig, I82371SB, tag, owner, clock) , pci_device_interface( mconfig, *this ) + , m_smi_callback(*this) , m_boot_state_hook(*this) + , m_csmigate(0) + , m_smien(0) + , m_apmc(0) + , m_apms(0) + , m_base(0) { } @@ -64,6 +70,19 @@ void i82371sb_device::pci_isa_w(device_t *busdevice, int offset, uint32_t data, m_regs[0][offset] |= 0x02800000; break; + + case 0xa0: + COMBINE_DATA(&m_regs[0][offset]); + + m_csmigate = m_regs[0][offset] & 1; + m_smien = (m_regs[0][offset] >> 16) & 511; + update_smireq_line(); + break; + + case 0xa8: + COMBINE_DATA(&m_regs[0][offset]); + update_smireq_line(); + break; } } @@ -90,12 +109,62 @@ void i82371sb_device::pci_ide_w(device_t *busdevice, int offset, uint32_t data, COMBINE_DATA(&m_regs[1][offset]); // clear reserved bits - m_regs[1][offset] &= 0x00000005; + m_regs[1][offset] &= 0x38000007; // set new status - m_regs[1][offset] |= 0x02800000; + m_regs[1][offset] |= 0x02800002; + // if bit 0 is 0 access to ide io ports must not be enabled + if (m_regs[1][offset] & 1) + { + if (m_ide_io_ports_enabled == false) + { + m_ide_io_ports_enabled = true; + map_busmaster_dma(); + } + } + else + { + if (m_ide_io_ports_enabled == true) + { + m_ide_io_ports_enabled = false; + if (m_base != 0) + spaceio->unmap_readwrite(m_base, m_base + 0xf); + } + } break; + + case 0x0c: + COMBINE_DATA(&m_regs[1][offset]); + m_regs[1][offset] &= 0x0000f000; + break; + + + case 0x20: + COMBINE_DATA(&m_regs[1][offset]); + m_regs[1][offset] = (m_regs[1][offset] & 0x0000fff0) | 1; + if (m_ide_io_ports_enabled == true) + if (m_base != 0) + spaceio->unmap_readwrite(m_base, m_base + 0xf); // unmap current + m_base = m_regs[1][offset] & 0x0000fff0; + if (m_ide_io_ports_enabled == true) + map_busmaster_dma(); + break; + + case 0x3c: + case 0x40: + case 0x44: + COMBINE_DATA(&m_regs[1][offset]); + break; + } +} + +void i82371sb_device::map_busmaster_dma() +{ + if (m_base != 0) + { + spaceio->install_readwrite_handler(m_base, m_base + 0x7, read32_delegate(FUNC(bus_master_ide_controller_device::bmdma_r), &(*m_ide)), write32_delegate(FUNC(bus_master_ide_controller_device::bmdma_w), &(*m_ide)), 0xffffffff); + spaceio->install_readwrite_handler(m_base + 0x8, m_base + 0xf, read32_delegate(FUNC(bus_master_ide_controller_device::bmdma_r), &(*m_ide2)), write32_delegate(FUNC(bus_master_ide_controller_device::bmdma_w), &(*m_ide2)), 0xffffffff); } } @@ -128,6 +197,16 @@ void i82371sb_device::pci_usb_w(device_t *busdevice, int offset, uint32_t data, m_regs[2][offset] |= 0x02800000; break; + + case 0x20: + COMBINE_DATA(&m_regs[2][offset]); + m_regs[2][offset] = (m_regs[2][offset] & 0x0000ffe0) | 1; + break; + + case 0x3c: + COMBINE_DATA(&m_regs[2][offset]); + m_regs[2][offset] = (m_regs[2][offset] & 0x000000ff) | 0x400; + break; } } @@ -159,13 +238,23 @@ void i82371sb_device::pci_write(pci_bus_device *pcibus, int function, int offset #endif } +void i82371sb_device::remap(int space_id, offs_t start, offs_t end) +{ + m_isabus->remap(space_id, start, end); +} + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void i82371sb_device::device_start() { + address_space& spaceio = machine().device(":maincpu")->memory().space(AS_IO); + southbridge_device::device_start(); + m_ide_io_ports_enabled = false; + spaceio.install_readwrite_handler(0x00b0, 0x00b3, read8_delegate(FUNC(i82371sb_device::read_apmcapms), this), write8_delegate(FUNC(i82371sb_device::write_apmcapms), this), 0xffff0000); + m_smi_callback.resolve_safe(); m_boot_state_hook.resolve_safe(); // setup save states save_item(NAME(m_regs)); @@ -189,18 +278,56 @@ void i82371sb_device::device_reset() // ide m_regs[1][0x00] = 0x70108086; - m_regs[1][0x04] = 0x02800000; + m_regs[1][0x04] = 0x02800002; m_regs[1][0x08] = 0x01018000; m_regs[1][0x0c] = 0x00000000; + m_regs[1][0x20] = 0x00000001; + m_regs[2][0x3c] = 0x00000100; // usb m_regs[2][0x00] = 0x70208086; m_regs[2][0x04] = 0x02800000; m_regs[2][0x08] = 0x0c030000; m_regs[2][0x0c] = 0x00000000; + m_regs[2][0x3c] = 0x00000400; + m_regs[2][0x60] = 0x00000010; + m_regs[2][0x68] = 0x00010000; + m_regs[2][0xc0] = 0x00002000; } void i82371sb_device::port80_debug_write(uint8_t value) { m_boot_state_hook((offs_t)0, value); } + +READ8_MEMBER(i82371sb_device::read_apmcapms) +{ + if (offset == 0) + return m_apmc; + else + return m_apms; +} + +WRITE8_MEMBER(i82371sb_device::write_apmcapms) +{ + if (offset == 0) + { + m_apmc = data; + if (m_smien & 128) + m_regs[0][0xa8] |= (1 << 7) << 16; + update_smireq_line(); + } + else + m_apms = data; +} + +void i82371sb_device::update_smireq_line() +{ + int smireq = (m_regs[0][0xa8] >> 16) & 511; + int needed = smireq & m_smien; + + if (needed && m_csmigate) + m_smi_callback(1); + else + m_smi_callback(0); +} diff --git a/src/devices/bus/lpci/i82371sb.h b/src/devices/bus/lpci/i82371sb.h index dfb1f5de498..a3904279614 100644 --- a/src/devices/bus/lpci/i82371sb.h +++ b/src/devices/bus/lpci/i82371sb.h @@ -24,11 +24,14 @@ public: // construction/destruction i82371sb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + template devcb_base &set_smi_callback(Object &&cb) { return m_smi_callback.set_callback(std::forward(cb)); } template devcb_base &set_boot_state_hook(Object &&cb) { return m_boot_state_hook.set_callback(std::forward(cb)); } virtual uint32_t pci_read(pci_bus_device *pcibus, int function, int offset, uint32_t mem_mask) override; virtual void pci_write(pci_bus_device *pcibus, int function, int offset, uint32_t data, uint32_t mem_mask) override; + virtual void remap(int space_id, offs_t start, offs_t end) override; + protected: // device-level overrides virtual void device_start() override; @@ -44,13 +47,28 @@ protected: uint32_t pci_usb_r(device_t *busdevice, int offset, uint32_t mem_mask); void pci_usb_w(device_t *busdevice, int offset, uint32_t data, uint32_t mem_mask); private: + DECLARE_READ8_MEMBER(read_apmcapms); + DECLARE_WRITE8_MEMBER(write_apmcapms); + + void map_busmaster_dma(); + void update_smireq_line(); + uint32_t m_regs[3][0x400/4]; + devcb_write_line m_smi_callback; devcb_write8 m_boot_state_hook; + int m_csmigate; + int m_smien; + int m_apmc; + int m_apms; + uint32_t m_base; }; // device type definition DECLARE_DEVICE_TYPE(I82371SB, i82371sb_device) +#define MCFG_I82371SB_SMI_CB(_devcb) \ + devcb = &downcast(*device).set_smi_callback(DEVCB_##_devcb); + #define MCFG_I82371SB_BOOT_STATE_HOOK(_devcb) \ devcb = &downcast(*device).set_boot_state_hook(DEVCB_##_devcb); diff --git a/src/devices/bus/lpci/i82439tx.cpp b/src/devices/bus/lpci/i82439tx.cpp index 5c943036f8b..c6b5c74aefe 100644 --- a/src/devices/bus/lpci/i82439tx.cpp +++ b/src/devices/bus/lpci/i82439tx.cpp @@ -26,6 +26,7 @@ i82439tx_device::i82439tx_device(const machine_config &mconfig, const char *tag, m_space(nullptr), m_rom(nullptr) { + m_smram.smiact_n = 1; } void i82439tx_device::i82439tx_configure_memory(uint8_t val, offs_t begin, offs_t end) @@ -218,13 +219,43 @@ void i82439tx_device::pci_write(pci_bus_device *pcibus, int function, int offset logerror("i82439tx_pci_write(): Unemulated PCI write 0x%02X = 0x%04X\n", offset, data); break; + case 0x70: + if (ACCESSING_BITS_8_15) + { + // ESMRAMC: EXTENDED SYSTEM MANAGEMENT RAM CONTROL REGISTER + data = (data & ~(1 << 14)) | ((m_regs[(offset - 0x50) / 4] & ~data) & (1 << 14)); // e_smerr cleared only by writing 1 + m_smram.tseg_en = (data >> 8) & 1; + m_smram.tseg_sz = (data >> 9) & 3; + m_smram.e_smerr = (data >> 14) & 1; + m_smram.h_smrame = (data >> 15) & 1; + m_smram.tseg_size = 128 * (1 << m_smram.tseg_sz) * 1024; +#ifdef VERBOSE + logerror("i82439tx_pci_write(): ESMRAMC h_smrame %d e_smerr %d tseg_sz %d tseg_en %d\n", m_smram.h_smrame, m_smram.e_smerr, m_smram.tseg_sz, m_smram.tseg_en); +#endif + } + if (ACCESSING_BITS_16_23) + { + // SMRAMC: SYSTEM MANAGEMENT RAM CONTROL REGISTER + data = data | (m_regs[(offset - 0x50) / 4] & (1 << 20)); // d_lck can only be set to 1 + m_smram.c_base_seg = (data >> 16) & 7; + m_smram.g_smrame = (data >> 19) & 1; + m_smram.d_lck = (data >> 20) & 1; + m_smram.d_cls = (data >> 21) & 1; + m_smram.d_open = (data >> 22) & 1; +#ifdef VERBOSE + logerror("i82439tx_pci_write(): SMRAMC d_open %d d_cls %d d_lck %d g_smrame %d c_base_seg %d\n", m_smram.d_open, m_smram.d_cls, m_smram.d_lck, m_smram.g_smrame, m_smram.c_base_seg); +#endif + } + update_smram_mappings(); + COMBINE_DATA(&m_regs[(offset - 0x50) / 4]); + break; + case 0x50: case 0x54: case 0x60: case 0x64: case 0x68: case 0x6C: - case 0x70: case 0x74: case 0x78: case 0x7C: @@ -269,6 +300,140 @@ void i82439tx_device::pci_write(pci_bus_device *pcibus, int function, int offset } } +/* +A is the compatible smram area, the memory area from 0xa0000 to 0xbffff +S is the extended smram area, the memory area from 0x100a0000 to 0x100fffff +T is the TSEG (T segment) smram area, the memory area from 0x10000000+dram_size-tseg_size to 0x10000000+dram_size-1 + where dram_size is the size of the dram memory on the motherboard and tseg_size is the size of TSEG +A and S are mutually exclusive and are stored in the last 384 kilobytes of the first megabyte of dram memory +T is stored in the last tseg_size bytes of the dram memory on the motherboard + +g s h +s m s t +m i m s +r o a r e +a l c p c a g +m c l e t m e +e k s n # e n Code Data +------------- -------------------- -------------------- +0 x x x x x x A-PCI S-PCI T-PCI A-PCI S-PCI T-PCI +1 0 1 1 x x x Invalid Invalid + +1 0 0 0 0 0 0 A-DRAM S-PCI T-PCI A-DRAM S-PCI T-PCI +1 0 0 0 0 0 1 A-DRAM S-PCI T-DRAM A-DRAM S-PCI T-DRAM +1 0 0 0 0 1 0 A-PCI S-DRAM T-PCI A-PCI S-DRAM T-PCI +1 0 0 0 0 1 1 A-PCI S-DRAM T-DRAM A-PCI S-DRAM T-DRAM + +1 0 0 1 0 0 0 A-DRAM S-PCI T-PCI A-DRAM S-PCI T-PCI +1 0 0 1 0 0 1 A-DRAM S-PCI T-DRAM A-DRAM S-PCI T-DRAM +1 0 0 1 0 1 0 A-PCI S-DRAM T-PCI A-PCI S-DRAM T-PCI +1 0 0 1 0 1 1 A-PCI S-DRAM T-DRAM A-PCI S-DRAM T-DRAM + +1 1 0 0 0 0 0 A-DRAM S-PCI T-PCI A-DRAM S-PCI T-PCI +1 1 0 0 0 0 1 A-DRAM S-PCI T-DRAM A-DRAM S-PCI T-DRAM +1 1 0 0 0 1 0 A-PCI S-DRAM T-PCI A-PCI S-DRAM T-PCI +1 1 0 0 0 1 1 A-PCI S-DRAM T-DRAM A-PCI S-DRAM T-DRAM + +1 0 1 0 0 0 0 A-DRAM S-PCI T-PCI A-PCI S-PCI T-PCI +1 0 1 0 0 0 1 A-DRAM S-PCI T-DRAM A-PCI S-PCI T-PCI +1 0 1 0 0 1 0 A-dram S-DRAM T-PCI A-PCI S-PCI T-PCI +1 0 1 0 0 1 1 A-PCI S-DRAM T-DRAM A-PCI S-PCI T-PCI + +1 1 1 0 0 0 0 A-DRAM S-PCI T-PCI A-PCI S-PCI T-PCI +1 1 1 0 0 0 1 A-DRAM S-PCI T-DRAM A-PCI S-PCI T-PCI +1 1 1 0 0 1 0 A-PCI S-DRAM T-PCI A-PCI S-PCI T-PCI +1 1 1 0 0 1 1 A-PCI S-DRAM T-DRAM A-PCI S-PCI T-PCI + +1 0 0 1 1 0 0 A-DRAM S-PCI T-PCI A-DRAM S-PCI T-PCI +1 0 0 1 1 0 1 A-DRAM S-PCI T-DRAM A-DRAM S-PCI T-DRAM +1 0 0 1 1 1 0 A-PCI S-DRAM T-PCI A-PCI S-DRAM T-PCI +1 0 0 1 1 1 1 A-PCI S-DRAM T-DRAM A-PCI S-DRAM T-DRAM + +1 0 0 0 1 x x A-PCI S-PCI T-PCI A-PCI S-PCI T-PCI +1 0 1 0 1 x x A-PCI S-PCI T-PCI A-PCI S-PCI T-PCI +1 1 0 0 1 x x A-PCI S-PCI T-PCI A-PCI S-PCI T-PCI +1 1 1 0 1 x x A-PCI S-PCI T-PCI A-PCI S-PCI T-PCI +*/ + +void i82439tx_device::update_smram_mappings() +{ + int old = m_smram.mapping; + if (m_smram.g_smrame == 0) + m_smram.mapping = 0; // pci active in all ranges + else if (m_smram.smiact_n == 1) + { + if (m_smram.d_open == 1) + { + // TSEG_EN decides if tseg is present or not + // H_SMRAME decides between smram compatible and extended + m_smram.mapping = (1 - m_smram.h_smrame) | (m_smram.h_smrame << 1) | (m_smram.tseg_en << 2); + } + else + m_smram.mapping = 0; // pci active in all ranges + } + else // SMIACT# is 0 + { + // TSEG_EN decides if tseg is present or not + // H_SMRAME decides between smram compatible and extended + m_smram.mapping = (1 - m_smram.h_smrame) | (m_smram.h_smrame << 1) | (m_smram.tseg_en << 2); + } + if (m_smram.mapping != old) + { + int change = old ^ m_smram.mapping; + + if (change & 1) + { + // unmap current 0xa0000 to 0xbffff + m_space->unmap_readwrite(0xa0000, 0xbffff); + // map new + if (m_smram.mapping & 1) + { + m_space->install_ram(0xa0000, 0xbffff, m_ram->pointer() + 0xa0000); + } + else + m_pci_bus->remap(AS_PROGRAM, 0xa0000, 0xbffff); // remap all pci and isa devices + } + if (change & 2) + { + // unmap current 0x100a0000 to 0x100fffff + m_space->unmap_readwrite(0x100a0000, 0x100fffff); + // map new + if (m_smram.mapping & 2) + { + m_space->install_ram(0x100a0000, 0x100fffff, m_ram->pointer() + 0xa0000); // TODO: exclude areas used by shadow ram + } + else + m_pci_bus->remap(AS_PROGRAM, 0x100a0000, 0x100fffff); // remap all pci and isa devices + } + if (change & 4) + { + offs_t s = 0x10000000 + m_ram->size() - (offs_t)m_smram.tseg_size; + offs_t e = 0x10000000 + m_ram->size() - 1; + + // unmap current 0x10000000+dram_size-tseg_size to 0x10000000+dram_size-1 + m_space->unmap_readwrite(s, e); + // map new + if (m_smram.mapping & 4) + { + m_space->install_ram(s, e, m_ram->pointer() + m_ram->size() - (offs_t)m_smram.tseg_size); + } + else + m_pci_bus->remap(AS_PROGRAM, s, e); // remap all pci and isa devices + } + } +} + +WRITE_LINE_MEMBER(i82439tx_device::smi_act_w) +{ + // state is 0 when smm is not active + // but smiact_n reflects the state of the SMIACT# pin + if (state == 0) + m_smram.smiact_n = 1; + else + m_smram.smiact_n = 0; + update_smram_mappings(); +} + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- @@ -288,6 +453,7 @@ void i82439tx_device::device_start() // setup save states save_item(NAME(m_regs)); save_item(NAME(m_bios_ram)); + // TODO: savestate m_smram } //------------------------------------------------- @@ -306,6 +472,7 @@ void i82439tx_device::device_reset() m_regs[0x05] = 0x00000002; m_regs[0x06] = 0x00000000; m_regs[0x07] = 0x00000000; + m_regs[0x20] = 0x00000000; memset(m_bios_ram, 0, sizeof(m_bios_ram)); diff --git a/src/devices/bus/lpci/i82439tx.h b/src/devices/bus/lpci/i82439tx.h index 781ff949089..8b251c6d60b 100644 --- a/src/devices/bus/lpci/i82439tx.h +++ b/src/devices/bus/lpci/i82439tx.h @@ -36,12 +36,15 @@ public: virtual uint32_t pci_read(pci_bus_device *pcibus, int function, int offset, uint32_t mem_mask) override; virtual void pci_write(pci_bus_device *pcibus, int function, int offset, uint32_t data, uint32_t mem_mask) override; + DECLARE_WRITE_LINE_MEMBER(smi_act_w); + protected: // device-level overrides virtual void device_start() override; virtual void device_reset() override; void i82439tx_configure_memory(uint8_t val, offs_t begin, offs_t end); + void update_smram_mappings(); private: const char *m_cpu_tag; @@ -52,6 +55,22 @@ private: uint32_t m_regs[8*256]; uint32_t m_bios_ram[0x40000 / 4]; + + // system management ram setup + struct { + int tseg_en; + int tseg_sz; + int e_smerr; + int h_smrame; + int c_base_seg; + int g_smrame; + int d_lck; + int d_cls; + int d_open; + int smiact_n; + int tseg_size; + int mapping; + } m_smram; }; // device type definition diff --git a/src/devices/bus/lpci/northbridge.cpp b/src/devices/bus/lpci/northbridge.cpp index a2b9314b40a..e07220bb005 100644 --- a/src/devices/bus/lpci/northbridge.cpp +++ b/src/devices/bus/lpci/northbridge.cpp @@ -30,12 +30,12 @@ void northbridge_device::device_start() machine().root_device().membank("bank10")->set_base(m_ram->pointer()); - if (m_ram->size() > 0x0a0000) + if (m_ram->size() > 0x100000) { - offs_t ram_limit = 0x100000 + m_ram->size() - 0x0a0000; - space.install_read_bank(0x100000, ram_limit - 1, "bank1"); - space.install_write_bank(0x100000, ram_limit - 1, "bank1"); - machine().root_device().membank("bank1")->set_base(m_ram->pointer() + 0xa0000); + offs_t ram_limit = 0x100000 + m_ram->size() - 0x100000; + space.install_read_bank (0x100000, ram_limit - 1, "bank1"); + space.install_write_bank(0x100000, ram_limit - 1, "bank1"); + machine().root_device().membank("bank1")->set_base(m_ram->pointer() + 0x100000); } } diff --git a/src/devices/bus/lpci/pci.cpp b/src/devices/bus/lpci/pci.cpp index d6c8aef5bba..7d1969f86a7 100644 --- a/src/devices/bus/lpci/pci.cpp +++ b/src/devices/bus/lpci/pci.cpp @@ -234,6 +234,18 @@ void pci_bus_device::add_sibling(pci_bus_device *sibling, int busnum) m_siblings_count++; } +void pci_bus_device::remap(int space_id, offs_t start, offs_t end) +{ + for (int i = 0; i < ARRAY_LENGTH(m_devtag); i++) + { + if (m_device[i] != nullptr) + m_device[i]->remap(space_id, start, end); + } + for (int i = 0; i < m_siblings_count; i++) + m_siblings[i]->remap(space_id, start, end); +} + + //------------------------------------------------- // device_post_load - handle updating after a @@ -263,8 +275,11 @@ void pci_bus_device::device_start() { sprintf(id, "%d", i); pci_connector_device *conn = downcast(subdevice(id)); - if (conn!=nullptr) + if (conn != nullptr) + { m_device[i] = conn->get_device(); + m_device[i]->set_pci_bus(this); + } else m_device[i] = nullptr; } @@ -298,7 +313,8 @@ void pci_bus_device::device_reset() //------------------------------------------------- pci_device_interface::pci_device_interface(const machine_config &mconfig, device_t &device) - : device_slot_card_interface(mconfig, device) + : device_slot_card_interface(mconfig, device), + m_pci_bus(nullptr) { } diff --git a/src/devices/bus/lpci/pci.h b/src/devices/bus/lpci/pci.h index f6c30037597..aa9721435f8 100644 --- a/src/devices/bus/lpci/pci.h +++ b/src/devices/bus/lpci/pci.h @@ -12,6 +12,7 @@ #define MAME_BUS_LPCI_PCI_H #pragma once +#include //************************************************************************** // TYPE DEFINITIONS @@ -29,8 +30,14 @@ public: virtual uint32_t pci_read(pci_bus_device *pcibus, int function, int offset, uint32_t mem_mask) = 0; virtual void pci_write(pci_bus_device *pcibus, int function, int offset, uint32_t data, uint32_t mem_mask) = 0; + virtual void remap(int space_id, offs_t start, offs_t end) {} + + void set_pci_bus(pci_bus_device *bus) { m_pci_bus = bus; } + protected: pci_device_interface(const machine_config &mconfig, device_t &device); + + pci_bus_device *m_pci_bus; }; class pci_connector_device : public device_t, @@ -70,6 +77,8 @@ public: pci_bus_device *pci_search_bustree(int busnum, int devicenum, pci_bus_device *pcibus); void add_sibling(pci_bus_device *sibling, int busnum); + void remap(int space_id, offs_t start, offs_t end); + protected: // device-level overrides virtual void device_start() override; diff --git a/src/devices/bus/lpci/southbridge.cpp b/src/devices/bus/lpci/southbridge.cpp index 882ceb26efa..df23c3fd9e9 100644 --- a/src/devices/bus/lpci/southbridge.cpp +++ b/src/devices/bus/lpci/southbridge.cpp @@ -123,7 +123,7 @@ southbridge_device::southbridge_device(const machine_config &mconfig, device_typ m_speaker(*this, "speaker"), m_ide(*this, "ide"), m_ide2(*this, "ide2"), - m_at_spkrdata(0), m_pit_out2(0), m_dma_channel(0), m_cur_eop(false), m_dma_high_byte(0), m_at_speaker(0), m_refresh(false), m_channel_check(0), m_nmi_enabled(0) + m_at_spkrdata(0), m_pit_out2(0), m_dma_channel(0), m_cur_eop(false), m_dma_high_byte(0), m_at_speaker(0), m_refresh(false), m_eisa_irq_mode(0), m_channel_check(0), m_nmi_enabled(0), m_ide_io_ports_enabled(true) { } @@ -133,50 +133,103 @@ southbridge_device::southbridge_device(const machine_config &mconfig, device_typ * **********************************************************/ -/// HACK: the memory system cannot cope with mixing the 8 bit device map from the fdc with a 32 bit handler -READ8_MEMBER(southbridge_device::ide_read_cs1_r) +READ32_MEMBER(southbridge_device::ide1_read32_cs0_r) { + if (!m_ide_io_ports_enabled) + return 0xffffffff; + return m_ide->read_cs0(space, offset, mem_mask); +} + +WRITE32_MEMBER(southbridge_device::ide1_write32_cs0_w) +{ + if (!m_ide_io_ports_enabled) + return; + m_ide->write_cs0(space, offset, data, mem_mask); +} + +READ32_MEMBER(southbridge_device::ide2_read32_cs0_r) +{ + if (!m_ide_io_ports_enabled) + return 0xffffffff; + return m_ide2->read_cs0(space, offset, mem_mask); +} + +WRITE32_MEMBER(southbridge_device::ide2_write32_cs0_w) +{ + if (!m_ide_io_ports_enabled) + return; + m_ide2->write_cs0(space, offset, data, mem_mask); +} + +READ8_MEMBER(southbridge_device::ide1_read_cs1_r) +{ + if (!m_ide_io_ports_enabled) + return 0xff; return m_ide->read_cs1(1, 0xff0000) >> 16; } -WRITE8_MEMBER(southbridge_device::ide_write_cs1_w) +WRITE8_MEMBER(southbridge_device::ide1_write_cs1_w) { + if (!m_ide_io_ports_enabled) + return; m_ide->write_cs1(1, data << 16, 0xff0000); } READ8_MEMBER(southbridge_device::ide2_read_cs1_r) { + if (!m_ide_io_ports_enabled) + return 0xff; return m_ide2->read_cs1(1, 0xff0000) >> 16; } WRITE8_MEMBER(southbridge_device::ide2_write_cs1_w) { + if (!m_ide_io_ports_enabled) + return; m_ide2->write_cs1(1, data << 16, 0xff0000); } +// With EISA it is possible to select whether each IRQ line is edge sensitive or level sensitive +// Each bit corresponds to an IRQ, 0 for edge triggered 1 for level sensitive +// IRQs 0 1 2 8 13 are always edge triggered +READ8_MEMBER(southbridge_device::eisa_irq_read) +{ + if (offset == 0) + return m_eisa_irq_mode & 0xff; + else + return m_eisa_irq_mode >> 8; +} + +WRITE8_MEMBER(southbridge_device::eisa_irq_write) +{ + if (offset == 0) + m_eisa_irq_mode = (m_eisa_irq_mode & 0xff00) | data; + else + m_eisa_irq_mode = (m_eisa_irq_mode & 0x00ff) | (data << 8); + // TODO: update m_pic8259_master and m_pic8259_slave with the new configuration +} + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void southbridge_device::device_start() { - address_space& spaceio = machine().device(":maincpu")->memory().space(AS_IO); + spaceio = &machine().device(":maincpu")->memory().space(AS_IO); - spaceio.install_readwrite_handler(0x0000, 0x001f, read8_delegate(FUNC(am9517a_device::read),&(*m_dma8237_1)), write8_delegate(FUNC(am9517a_device::write),&(*m_dma8237_1)), 0xffffffff); - spaceio.install_readwrite_handler(0x0020, 0x003f, read8_delegate(FUNC(pic8259_device::read),&(*m_pic8259_master)), write8_delegate(FUNC(pic8259_device::write),&(*m_pic8259_master)), 0xffffffff); - spaceio.install_readwrite_handler(0x0040, 0x005f, read8_delegate(FUNC(pit8254_device::read),&(*m_pit8254)), write8_delegate(FUNC(pit8254_device::write),&(*m_pit8254)), 0xffffffff); - spaceio.install_readwrite_handler(0x0060, 0x0063, read8_delegate(FUNC(southbridge_device::at_portb_r), this), write8_delegate(FUNC(southbridge_device::at_portb_w), this), 0x0000ff00); - spaceio.install_readwrite_handler(0x0080, 0x009f, read8_delegate(FUNC(southbridge_device::at_page8_r),this), write8_delegate(FUNC(southbridge_device::at_page8_w),this), 0xffffffff); - spaceio.install_readwrite_handler(0x00a0, 0x00bf, read8_delegate(FUNC(pic8259_device::read),&(*m_pic8259_slave)), write8_delegate(FUNC(pic8259_device::write),&(*m_pic8259_slave)), 0xffffffff); - spaceio.install_readwrite_handler(0x00c0, 0x00df, read8_delegate(FUNC(southbridge_device::at_dma8237_2_r),this), write8_delegate(FUNC(southbridge_device::at_dma8237_2_w),this), 0xffffffff); - spaceio.install_readwrite_handler(0x0170, 0x0177, read32_delegate(FUNC(bus_master_ide_controller_device::read_cs0),&(*m_ide2)), write32_delegate(FUNC(bus_master_ide_controller_device::write_cs0), &(*m_ide2)),0xffffffff); - spaceio.install_readwrite_handler(0x01f0, 0x01f7, read32_delegate(FUNC(bus_master_ide_controller_device::read_cs0),&(*m_ide)), write32_delegate(FUNC(bus_master_ide_controller_device::write_cs0), &(*m_ide)),0xffffffff); -// HACK: this works if you take out the (non working) fdc -// spaceio.install_readwrite_handler(0x0370, 0x0377, read32_delegate(FUNC(bus_master_ide_controller_device::read_cs1),&(*m_ide2)), write32_delegate(FUNC(bus_master_ide_controller_device::write_cs1), &(*m_ide2)),0xffffffff); -// spaceio.install_readwrite_handler(0x03f0, 0x03f7, read32_delegate(FUNC(bus_master_ide_controller_device::read_cs1),&(*m_ide)), write32_delegate(FUNC(bus_master_ide_controller_device::write_cs1), &(*m_ide)),0xffffffff); - spaceio.install_readwrite_handler(0x0374, 0x0377, read8_delegate(FUNC(southbridge_device::ide2_read_cs1_r),this), write8_delegate(FUNC(southbridge_device::ide2_write_cs1_w), this),0xff0000); - spaceio.install_readwrite_handler(0x03f4, 0x03f7, read8_delegate(FUNC(southbridge_device::ide_read_cs1_r),this), write8_delegate(FUNC(southbridge_device::ide_write_cs1_w), this),0xff0000); - spaceio.nop_readwrite(0x00e0, 0x00ef); + spaceio->install_readwrite_handler(0x0000, 0x001f, read8_delegate(FUNC(am9517a_device::read), &(*m_dma8237_1)), write8_delegate(FUNC(am9517a_device::write), &(*m_dma8237_1)), 0xffffffff); + spaceio->install_readwrite_handler(0x0020, 0x003f, read8_delegate(FUNC(pic8259_device::read), &(*m_pic8259_master)), write8_delegate(FUNC(pic8259_device::write), &(*m_pic8259_master)), 0xffffffff); + spaceio->install_readwrite_handler(0x0040, 0x005f, read8_delegate(FUNC(pit8254_device::read), &(*m_pit8254)), write8_delegate(FUNC(pit8254_device::write), &(*m_pit8254)), 0xffffffff); + spaceio->install_readwrite_handler(0x0060, 0x0063, read8_delegate(FUNC(southbridge_device::at_portb_r), this), write8_delegate(FUNC(southbridge_device::at_portb_w), this), 0x0000ff00); + spaceio->install_readwrite_handler(0x0080, 0x009f, read8_delegate(FUNC(southbridge_device::at_page8_r), this), write8_delegate(FUNC(southbridge_device::at_page8_w), this), 0xffffffff); + spaceio->install_readwrite_handler(0x00a0, 0x00bf, read8_delegate(FUNC(pic8259_device::read), &(*m_pic8259_slave)), write8_delegate(FUNC(pic8259_device::write), &(*m_pic8259_slave)), 0xffffffff); + spaceio->install_readwrite_handler(0x00c0, 0x00df, read8_delegate(FUNC(southbridge_device::at_dma8237_2_r), this), write8_delegate(FUNC(southbridge_device::at_dma8237_2_w), this), 0xffffffff); + spaceio->install_readwrite_handler(0x0170, 0x0177, read32_delegate(FUNC(southbridge_device::ide2_read32_cs0_r), this), write32_delegate(FUNC(southbridge_device::ide2_write32_cs0_w), this), 0xffffffff); + spaceio->install_readwrite_handler(0x01f0, 0x01f7, read32_delegate(FUNC(southbridge_device::ide1_read32_cs0_r), this), write32_delegate(FUNC(southbridge_device::ide1_write32_cs0_w), this), 0xffffffff); + spaceio->install_readwrite_handler(0x0374, 0x0377, read8_delegate(FUNC(southbridge_device::ide2_read_cs1_r), this), write8_delegate(FUNC(southbridge_device::ide2_write_cs1_w), this), 0xff0000); + spaceio->install_readwrite_handler(0x03f4, 0x03f7, read8_delegate(FUNC(southbridge_device::ide1_read_cs1_r), this), write8_delegate(FUNC(southbridge_device::ide1_write_cs1_w), this), 0xff0000); + spaceio->install_readwrite_handler(0x04d0, 0x04d3, read8_delegate(FUNC(southbridge_device::eisa_irq_read), this), write8_delegate(FUNC(southbridge_device::eisa_irq_write), this), 0x0000ffff); + spaceio->nop_readwrite(0x00e0, 0x00ef); } //------------------------------------------------- diff --git a/src/devices/bus/lpci/southbridge.h b/src/devices/bus/lpci/southbridge.h index 011f43476ee..0e25c8392f4 100644 --- a/src/devices/bus/lpci/southbridge.h +++ b/src/devices/bus/lpci/southbridge.h @@ -72,10 +72,13 @@ protected: uint16_t m_dma_high_byte; uint8_t m_at_speaker; bool m_refresh; + uint16_t m_eisa_irq_mode; void at_speaker_set_spkrdata(uint8_t data); uint8_t m_channel_check; uint8_t m_nmi_enabled; + bool m_ide_io_ports_enabled; + address_space *spaceio; void pc_select_dma_channel(int channel, bool state); @@ -112,16 +115,24 @@ private: DECLARE_WRITE_LINE_MEMBER(pc_dack5_w); DECLARE_WRITE_LINE_MEMBER(pc_dack6_w); DECLARE_WRITE_LINE_MEMBER(pc_dack7_w); - DECLARE_READ8_MEMBER(ide_read_cs1_r); - DECLARE_WRITE8_MEMBER(ide_write_cs1_w); + + DECLARE_READ32_MEMBER(ide1_read32_cs0_r); + DECLARE_WRITE32_MEMBER(ide1_write32_cs0_w); + DECLARE_READ32_MEMBER(ide2_read32_cs0_r); + DECLARE_WRITE32_MEMBER(ide2_write32_cs0_w); + DECLARE_READ8_MEMBER(ide1_read_cs1_r); + DECLARE_WRITE8_MEMBER(ide1_write_cs1_w); DECLARE_READ8_MEMBER(ide2_read_cs1_r); DECLARE_WRITE8_MEMBER(ide2_write_cs1_w); + DECLARE_READ8_MEMBER(at_dma8237_2_r); DECLARE_WRITE8_MEMBER(at_dma8237_2_w); DECLARE_READ8_MEMBER(pc_dma_read_byte); DECLARE_WRITE8_MEMBER(pc_dma_write_byte); DECLARE_READ8_MEMBER(pc_dma_read_word); DECLARE_WRITE8_MEMBER(pc_dma_write_word); + DECLARE_READ8_MEMBER(eisa_irq_read); + DECLARE_WRITE8_MEMBER(eisa_irq_write); }; // ======================> southbridge_extended_device