i82439tx: add support for system management mode and more [Samuele Zannoli]

This is a squash of various commits whose messages are below
.
i82371sb.cpp: update to ide and usb pci config registers (nw)
With ide is now possible to enable and disable access to io ports (bus master dma ones too).
.
southbridge.cpp: support to enable/disable ide io ports (nw)
When disabled reads should return all bits to 1 and writes should do nothing.
Used when io access is disabled by py pci config registers.
.
lpci/i82371ab.cpp: small update for system managemant mode (nw)
.
lpci/southbridge.h: intercept access to eisa interrupt line mode config ports (nw)
.
lpci/northbridge.cpp: do not remap ram betweek 640k and 1megabyte (nw)
.
lpci/i82439tx.cpp: support System Management Mode (nw)
i82371sb.cpp is updated too
.
legacy pci: pci devices now have the possibility to remap themselves (nw)
like in the isa bus remap(int space_id, offs_t start, offs_t end) of the pci bus manager can
be called to tell devices that if they have mapped something in address space space_id from start to end
they should remap themselves
It will be used with system management mode.
.
isa bus: isa devices now have the possibility to remap themselves (nw)
 - isa bus managers have a list of their slots
 - isa bus managers and device base classes have a new virtual method remap()
 - modify the et4000 isa device to support the new method
Currently isa devices map themselves in their address space ranges only in device_start()
and if something unmaps them, they are not visible anymore
remap(int space_id, offs_t start, offs_t end) of the isa bus manager can be called
to tell devices that if they have mapped something in address space space_id from start to end
they should remap themselves
This commit is contained in:
yz70s 2018-04-25 12:22:54 +02:00
parent 41b5695ab7
commit 1f6f676556
15 changed files with 548 additions and 41 deletions

View File

@ -43,10 +43,13 @@ void isa8_slot_device::device_start()
{
device_isa8_card_interface *dev = dynamic_cast<device_isa8_card_interface *>(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<isa8_device *>(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<device_isa8_card_interface *>(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<isa8_device *>(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<device_slot_interface *>(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<device_isa8_card_interface *>(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<device_isa16_card_interface *>(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<device_isa8_card_interface *>(dev);
device_isa16_card_interface *isadev16 = dynamic_cast<device_isa16_card_interface *>(dev);
if (isadev16)
isadev16->remap(space_id, start, end);
else
if (isadev8)
isadev8->remap(space_id, start, end);
}
}
}
//-------------------------------------------------
// device_isa16_card_interface - constructor
//-------------------------------------------------

View File

@ -67,6 +67,7 @@
#pragma once
#include <forward_list>
//**************************************************************************
@ -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<device_slot_interface *> 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);

View File

@ -74,12 +74,8 @@ void isa8_svga_et4k_device::device_start()
m_vga = subdevice<tseng_vga_device>("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));
}

View File

@ -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;
};

View File

@ -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
//-------------------------------------------------

View File

@ -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;

View File

@ -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);
}

View File

@ -24,11 +24,14 @@ public:
// construction/destruction
i82371sb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
template <class Object> devcb_base &set_smi_callback(Object &&cb) { return m_smi_callback.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_boot_state_hook(Object &&cb) { return m_boot_state_hook.set_callback(std::forward<Object>(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<i82371sb_device &>(*device).set_smi_callback(DEVCB_##_devcb);
#define MCFG_I82371SB_BOOT_STATE_HOOK(_devcb) \
devcb = &downcast<i82371sb_device &>(*device).set_boot_state_hook(DEVCB_##_devcb);

View File

@ -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));

View File

@ -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

View File

@ -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);
}
}

View File

@ -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<pci_connector_device *>(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)
{
}

View File

@ -12,6 +12,7 @@
#define MAME_BUS_LPCI_PCI_H
#pragma once
#include <forward_list>
//**************************************************************************
// 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;

View File

@ -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);
}
//-------------------------------------------------

View File

@ -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