diff options
author | 2014-11-03 17:00:25 +0100 | |
---|---|---|
committer | 2014-11-05 13:28:48 +0100 | |
commit | f975ef079a135fe3bdc19c0a70cd41178ffff5d8 (patch) | |
tree | 02e852ce8692fbf66121a2225af04d033c3f3947 /src/emu/bus/lpci | |
parent | 749dbb5f4a9faac3758c7d1eca09038e76007c03 (diff) |
Experiments in PCI land [O. Galibert]
Diffstat (limited to 'src/emu/bus/lpci')
-rw-r--r-- | src/emu/bus/lpci/cirrus.c | 162 | ||||
-rw-r--r-- | src/emu/bus/lpci/cirrus.h | 39 | ||||
-rw-r--r-- | src/emu/bus/lpci/i82371ab.c | 255 | ||||
-rw-r--r-- | src/emu/bus/lpci/i82371ab.h | 51 | ||||
-rw-r--r-- | src/emu/bus/lpci/i82371sb.c | 179 | ||||
-rw-r--r-- | src/emu/bus/lpci/i82371sb.h | 48 | ||||
-rw-r--r-- | src/emu/bus/lpci/i82439tx.c | 310 | ||||
-rw-r--r-- | src/emu/bus/lpci/i82439tx.h | 57 | ||||
-rw-r--r-- | src/emu/bus/lpci/mpc105.c | 231 | ||||
-rw-r--r-- | src/emu/bus/lpci/mpc105.h | 58 | ||||
-rw-r--r-- | src/emu/bus/lpci/northbridge.c | 46 | ||||
-rw-r--r-- | src/emu/bus/lpci/northbridge.h | 32 | ||||
-rw-r--r-- | src/emu/bus/lpci/pci.c | 332 | ||||
-rw-r--r-- | src/emu/bus/lpci/pci.h | 110 | ||||
-rw-r--r-- | src/emu/bus/lpci/southbridge.c | 488 | ||||
-rw-r--r-- | src/emu/bus/lpci/southbridge.h | 129 |
16 files changed, 2527 insertions, 0 deletions
diff --git a/src/emu/bus/lpci/cirrus.c b/src/emu/bus/lpci/cirrus.c new file mode 100644 index 00000000000..ac001b09b74 --- /dev/null +++ b/src/emu/bus/lpci/cirrus.c @@ -0,0 +1,162 @@ +/*************************************************************************** + + video/cirrus.c + + Cirrus SVGA card emulation (preliminary) + + Cirrus has the following additional registers that are not present in + conventional VGA: + + SEQ 06h: Unlock Cirrus registers; write 12h to unlock registers, + and read 12h back to confirm Cirrus presence. + SEQ 07h + bit 3-1: Pixel depth + 0x00 8 bpp + 0x02 16 bpp (double vert clock) + 0x04 24 bpp + 0x06 16 bpp + 0x08 32 bpp + bit 0: VGA/SVGA (0=VGA, 1=SVGA) + SEQ 0Fh + bit 7: Bankswitch enable + bits 4-3: Memory size + 0x00 256K + 0x08 512K + 0x10 1M + 0x18 2M + SEQ 12h: Hardware Cursor + + + + + GC 09h: Set 64k bank (bits 3-0 only) + GC 20h: Blit Width (bits 7-0) + GC 21h: Blit Width (bits 12-8) + GC 22h: Blit Height (bits 7-0) + GC 23h: Blit Height (bits 12-8) + GC 24h: Blit Destination Pitch (bits 7-0) + GC 25h: Blit Destination Pitch (bits 12-8) + GC 26h: Blit Source Pitch (bits 7-0) + GC 27h: Blit Source Pitch (bits 12-8) + GC 28h: Blit Destination Address (bits 7-0) + GC 29h: Blit Destination Address (bits 15-8) + GC 2Ah: Blit Destination Address (bits 21-16) + GC 2Ch: Blit Source Address (bits 7-0) + GC 2Dh: Blit Source Address (bits 15-8) + GC 2Eh: Blit Source Address (bits 21-16) + GC 2Fh: Blit Write Mask + GC 30h: Blit Mode + GC 31h: Blit Status + bit 7 - Autostart + bit 4 - FIFO Used + bit 2 - Blit Reset + bit 1 - Blit Started + bit 0 - Blit Busy + GC 32h: Raster Operation + GC 33h: Blit Mode Extension + GC 34h: Blit Transparent Color (bits 7-0) + GC 35h: Blit Transparent Color (bits 15-8) + GC 38h: Blit Transparent Color Mask (bits 7-0) + GC 39h: Blit Transparent Color Mask (bits 15-8) + +***************************************************************************/ + +#include "emu.h" +#include "cirrus.h" +#include "video/pc_vga.h" + +#define LOG_PCIACCESS 0 + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type CIRRUS = &device_creator<cirrus_device>; + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// cirrus_device - constructor +//------------------------------------------------- + +cirrus_device::cirrus_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, CIRRUS, "CIRRUS", tag, owner, clock, "cirrus", __FILE__), + pci_device_interface( mconfig, *this ) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void cirrus_device::device_start() +{ +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void cirrus_device::device_reset() +{ +} + +//------------------------------------------------- +// pci_read - implementation of PCI read +//------------------------------------------------- + +UINT32 cirrus_device::pci_read(pci_bus_device *pcibus, int function, int offset, UINT32 mem_mask) +{ + UINT32 result = 0; + + if (function == 0) + { + switch(offset) + { + case 0x00: /* vendor/device ID */ + result = 0x00A01013; + break; + + case 0x08: + result = 0x03000000; + break; + + case 0x10: + result = 0xD0000000; + break; + + default: + result = 0; + break; + } + } + + if (LOG_PCIACCESS) + logerror("cirrus5430_pci_read(): function=%d offset=0x%02X result=0x%04X\n", function, offset, result); + return result; +} + + +//------------------------------------------------- +// pci_write - implementation of PCI write +//------------------------------------------------- + +void cirrus_device::pci_write(pci_bus_device *pcibus, int function, int offset, UINT32 data, UINT32 mem_mask) +{ + if (LOG_PCIACCESS) + logerror("cirrus5430_pci_write(): function=%d offset=0x%02X data=0x%04X\n", function, offset, data); +} + +/************************************* + * + * Ports + * + *************************************/ + +WRITE8_MEMBER( cirrus_device::cirrus_42E8_w ) +{ + if (data & 0x80) + machine().device("vga")->reset(); +} diff --git a/src/emu/bus/lpci/cirrus.h b/src/emu/bus/lpci/cirrus.h new file mode 100644 index 00000000000..9027f6827e4 --- /dev/null +++ b/src/emu/bus/lpci/cirrus.h @@ -0,0 +1,39 @@ +/*************************************************************************** + + video/cirrus.h + + Cirrus SVGA card emulation (preliminary) + +***************************************************************************/ + +#ifndef CIRRUS_H +#define CIRRUS_H + +#include "bus/lpci/pci.h" + +// ======================> cirrus_device + +class cirrus_device : public device_t, + public pci_device_interface +{ +public: + // construction/destruction + cirrus_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + virtual UINT32 pci_read(pci_bus_device *pcibus, int function, int offset, UINT32 mem_mask); + virtual void pci_write(pci_bus_device *pcibus, int function, int offset, UINT32 data, UINT32 mem_mask); + + DECLARE_WRITE8_MEMBER( cirrus_42E8_w ); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); +private: +}; + + +// device type definition +extern const device_type CIRRUS; + +#endif /* CIRRUS_H */ diff --git a/src/emu/bus/lpci/i82371ab.c b/src/emu/bus/lpci/i82371ab.c new file mode 100644 index 00000000000..649d1ed3b78 --- /dev/null +++ b/src/emu/bus/lpci/i82371ab.c @@ -0,0 +1,255 @@ +/*************************************************************************** + + Intel 82371AB PCI IDE ISA Xcelerator (PIIX4) + + Part of the Intel 430TX chipset + + - Integrated IDE Controller + - Enhanced DMA Controller based on two 82C37 + - Interrupt Controller based on two 82C59 + - Timers based on 82C54 + - USB + - SMBus + - Real Time Clock based on MC146818 + +***************************************************************************/ + +#include "emu.h" +#include "i82371ab.h" + +const device_type I82371AB = &device_creator<i82371ab_device>; + + +i82371ab_device::i82371ab_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : southbridge_device(mconfig, I82371AB, "Intel 82371AB", tag, owner, clock, "i82371ab", __FILE__), + pci_device_interface( mconfig, *this ) +{ +} + +UINT32 i82371ab_device::pci_isa_r(device_t *busdevice, int offset, UINT32 mem_mask) +{ + UINT32 result = m_regs[0][offset] | + m_regs[0][offset+1] << 8 | + m_regs[0][offset+2] << 16| + m_regs[0][offset+3] << 24; + + logerror("i82371ab_pci_isa_r, offset = %02x, mem_mask = %08x\n", offset, mem_mask); + + return result; +} + +void i82371ab_device::pci_isa_w(device_t *busdevice, int offset, UINT32 data, UINT32 mem_mask) +{ + UINT32 cdata = 0; + int i; + COMBINE_DATA(&cdata); + + logerror("i82371ab_pci_isa_w, offset = %02x, data = %08x, mem_mask = %08x\n", offset, data, mem_mask); + + for(i = 0; i < 4; i++, offset++, cdata >>= 8) + { + switch (offset) + { + case 0x04: + /* clear reserved bits */ + m_regs[0][offset] = cdata & 0x05; + break; + case 0x06: + /* set new status */ + m_regs[0][offset] |= 0x80; + break; + case 0x07: + m_regs[0][offset] |= 0x02; + break; + } + } +} + +UINT32 i82371ab_device::pci_ide_r(device_t *busdevice, int offset, UINT32 mem_mask) +{ + UINT32 result = m_regs[1][offset] | + m_regs[1][offset+1] << 8 | + m_regs[1][offset+2] << 16| + m_regs[1][offset+3] << 24; + + logerror("i82371ab_pci_ide_r, offset = %02x, mem_mask = %08x\n", offset, mem_mask); + + return result; +} + +void i82371ab_device::pci_ide_w(device_t *busdevice, int offset, UINT32 data, UINT32 mem_mask) +{ + UINT32 cdata = 0; + int i; + COMBINE_DATA(&cdata); + + logerror("i82371ab_pci_isa_w, offset = %02x, data = %08x, mem_mask = %08x\n", offset, data, mem_mask); + + for(i = 0; i < 4; i++, offset++, cdata >>= 8) + { + switch (offset) + { + case 0x04: + /* clear reserved bits */ + m_regs[1][offset] = cdata & 0x05; + break; + case 0x06: + /* set new status */ + m_regs[1][offset] |= 0x80; + break; + case 0x07: + m_regs[1][offset] |= 0x02; + break; + } + } +} + +UINT32 i82371ab_device::pci_usb_r(device_t *busdevice, int offset, UINT32 mem_mask) +{ + UINT32 result = m_regs[2][offset] | + m_regs[2][offset+1] << 8 | + m_regs[2][offset+2] << 16| + m_regs[2][offset+3] << 24; + + logerror("i82371ab_pci_usb_r, offset = %02x, mem_mask = %08x\n", offset, mem_mask); + + return result; +} + +void i82371ab_device::pci_usb_w(device_t *busdevice, int offset, UINT32 data, UINT32 mem_mask) +{ + UINT32 cdata = 0; + int i; + COMBINE_DATA(&cdata); + + logerror("i82371ab_pci_isa_w, offset = %02x, data = %08x, mem_mask = %08x\n", offset, data, mem_mask); + + for(i = 0; i < 4; i++, offset++, cdata >>= 8) + { + switch (offset) + { + case 0x04: + /* clear reserved bits */ + m_regs[2][offset] = cdata & 0x05; + break; + case 0x06: + /* set new status */ + m_regs[2][offset] |= 0x80; + break; + case 0x07: + m_regs[2][offset] |= 0x02; + break; + } + } +} + +UINT32 i82371ab_device::pci_acpi_r(device_t *busdevice, int offset, UINT32 mem_mask) +{ + UINT32 result = m_regs[3][offset] | + m_regs[3][offset+1] << 8 | + m_regs[3][offset+2] << 16| + m_regs[3][offset+3] << 24; + + logerror("i82371ab_pci_acpi_r, offset = %02x, mem_mask = %08x\n", offset, mem_mask); + + return result; +} + +void i82371ab_device::pci_acpi_w(device_t *busdevice, int offset, UINT32 data, UINT32 mem_mask) +{ + UINT32 cdata = 0; + int i; + COMBINE_DATA(&cdata); + + logerror("i82371ab_pci_isa_w, offset = %02x, data = %08x, mem_mask = %08x\n", offset, data, mem_mask); + + for(i = 0; i < 4; i++, offset++, cdata >>= 8) + { + switch (offset) + { + case 0x04: + /* clear reserved bits */ + m_regs[3][offset] = cdata & 0x05; + break; + case 0x06: + /* set new status */ + m_regs[3][offset] |= 0x80; + break; + case 0x07: + m_regs[3][offset] |= 0x02; + break; + } + } +} + +UINT32 i82371ab_device::pci_read(pci_bus_device *pcibus, int function, int offset, UINT32 mem_mask) +{ + switch (function) + { + case 0: return pci_isa_r(pcibus, offset, mem_mask); + case 1: return pci_ide_r(pcibus, offset, mem_mask); + case 2: return pci_usb_r(pcibus, offset, mem_mask); + case 3: return pci_acpi_r(pcibus, offset, mem_mask); + } + + logerror("i82371ab_pci_read: read from undefined function %d\n", function); + + return 0; +} + +void i82371ab_device::pci_write(pci_bus_device *pcibus, int function, int offset, UINT32 data, UINT32 mem_mask) +{ + switch (function) + { + case 0: pci_isa_w(pcibus, offset, data, mem_mask); break; + case 1: pci_ide_w(pcibus, offset, data, mem_mask); break; + case 2: pci_usb_w(pcibus, offset, data, mem_mask); break; + case 3: pci_acpi_w(pcibus, offset, data, mem_mask); break; + } +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void i82371ab_device::device_start() +{ + southbridge_device::device_start(); + /* setup save states */ + save_item(NAME(m_regs)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void i82371ab_device::device_reset() +{ + southbridge_device::device_reset(); + memset(m_regs, 0, sizeof(m_regs)); + UINT32 (*regs32)[64] = (UINT32 (*)[64])(m_regs); + + /* isa */ + regs32[0][0x00] = 0x71108086; + regs32[0][0x04] = 0x00000000; + regs32[0][0x08] = 0x06010000; + regs32[0][0x0c] = 0x00800000; + + /* ide */ + regs32[1][0x00] = 0x71118086; + regs32[1][0x04] = 0x02800000; + regs32[1][0x08] = 0x01018000; + regs32[1][0x0c] = 0x00000000; + + /* usb */ + regs32[2][0x00] = 0x71128086; + regs32[2][0x04] = 0x02800000; + regs32[2][0x08] = 0x0c030000; + regs32[2][0x0c] = 0x00000000; + + /* acpi */ + regs32[3][0x00] = 0x71138086; + regs32[3][0x04] = 0x02800000; + regs32[3][0x08] = 0x06800000; + regs32[3][0x0c] = 0x02800000; +} diff --git a/src/emu/bus/lpci/i82371ab.h b/src/emu/bus/lpci/i82371ab.h new file mode 100644 index 00000000000..c90468e0481 --- /dev/null +++ b/src/emu/bus/lpci/i82371ab.h @@ -0,0 +1,51 @@ +/*************************************************************************** + + Intel 82371AB PCI IDE ISA Xcelerator (PIIX4) + + Part of the Intel 430TX chipset + +***************************************************************************/ + +#ifndef __I82371AB_H__ +#define __I82371AB_H__ + +#include "pci.h" +#include "southbridge.h" + +// ======================> i82371ab_device + +class i82371ab_device : public southbridge_device, + public pci_device_interface +{ +public: + // construction/destruction + i82371ab_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + virtual UINT32 pci_read(pci_bus_device *pcibus, int function, int offset, UINT32 mem_mask); + virtual void pci_write(pci_bus_device *pcibus, int function, int offset, UINT32 data, UINT32 mem_mask); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + UINT32 pci_isa_r(device_t *busdevice, int offset, UINT32 mem_mask); + void pci_isa_w(device_t *busdevice, int offset, UINT32 data, UINT32 mem_mask); + + UINT32 pci_ide_r(device_t *busdevice, int offset, UINT32 mem_mask); + void pci_ide_w(device_t *busdevice, int offset, UINT32 data, UINT32 mem_mask); + + UINT32 pci_usb_r(device_t *busdevice, int offset, UINT32 mem_mask); + void pci_usb_w(device_t *busdevice, int offset, UINT32 data, UINT32 mem_mask); + + UINT32 pci_acpi_r(device_t *busdevice, int offset, UINT32 mem_mask); + void pci_acpi_w(device_t *busdevice, int offset, UINT32 data, UINT32 mem_mask); + +private: + UINT8 m_regs[4][0x100]; +}; + +// device type definition +extern const device_type I82371AB; + +#endif /* __I82371AB_H__ */ diff --git a/src/emu/bus/lpci/i82371sb.c b/src/emu/bus/lpci/i82371sb.c new file mode 100644 index 00000000000..7d173663596 --- /dev/null +++ b/src/emu/bus/lpci/i82371sb.c @@ -0,0 +1,179 @@ +/*************************************************************************** + + Intel 82371SB PCI IDE ISA Xcelerator (PIIX3) + + Part of the Intel 430TX chipset + + - Integrated IDE Controller + - Enhanced DMA Controller based on two 82C37 + - Interrupt Controller based on two 82C59 + - Timers based on 82C54 + - USB + - SMBus + - Real Time Clock based on MC146818 + +***************************************************************************/ + +#include "emu.h" +#include "i82371sb.h" + + +/*************************************************************************** + IMPLEMENTATION +***************************************************************************/ + +const device_type I82371SB = &device_creator<i82371sb_device>; + + +i82371sb_device::i82371sb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : southbridge_device(mconfig, I82371SB, "Intel 82371SB", tag, owner, clock, "i82371sb", __FILE__), + pci_device_interface( mconfig, *this ) +{ +} + +UINT32 i82371sb_device::pci_isa_r(device_t *busdevice,int offset, UINT32 mem_mask) +{ + UINT32 result = m_regs[0][offset]; + + //logerror("i82371sb_pci_isa_r, offset = %02x, mem_mask = %08x\n", offset, mem_mask); + + return result; +} + +void i82371sb_device::pci_isa_w(device_t *busdevice, int offset, UINT32 data, UINT32 mem_mask) +{ + //logerror("i82371sb_pci_isa_w, offset = %02x, data = %08x, mem_mask = %08x\n", offset, data, mem_mask); + + switch (offset) + { + case 0x04: + COMBINE_DATA(&m_regs[0][offset]); + + /* clear reserved bits */ + m_regs[0][offset] &= 0x00000005; + + /* set new status */ + m_regs[0][offset] |= 0x02800000; + + break; + } +} + +UINT32 i82371sb_device::pci_ide_r(device_t *busdevice, int offset, UINT32 mem_mask) +{ + //logerror("i82371sb_pci_ide_r, offset = %02x, mem_mask = %08x\n", offset, mem_mask); + UINT32 result = m_regs[1][offset]; + return result; +} + +void i82371sb_device::pci_ide_w(device_t *busdevice, int offset, UINT32 data, UINT32 mem_mask) +{ + //logerror("i82371sb_pci_ide_w, offset = %02x, data = %08x, mem_mask = %08x\n", offset, data, mem_mask); + + switch (offset) + { + case 0x04: + COMBINE_DATA(&m_regs[1][offset]); + + /* clear reserved bits */ + m_regs[1][offset] &= 0x00000005; + + /* set new status */ + m_regs[1][offset] |= 0x02800000; + + break; + } +} + +UINT32 i82371sb_device::pci_usb_r(device_t *busdevice, int offset, UINT32 mem_mask) +{ + UINT32 result = m_regs[2][offset]; + + //logerror("i82371sb_pci_usb_r, offset = %02x, mem_mask = %08x\n", offset, mem_mask); + + return result; +} + +void i82371sb_device::pci_usb_w(device_t *busdevice, int offset, UINT32 data, UINT32 mem_mask) +{ + //logerror("i82371sb_pci_usb_w, offset = %02x, data = %08x, mem_mask = %08x\n", offset, data, mem_mask); + + switch (offset) + { + case 0x04: + COMBINE_DATA(&m_regs[2][offset]); + + /* clear reserved bits */ + m_regs[2][offset] &= 0x00000005; + + /* set new status */ + m_regs[2][offset] |= 0x02800000; + + break; + } +} + +UINT32 i82371sb_device::pci_read(pci_bus_device *pcibus, int function, int offset, UINT32 mem_mask) +{ + switch (function) + { + case 0: return pci_isa_r(pcibus, offset, mem_mask); + case 1: return pci_ide_r(pcibus, offset, mem_mask); + case 2: return pci_usb_r(pcibus, offset, mem_mask); + } + + //logerror("i82371sb_pci_read: read from undefined function %d\n", function); + + return 0; +} + +void i82371sb_device::pci_write(pci_bus_device *pcibus, int function, int offset, UINT32 data, UINT32 mem_mask) +{ + switch (function) + { + case 0: pci_isa_w(pcibus, offset, data, mem_mask); break; + case 1: pci_ide_w(pcibus, offset, data, mem_mask); break; + case 2: pci_usb_w(pcibus, offset, data, mem_mask); break; + } + //logerror("i82371sb_pci_write: write to undefined function %d\n", function); +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void i82371sb_device::device_start() +{ + southbridge_device::device_start(); + /* setup save states */ + save_item(NAME(m_regs)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void i82371sb_device::device_reset() +{ + southbridge_device::device_reset(); + + memset(m_regs, 0, sizeof(m_regs)); + + /* isa */ + m_regs[0][0x00] = 0x70008086; + m_regs[0][0x04] = 0x00000000; + m_regs[0][0x08] = 0x06010000; + m_regs[0][0x0c] = 0x00800000; + + /* ide */ + m_regs[1][0x00] = 0x70108086; + m_regs[1][0x04] = 0x02800000; + m_regs[1][0x08] = 0x01018000; + m_regs[1][0x0c] = 0x00000000; + + /* usb */ + m_regs[2][0x00] = 0x70208086; + m_regs[2][0x04] = 0x02800000; + m_regs[2][0x08] = 0x0c030000; + m_regs[2][0x0c] = 0x00000000; +} diff --git a/src/emu/bus/lpci/i82371sb.h b/src/emu/bus/lpci/i82371sb.h new file mode 100644 index 00000000000..c9ccbff9a8c --- /dev/null +++ b/src/emu/bus/lpci/i82371sb.h @@ -0,0 +1,48 @@ +/*************************************************************************** + + Intel 82371SB PCI IDE ISA Xcelerator (PIIX3) + + Part of the Intel 430TX chipset + +***************************************************************************/ + +#ifndef __I82371SB_H__ +#define __I82371SB_H__ + +#include "pci.h" +#include "southbridge.h" + +// ======================> i82371sb_device + +class i82371sb_device : public southbridge_device, + public pci_device_interface +{ +public: + // construction/destruction + i82371sb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + virtual UINT32 pci_read(pci_bus_device *pcibus, int function, int offset, UINT32 mem_mask); + virtual void pci_write(pci_bus_device *pcibus, int function, int offset, UINT32 data, UINT32 mem_mask); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + UINT32 pci_isa_r(device_t *busdevice, int offset, UINT32 mem_mask); + void pci_isa_w(device_t *busdevice, int offset, UINT32 data, UINT32 mem_mask); + + UINT32 pci_ide_r(device_t *busdevice, int offset, UINT32 mem_mask); + void pci_ide_w(device_t *busdevice, int offset, UINT32 data, UINT32 mem_mask); + + UINT32 pci_usb_r(device_t *busdevice, int offset, UINT32 mem_mask); + void pci_usb_w(device_t *busdevice, int offset, UINT32 data, UINT32 mem_mask); +private: + UINT32 m_regs[3][0x400/4]; +}; + +// device type definition +extern const device_type I82371SB; + + +#endif /* __I82371SB_H__ */ diff --git a/src/emu/bus/lpci/i82439tx.c b/src/emu/bus/lpci/i82439tx.c new file mode 100644 index 00000000000..daa612c70ac --- /dev/null +++ b/src/emu/bus/lpci/i82439tx.c @@ -0,0 +1,310 @@ +/*************************************************************************** + + Intel 82439TX System Controller (MTXC) + +***************************************************************************/ + +#include "emu.h" +#include "i82439tx.h" + +/*************************************************************************** + IMPLEMENTATION +***************************************************************************/ + +const device_type I82439TX = &device_creator<i82439tx_device>; + + +i82439tx_device::i82439tx_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : northbridge_device(mconfig, I82439TX, "Intel 82439TX", tag, owner, clock, "i82439tx", __FILE__), + pci_device_interface( mconfig, *this ), + m_cpu_tag( NULL ), + m_region_tag( NULL ) +{ +} + +void i82439tx_device::i82439tx_configure_memory(UINT8 val, offs_t begin, offs_t end) +{ + switch (val & 0x03) + { + case 0: + m_space->install_rom(begin, end, m_rom + (begin - 0xc0000)); + m_space->nop_write(begin, end); + break; + case 1: + m_space->install_rom(begin, end, m_bios_ram + (begin - 0xc0000) / 4); + m_space->nop_write(begin, end); + break; + case 2: + m_space->install_rom(begin, end, m_rom + (begin - 0xc0000)); + m_space->install_writeonly(begin, end, m_bios_ram + (begin - 0xc0000) / 4); + break; + case 3: + m_space->install_ram(begin, end, m_bios_ram + (begin - 0xc0000) / 4); + break; + } +} + + +/*************************************************************************** + PCI INTERFACE +***************************************************************************/ + +UINT32 i82439tx_device::pci_read(pci_bus_device *pcibus, int function, int offset, UINT32 mem_mask) +{ + UINT32 result = 0; + + if (function != 0) + return 0; + + switch(offset) + { + case 0x00: /* vendor/device ID */ + result = 0x71008086; + break; + + case 0x08: /* revision identification register and class code register*/ + result = 0x06000001; + break; + + case 0x04: /* PCI command register */ + case 0x0C: + case 0x10: /* reserved */ + case 0x14: /* reserved */ + case 0x18: /* reserved */ + case 0x1C: /* reserved */ + case 0x20: /* reserved */ + case 0x24: /* reserved */ + case 0x28: /* reserved */ + case 0x2C: /* reserved */ + case 0x30: /* reserved */ + case 0x34: /* reserved */ + case 0x38: /* reserved */ + case 0x3C: /* reserved */ + case 0x40: /* reserved */ + case 0x44: /* reserved */ + case 0x48: /* reserved */ + case 0x4C: /* reserved */ + case 0x50: + case 0x54: + case 0x58: + case 0x5C: + case 0x60: + case 0x64: + case 0x68: + case 0x6C: + case 0x70: + case 0x74: + case 0x78: + case 0x7C: + case 0x80: + case 0x84: + case 0x88: + case 0x8C: + case 0x90: + case 0x94: + case 0x98: + case 0x9C: + case 0xA0: + case 0xA4: + case 0xA8: + case 0xAC: + case 0xB0: + case 0xB4: + case 0xB8: + case 0xBC: + case 0xC0: + case 0xC4: + case 0xC8: + case 0xCC: + case 0xD0: + case 0xD4: + case 0xD8: + case 0xDC: + case 0xE0: + case 0xE4: + case 0xE8: + case 0xEC: + case 0xF0: + case 0xF4: + case 0xF8: + case 0xFC: + assert(((offset - 0x50) / 4) >= 0 && ((offset - 0x50) / 4) < ARRAY_LENGTH(m_regs)); + result = m_regs[(offset - 0x50) / 4]; + break; + + default: + fatalerror("i82439tx_pci_read(): Unexpected PCI read 0x%02X\n", offset); + } + return result; +} + +void i82439tx_device::pci_write(pci_bus_device *pcibus, int function, int offset, UINT32 data, UINT32 mem_mask) +{ + if (function != 0) + return; + + switch(offset) + { + case 0x00: /* vendor/device ID */ + case 0x10: /* reserved */ + case 0x14: /* reserved */ + case 0x18: /* reserved */ + case 0x1C: /* reserved */ + case 0x20: /* reserved */ + case 0x24: /* reserved */ + case 0x28: /* reserved */ + case 0x2C: /* reserved */ + case 0x30: /* reserved */ + case 0x3C: /* reserved */ + case 0x40: /* reserved */ + case 0x44: /* reserved */ + case 0x48: /* reserved */ + case 0x4C: /* reserved */ + /* read only */ + break; + + case 0x04: /* PCI command register */ + case 0x0C: + case 0x50: + case 0x54: + case 0x58: + case 0x5C: + case 0x60: + case 0x64: + case 0x68: + case 0x6C: + case 0x70: + case 0x74: + case 0x78: + case 0x7C: + case 0x80: + case 0x84: + case 0x88: + case 0x8C: + case 0x90: + case 0x94: + case 0x98: + case 0x9C: + case 0xA0: + case 0xA4: + case 0xA8: + case 0xAC: + case 0xB0: + case 0xB4: + case 0xB8: + case 0xBC: + case 0xC0: + case 0xC4: + case 0xC8: + case 0xCC: + case 0xD0: + case 0xD4: + case 0xD8: + case 0xDC: + case 0xE0: + case 0xE4: + case 0xE8: + case 0xEC: + case 0xF0: + case 0xF4: + case 0xF8: + case 0xFC: + switch(offset) + { + case 0x58: + if ((mem_mask & 0x0000f000)) + i82439tx_configure_memory(data >> 12, 0xf0000, 0xfffff); + if ((mem_mask & 0x000f0000)) + i82439tx_configure_memory(data >> 16, 0xc0000, 0xc3fff); + if ((mem_mask & 0x00f00000)) + i82439tx_configure_memory(data >> 20, 0xc4000, 0xc7fff); + if ((mem_mask & 0x0f000000)) + i82439tx_configure_memory(data >> 24, 0xc8000, 0xccfff); + if ((mem_mask & 0xf0000000)) + i82439tx_configure_memory(data >> 28, 0xcc000, 0xcffff); + break; + + case 0x5C: + if ((mem_mask & 0x0000000f)) + i82439tx_configure_memory(data >> 0, 0xd0000, 0xd3fff); + if ((mem_mask & 0x000000f0)) + i82439tx_configure_memory(data >> 4, 0xd4000, 0xd7fff); + if ((mem_mask & 0x00000f00)) + i82439tx_configure_memory(data >> 8, 0xd8000, 0xdbfff); + if ((mem_mask & 0x0000f000)) + i82439tx_configure_memory(data >> 12, 0xdc000, 0xdffff); + if ((mem_mask & 0x000f0000)) + i82439tx_configure_memory(data >> 16, 0xe0000, 0xe3fff); + if ((mem_mask & 0x00f00000)) + i82439tx_configure_memory(data >> 20, 0xe4000, 0xe7fff); + if ((mem_mask & 0x0f000000)) + i82439tx_configure_memory(data >> 24, 0xe8000, 0xecfff); + if ((mem_mask & 0xf0000000)) + i82439tx_configure_memory(data >> 28, 0xec000, 0xeffff); + break; + } + + assert(((offset - 0x50) / 4) >= 0 && ((offset - 0x50) / 4) < ARRAY_LENGTH(m_regs)); + COMBINE_DATA(&m_regs[(offset - 0x50) / 4]); + break; + + default: + fatalerror("i82439tx_pci_write(): Unexpected PCI write 0x%02X <-- 0x%08X\n", offset, data); + } +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void i82439tx_device::device_start() +{ + northbridge_device::device_start(); + /* get address space we are working on */ + device_t *cpu = machine().device(m_cpu_tag); + assert(cpu != NULL); + + m_space = &cpu->memory().space(AS_PROGRAM); + + /* get rom region */ + m_rom = machine().root_device().memregion(m_region_tag)->base(); + + /* setup save states */ + save_item(NAME(m_regs)); + save_item(NAME(m_bios_ram)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void i82439tx_device::device_reset() +{ + northbridge_device::device_reset(); + /* setup initial values */ + m_regs[0x00] = 0x14020000; + m_regs[0x01] = 0x01520000; + m_regs[0x02] = 0x00000000; + m_regs[0x03] = 0x00000000; + m_regs[0x04] = 0x02020202; + m_regs[0x05] = 0x00000002; + m_regs[0x06] = 0x00000000; + m_regs[0x07] = 0x00000000; + + memset(m_bios_ram, 0, sizeof(m_bios_ram)); + + /* configure initial memory state */ + i82439tx_configure_memory(0, 0xf0000, 0xfffff); + i82439tx_configure_memory(0, 0xc0000, 0xc3fff); + i82439tx_configure_memory(0, 0xc4000, 0xc7fff); + i82439tx_configure_memory(0, 0xc8000, 0xccfff); + i82439tx_configure_memory(0, 0xcc000, 0xcffff); + i82439tx_configure_memory(0, 0xd0000, 0xd3fff); + i82439tx_configure_memory(0, 0xd4000, 0xd7fff); + i82439tx_configure_memory(0, 0xd8000, 0xdbfff); + i82439tx_configure_memory(0, 0xdc000, 0xdffff); + i82439tx_configure_memory(0, 0xe0000, 0xe3fff); + i82439tx_configure_memory(0, 0xe4000, 0xe7fff); + i82439tx_configure_memory(0, 0xe8000, 0xecfff); + i82439tx_configure_memory(0, 0xec000, 0xeffff); +} diff --git a/src/emu/bus/lpci/i82439tx.h b/src/emu/bus/lpci/i82439tx.h new file mode 100644 index 00000000000..3e8d1514e49 --- /dev/null +++ b/src/emu/bus/lpci/i82439tx.h @@ -0,0 +1,57 @@ +/*************************************************************************** + + Intel 82439TX System Controller (MTXC) + + Part of the Intel 430TX chipset + +***************************************************************************/ + +#ifndef __I82439TX_H__ +#define __I82439TX_H__ + +#include "pci.h" +#include "northbridge.h" + +#define MCFG_I82439TX_CPU( _tag ) \ + i82439tx_device::static_set_cpu(*device, _tag); + +#define MCFG_I82439TX_REGION( _tag ) \ + i82439tx_device::static_set_region(*device, _tag); + +// ======================> i82439tx_device + +class i82439tx_device : public northbridge_device, + public pci_device_interface +{ +public: + // construction/destruction + i82439tx_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + static void static_set_cpu(device_t &device, const char *tag) { dynamic_cast<i82439tx_device &>(device).m_cpu_tag = tag; } + static void static_set_region(device_t &device, const char *tag) { dynamic_cast<i82439tx_device &>(device).m_region_tag = tag; } + + virtual UINT32 pci_read(pci_bus_device *pcibus, int function, int offset, UINT32 mem_mask); + virtual void pci_write(pci_bus_device *pcibus, int function, int offset, UINT32 data, UINT32 mem_mask); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + void i82439tx_configure_memory(UINT8 val, offs_t begin, offs_t end); + +private: + const char *m_cpu_tag; + const char *m_region_tag; + + address_space *m_space; + UINT8 *m_rom; + + UINT32 m_regs[8]; + UINT32 m_bios_ram[0x40000 / 4]; +}; + +// device type definition +extern const device_type I82439TX; + +#endif /* __I82439TX_H__ */ diff --git a/src/emu/bus/lpci/mpc105.c b/src/emu/bus/lpci/mpc105.c new file mode 100644 index 00000000000..57b448bd49d --- /dev/null +++ b/src/emu/bus/lpci/mpc105.c @@ -0,0 +1,231 @@ +/*************************************************************************** + + mpc105.h + + Motorola MPC105 PCI bridge + +***************************************************************************/ + +#include "emu.h" +#include "mpc105.h" +#include "machine/ram.h" + +#define LOG_MPC105 0 + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type MPC105 = &device_creator<mpc105_device>; + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// mpc105_device - constructor +//------------------------------------------------- + +mpc105_device::mpc105_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, MPC105, "MPC105", tag, owner, clock, "mpc105", __FILE__), + pci_device_interface( mconfig, *this ), + m_cpu_tag(NULL), + m_bank_base_default(0) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void mpc105_device::device_start() +{ + m_maincpu = machine().device<cpu_device>(m_cpu_tag); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void mpc105_device::device_reset() +{ + m_bank_base = m_bank_base_default; + m_bank_enable = 0; + memset(m_bank_registers,0,sizeof(m_bank_registers)); +} + +//------------------------------------------------- +// update_memory - MMU update +//------------------------------------------------- + +void mpc105_device::update_memory() +{ + int bank; + offs_t begin, end; + char bank_str[10]; + + if (LOG_MPC105) + logerror("mpc105_update_memory(machine): Updating memory (bank enable=0x%02X)\n", m_bank_enable); + + if (m_bank_base > 0) + { + address_space &space = m_maincpu->space(AS_PROGRAM); + + /* first clear everything out */ + space.nop_read(0x00000000, 0x3FFFFFFF); + space.nop_read(0x00000000, 0x3FFFFFFF); + } + + for (bank = 0; bank < MPC105_MEMORYBANK_COUNT; bank++) + { + if (m_bank_enable & (1 << bank)) + { + begin = (((m_bank_registers[(bank / 4) + 0] >> (bank % 4) * 8)) & 0xFF) << 20 + | (((m_bank_registers[(bank / 4) + 2] >> (bank % 4) * 8)) & 0x03) << 28; + + end = (((m_bank_registers[(bank / 4) + 4] >> (bank % 4) * 8)) & 0xFF) << 20 + | (((m_bank_registers[(bank / 4) + 6] >> (bank % 4) * 8)) & 0x03) << 28 + | 0x000FFFFF; + + end = MIN(end, begin + machine().device<ram_device>(RAM_TAG)->size() - 1); + + if ((begin + 0x100000) <= end) + { + if (LOG_MPC105) + logerror("\tbank #%d [%02d]: 0x%08X - 0x%08X [%p-%p]\n", bank, bank + m_bank_base, begin, end, machine().device<ram_device>(RAM_TAG)->pointer(), machine().device<ram_device>(RAM_TAG)->pointer() + (end - begin)); + + if (m_bank_base > 0) + { + sprintf(bank_str,"bank%d",bank + m_bank_base); + membank(bank_str)->set_base(machine().device<ram_device>(RAM_TAG)->pointer()); + } + } + } + } +} + +//------------------------------------------------- +// pci_read - implementation of PCI read +//------------------------------------------------- + +UINT32 mpc105_device::pci_read(pci_bus_device *pcibus, int function, int offset, UINT32 mem_mask) +{ + UINT32 result; + + if (function != 0) + return 0; + + switch(offset) + { + case 0x00: /* vendor/device ID */ + result = 0x00011057; + break; + + case 0x08: + result = 0x06000000; + break; + + case 0x80: /* memory starting address 1 */ + case 0x84: /* memory starting address 2 */ + case 0x88: /* extended memory starting address 1 */ + case 0x8C: /* extended memory starting address 2 */ + case 0x90: /* memory ending address 1 */ + case 0x94: /* memory ending address 2 */ + case 0x98: /* extended memory ending address 1 */ + case 0x9C: /* extended memory ending address 2 */ + result = m_bank_registers[(offset - 0x80) / 4]; + break; + + case 0xA0: /* memory enable */ + result = m_bank_enable; + break; + + case 0xA8: /* processor interface configuration 1 */ + /* TODO: Fix me! */ + switch(/*cpu_getactivecpu()*/0) + { + case 0: + result = 0xFF000010; + break; + + case 1: + result = 0xFF008010; + break; + + default: + fatalerror("Unknown CPU\n"); + } + break; + + case 0xAC: /* processor interface configuration 1 */ + result = 0x000C060C; + break; + + case 0xF0: /* memory control configuration 1 */ + result = 0xFF020000; + break; + case 0xF4: /* memory control configuration 2 */ + result = 0x00000003; + break; + case 0xF8: /* memory control configuration 3 */ + result = 0x00000000; + break; + case 0xFC: /* memory control configuration 4 */ + result = 0x00100000; + break; + + default: + result = 0; + break; + } + return result; +} + +//------------------------------------------------- +// pci_write - implementation of PCI write +//------------------------------------------------- + +void mpc105_device::pci_write(pci_bus_device *pcibus, int function, int offset, UINT32 data, UINT32 mem_mask) +{ + int i; + if (function != 0) + return; + + switch(offset) + { + case 0x80: /* memory starting address 1 */ + case 0x84: /* memory starting address 2 */ + case 0x88: /* extended memory starting address 1 */ + case 0x8C: /* extended memory starting address 2 */ + case 0x90: /* memory ending address 1 */ + case 0x94: /* memory ending address 2 */ + case 0x98: /* extended memory ending address 1 */ + case 0x9C: /* extended memory ending address 2 */ + i = (offset - 0x80) / 4; + if (m_bank_registers[i] != data) + { + m_bank_registers[i] = data; + update_memory(); + } + break; + + case 0xA0: /* memory enable */ + if (m_bank_enable != (UINT8) data) + { + m_bank_enable = (UINT8) data; + update_memory(); + } + break; + + case 0xF0: /* memory control configuration 1 */ + case 0xF4: /* memory control configuration 2 */ + case 0xF8: /* memory control configuration 3 */ + case 0xFC: /* memory control configuration 4 */ + break; + + case 0xA8: /* processor interface configuration 1 */ + //fatalerror("mpc105_pci_write(): Unexpected PCI write 0x%02X <-- 0x%08X\n", offset, data); + break; + } +} diff --git a/src/emu/bus/lpci/mpc105.h b/src/emu/bus/lpci/mpc105.h new file mode 100644 index 00000000000..ae3f4f2b1cc --- /dev/null +++ b/src/emu/bus/lpci/mpc105.h @@ -0,0 +1,58 @@ +/*************************************************************************** + + mpc105.h + + Motorola MPC105 PCI bridge + +***************************************************************************/ + +#ifndef MPC105_H +#define MPC105_H + +#include "pci.h" + +#define MPC105_MEMORYBANK_COUNT 8 + +#define MCFG_MPC105_CPU( _tag ) \ + mpc105_device::static_set_cpu(*device, _tag); + +#define MCFG_MPC105_BANK_BASE_DEFAULT( bank_base_default ) \ + mpc105_device::static_set_bank_base_default(*device, bank_base_default); + +// ======================> mpc105_device + +class mpc105_device : public device_t, + public pci_device_interface +{ +public: + // construction/destruction + mpc105_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + static void static_set_cpu(device_t &device, const char *tag) { dynamic_cast<mpc105_device &>(device).m_cpu_tag = tag; } + static void static_set_bank_base_default(device_t &device, int bank_base_default) { dynamic_cast<mpc105_device &>(device).m_bank_base_default = bank_base_default; } + + virtual UINT32 pci_read(pci_bus_device *pcibus, int function, int offset, UINT32 mem_mask); + virtual void pci_write(pci_bus_device *pcibus, int function, int offset, UINT32 data, UINT32 mem_mask); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + void update_memory(); + +private: + const char *m_cpu_tag; + int m_bank_base_default; + int m_bank_base; + UINT8 m_bank_enable; + UINT32 m_bank_registers[8]; + + cpu_device* m_maincpu; +}; + + +// device type definition +extern const device_type MPC105; + +#endif /* MPC105_H */ diff --git a/src/emu/bus/lpci/northbridge.c b/src/emu/bus/lpci/northbridge.c new file mode 100644 index 00000000000..83db12613b9 --- /dev/null +++ b/src/emu/bus/lpci/northbridge.c @@ -0,0 +1,46 @@ +/*************************************************************************** + + Northbridge implementation + +***************************************************************************/ + +#include "emu.h" +#include "northbridge.h" + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +northbridge_device::northbridge_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + m_maincpu(*this, ":maincpu"), + m_ram(*this, ":" RAM_TAG) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void northbridge_device::device_start() +{ + address_space& space = machine().device(":maincpu")->memory().space(AS_PROGRAM); + + machine().root_device().membank("bank10")->set_base(m_ram->pointer()); + + if (m_ram->size() > 0x0a0000) + { + 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); + } +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void northbridge_device::device_reset() +{ +} diff --git a/src/emu/bus/lpci/northbridge.h b/src/emu/bus/lpci/northbridge.h new file mode 100644 index 00000000000..1f0600deaaf --- /dev/null +++ b/src/emu/bus/lpci/northbridge.h @@ -0,0 +1,32 @@ +#pragma once + +#ifndef __NORTHBRIDGE_H__ +#define __NORTHBRIDGE_H__ + +#include "emu.h" + +#include "machine/ram.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> northbridge_device + +class northbridge_device : + public device_t +{ +public: + // construction/destruction + northbridge_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); +public: + required_device<cpu_device> m_maincpu; + required_device<ram_device> m_ram; + +}; + +#endif /* __NORTHBRIDGE_H__ */ diff --git a/src/emu/bus/lpci/pci.c b/src/emu/bus/lpci/pci.c new file mode 100644 index 00000000000..1f13b78dfe4 --- /dev/null +++ b/src/emu/bus/lpci/pci.c @@ -0,0 +1,332 @@ +/*************************************************************************** + + pci.c + + PCI bus + + The PCI bus is a 32-bit bus introduced by Intel, so it is little endian + + Control word: + bit 31: Enable bit + bits 30-24: Reserved + bits 23-16: PCI bus number + bits 15-11: PCI device number + bits 10- 8: PCI function number + bits 7- 0: Offset address + + Standard PCI registers: + 0x00 2 Vendor ID + 0x02 2 Device ID + 0x04 2 PCI Command + 0x06 2 PCI Status + 0x08 1 Revision ID + 0x09 1 Programming Interface + 0x0A 1 Subclass Code + 0x0B 1 Class Code + + Class Code/Subclass Code/Programming Interface + 0x00XXXX Pre-PCI 2.0 devices + 0x000000 Non-VGA device + 0x000101 VGA device + 0x01XXXX Storage Controller + 0x010000 SCSI + 0x0101XX IDE + 0x0102XX Floppy + 0x0103XX IPI + 0x0104XX RAID + 0x0180XX Other + 0x02XXXX Network Card + 0x020000 Ethernet + 0x020100 Tokenring + 0x020200 FDDI + 0x020300 ATM + 0x028000 Other + 0x03XXXX Display Controller + 0x030000 VGA + 0x030001 8514 Compatible + 0x030100 XGA + 0x038000 Other + 0x04XXXX Multimedia + 0x040000 Video + 0x040100 Audio + 0x048000 Other + 0x05XXXX Memory Controller + 0x050000 RAM + 0x050100 Flash + 0x058000 Other + 0x06XXXX Bridge + 0x060000 Host/PCI + 0x060100 PCI/ISA + 0x060200 PCI/EISA + 0x060300 PCI/Micro Channel + 0x060400 PCI/PCI + 0x060500 PCI/PCMCIA + 0x060600 PCI/NuBus + 0x060700 PCI/CardBus + 0x068000 Other + + Information on PCI vendors can be found at http://www.pcidatabase.com/ + +***************************************************************************/ + +#include "emu.h" +#include "pci.h" + +#define LOG_PCI 0 + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +const device_type PCI_BUS = &device_creator<pci_bus_device>; + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// pci_bus_device - constructor +//------------------------------------------------- +pci_bus_device::pci_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, PCI_BUS, "PCI Bus", tag, owner, clock, "pci_bus", __FILE__), + m_father(NULL) +{ + for (int i = 0; i < ARRAY_LENGTH(m_devtag); i++) { + m_devtag[i]= NULL; + } + m_siblings_count = 0; +} + +/*************************************************************************** + INLINE FUNCTIONS +***************************************************************************/ + +READ32_MEMBER( pci_bus_device::read ) +{ + UINT32 result = 0xffffffff; + int function, reg; + + offset %= 2; + + switch (offset) + { + case 0: + result = m_address; + break; + + case 1: + if (m_devicenum != -1) + { + if (m_busnumaddr->m_device[m_devicenum] != NULL) + { + function = (m_address >> 8) & 0x07; + reg = (m_address >> 0) & 0xfc; + result = m_busnumaddr->m_device[m_devicenum]->pci_read(m_busnumaddr, function, reg, mem_mask); + } + } + break; + } + + if (LOG_PCI) + logerror("read('%s'): offset=%d result=0x%08X\n", tag(), offset, result); + + return result; +} + + + +pci_bus_device *pci_bus_device::pci_search_bustree(int busnum, int devicenum, pci_bus_device *pcibus) +{ + int a; + pci_bus_device *ret; + + if (pcibus->m_busnum == busnum) + { + return pcibus; + } + for (a = 0; a < pcibus->m_siblings_count; a++) + { + ret = pci_search_bustree(busnum, devicenum, pcibus->m_siblings[a]); + if (ret != NULL) + return ret; + } + return NULL; +} + + + +WRITE32_MEMBER( pci_bus_device::write ) +{ + offset %= 2; + + if (LOG_PCI) + logerror("write('%s'): offset=%d data=0x%08X\n", tag(), offset, data); + + switch (offset) + { + case 0: + m_address = data; + + /* lookup current device */ + if (m_address & 0x80000000) + { + int busnum = (m_address >> 16) & 0xff; + int devicenum = (m_address >> 11) & 0x1f; + m_busnumaddr = pci_search_bustree(busnum, devicenum, this); + if (m_busnumaddr != NULL) + { + m_busnumber = busnum; + m_devicenum = devicenum; + } + else + m_devicenum = -1; + if (LOG_PCI) + logerror(" bus:%d device:%d\n", busnum, devicenum); + } + break; + + case 1: + if (m_devicenum != -1) + { + if (m_busnumaddr->m_device[m_devicenum] != NULL) + { + int function = (m_address >> 8) & 0x07; + int reg = (m_address >> 0) & 0xfc; + m_busnumaddr->m_device[m_devicenum]->pci_write(m_busnumaddr, function, reg, data, mem_mask); + } + if (LOG_PCI) + logerror(" function:%d register:%d\n", (m_address >> 8) & 0x07, (m_address >> 0) & 0xfc); + } + break; + } +} + + + +READ64_MEMBER(pci_bus_device::read_64be) +{ + UINT64 result = 0; + mem_mask = FLIPENDIAN_INT64(mem_mask); + if (ACCESSING_BITS_0_31) + result |= (UINT64)read(space, offset * 2 + 0, mem_mask >> 0) << 0; + if (ACCESSING_BITS_32_63) + result |= (UINT64)read(space, offset * 2 + 1, mem_mask >> 32) << 32; + return FLIPENDIAN_INT64(result); +} + +WRITE64_MEMBER(pci_bus_device::write_64be) +{ + data = FLIPENDIAN_INT64(data); + mem_mask = FLIPENDIAN_INT64(mem_mask); + if (ACCESSING_BITS_0_31) + write(space, offset * 2 + 0, data >> 0, mem_mask >> 0); + if (ACCESSING_BITS_32_63) + write(space, offset * 2 + 1, data >> 32, mem_mask >> 32); +} + + +void pci_bus_device::add_sibling(pci_bus_device *sibling, int busnum) +{ + m_siblings[m_siblings_count] = sibling; + m_siblings_busnum[m_siblings_count] = busnum; + m_siblings_count++; +} + + +//------------------------------------------------- +// device_post_load - handle updating after a +// restore +//------------------------------------------------- + +void pci_bus_device::device_post_load() +{ + if (m_devicenum != -1) + { + m_busnumaddr = pci_search_bustree(m_busnumber, m_devicenum, this); + } +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void pci_bus_device::device_start() +{ + /* store a pointer back to the device */ + m_devicenum = -1; + + char id[3]; + /* find all our devices */ + for (int i = 0; i < ARRAY_LENGTH(m_devtag); i++) + { + sprintf(id, "%d", i); + pci_connector *conn = downcast<pci_connector *>(subdevice(id)); + if (conn!=NULL) + m_device[i] = conn->get_device(); + else + m_device[i] = NULL; + } + + if (m_father != NULL) { + pci_bus_device *father = machine().device<pci_bus_device>(m_father); + if (father) + father->add_sibling(this, m_busnum); + } + + /* register pci states */ + save_item(NAME(m_address)); + save_item(NAME(m_devicenum)); + save_item(NAME(m_busnum)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void pci_bus_device::device_reset() +{ + /* reset the drive state */ + m_devicenum = -1; + m_address = 0; +} + +//------------------------------------------------- +// pci_device_interface - constructor +//------------------------------------------------- + +pci_device_interface::pci_device_interface(const machine_config &mconfig, device_t &device) + : device_slot_card_interface(mconfig, device) +{ +} + +//------------------------------------------------- +// ~pci_device_interface - destructor +//------------------------------------------------- + +pci_device_interface::~pci_device_interface() +{ +} + + +const device_type PCI_CONNECTOR = &device_creator<pci_connector>; + + +pci_connector::pci_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, PCI_CONNECTOR, "PCI device connector abstraction", tag, owner, clock, "pci_connector", __FILE__), + device_slot_interface(mconfig, *this) +{ +} + +pci_connector::~pci_connector() +{ +} + +void pci_connector::device_start() +{ +} + +pci_device_interface *pci_connector::get_device() +{ + return dynamic_cast<pci_device_interface *>(get_card_device()); +} diff --git a/src/emu/bus/lpci/pci.h b/src/emu/bus/lpci/pci.h new file mode 100644 index 00000000000..97d7b45d988 --- /dev/null +++ b/src/emu/bus/lpci/pci.h @@ -0,0 +1,110 @@ +/*************************************************************************** + + pci.h + + PCI bus + +***************************************************************************/ + +#ifndef PCI_H +#define PCI_H + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** +class pci_bus_device; + +// ======================> pci_device_interface + +class pci_device_interface : public device_slot_card_interface +{ +public: + // construction/destruction + pci_device_interface(const machine_config &mconfig, device_t &device); + virtual ~pci_device_interface(); + + virtual UINT32 pci_read(pci_bus_device *pcibus, int function, int offset, UINT32 mem_mask) = 0; + virtual void pci_write(pci_bus_device *pcibus, int function, int offset, UINT32 data, UINT32 mem_mask) = 0; +private: +}; + +class pci_connector: public device_t, + public device_slot_interface +{ +public: + pci_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual ~pci_connector(); + + pci_device_interface *get_device(); + +protected: + virtual void device_start(); +}; + +extern const device_type PCI_CONNECTOR; + +// ======================> pci_bus_device + +class pci_bus_device : public device_t +{ +public: + // construction/destruction + pci_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + DECLARE_READ32_MEMBER( read ); + DECLARE_WRITE32_MEMBER( write ); + + DECLARE_READ64_MEMBER( read_64be ); + DECLARE_WRITE64_MEMBER( write_64be ); + + void set_busnum(int busnum) { m_busnum = busnum; } + void set_father(const char *father) { m_father = father; } + void set_device(int num, const char *tag) { + m_devtag[num] = tag; } + + pci_bus_device *pci_search_bustree(int busnum, int devicenum, pci_bus_device *pcibus); + void add_sibling(pci_bus_device *sibling, int busnum); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual void device_post_load(); + +private: + UINT8 m_busnum; + + const char * m_devtag[32]; + pci_device_interface *m_device[32]; + + const char * m_father; + pci_bus_device * m_siblings[8]; + UINT8 m_siblings_busnum[8]; + int m_siblings_count; + + offs_t m_address; + INT8 m_devicenum; // device number we are addressing + INT8 m_busnumber; // pci bus number we are addressing + pci_bus_device * m_busnumaddr; // pci bus we are addressing +}; + +// device type definition +extern const device_type PCI_BUS; + + +/*************************************************************************** + DEVICE CONFIGURATION MACROS +***************************************************************************/ + +#define MCFG_PCI_BUS_ADD(_tag, _busnum) \ + MCFG_DEVICE_ADD(_tag, PCI_BUS, 0) \ + downcast<pci_bus_device *>(device)->set_busnum(_busnum); +#define MCFG_PCI_BUS_DEVICE(_tag, _slot_intf, _def_slot, _fixed) \ + MCFG_DEVICE_ADD(_tag, PCI_CONNECTOR, 0) \ + MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, _fixed) + +#define MCFG_PCI_BUS_SIBLING(_father_tag) \ + downcast<pci_bus_device *>(device)->set_father(_father_tag); + + +#endif /* PCI_H */ diff --git a/src/emu/bus/lpci/southbridge.c b/src/emu/bus/lpci/southbridge.c new file mode 100644 index 00000000000..d6797fdef06 --- /dev/null +++ b/src/emu/bus/lpci/southbridge.c @@ -0,0 +1,488 @@ +/*************************************************************************** + + Southbridge implementation + +***************************************************************************/ + +#include "emu.h" +#include "cpu/i386/i386.h" +#include "southbridge.h" +#include "bus/pc_kbd/keyboards.h" + + +static SLOT_INTERFACE_START(pc_isa_onboard) + SLOT_INTERFACE("comat", ISA8_COM_AT) + SLOT_INTERFACE("lpt", ISA8_LPT) + SLOT_INTERFACE("fdcsmc", ISA8_FDC_SMC) +SLOT_INTERFACE_END + +static MACHINE_CONFIG_FRAGMENT( southbridge ) + MCFG_DEVICE_ADD("pit8254", PIT8254, 0) + MCFG_PIT8253_CLK0(4772720/4) /* heartbeat IRQ */ + MCFG_PIT8253_OUT0_HANDLER(WRITELINE(southbridge_device, at_pit8254_out0_changed)) + MCFG_PIT8253_CLK1(4772720/4) /* dram refresh */ + MCFG_PIT8253_OUT1_HANDLER(WRITELINE(southbridge_device, at_pit8254_out1_changed)) + MCFG_PIT8253_CLK2(4772720/4) /* pio port c pin 4, and speaker polling enough */ + MCFG_PIT8253_OUT2_HANDLER(WRITELINE(southbridge_device, at_pit8254_out2_changed)) + + MCFG_DEVICE_ADD( "dma8237_1", AM9517A, XTAL_14_31818MHz/3 ) + MCFG_I8237_OUT_HREQ_CB(DEVWRITELINE("dma8237_2", am9517a_device, dreq0_w)) + MCFG_I8237_OUT_EOP_CB(WRITELINE(southbridge_device, at_dma8237_out_eop)) + MCFG_I8237_IN_MEMR_CB(READ8(southbridge_device, pc_dma_read_byte)) + MCFG_I8237_OUT_MEMW_CB(WRITE8(southbridge_device, pc_dma_write_byte)) + MCFG_I8237_IN_IOR_0_CB(READ8(southbridge_device, pc_dma8237_0_dack_r)) + MCFG_I8237_IN_IOR_1_CB(READ8(southbridge_device, pc_dma8237_1_dack_r)) + MCFG_I8237_IN_IOR_2_CB(READ8(southbridge_device, pc_dma8237_2_dack_r)) + MCFG_I8237_IN_IOR_3_CB(READ8(southbridge_device, pc_dma8237_3_dack_r)) + MCFG_I8237_OUT_IOW_0_CB(WRITE8(southbridge_device, pc_dma8237_0_dack_w)) + MCFG_I8237_OUT_IOW_1_CB(WRITE8(southbridge_device, pc_dma8237_1_dack_w)) + MCFG_I8237_OUT_IOW_2_CB(WRITE8(southbridge_device, pc_dma8237_2_dack_w)) + MCFG_I8237_OUT_IOW_3_CB(WRITE8(southbridge_device, pc_dma8237_3_dack_w)) + MCFG_I8237_OUT_DACK_0_CB(WRITELINE(southbridge_device, pc_dack0_w)) + MCFG_I8237_OUT_DACK_1_CB(WRITELINE(southbridge_device, pc_dack1_w)) + MCFG_I8237_OUT_DACK_2_CB(WRITELINE(southbridge_device, pc_dack2_w)) + MCFG_I8237_OUT_DACK_3_CB(WRITELINE(southbridge_device, pc_dack3_w)) + + MCFG_DEVICE_ADD( "dma8237_2", AM9517A, XTAL_14_31818MHz/3 ) + MCFG_I8237_OUT_HREQ_CB(WRITELINE(southbridge_device, pc_dma_hrq_changed)) + MCFG_I8237_IN_MEMR_CB(READ8(southbridge_device, pc_dma_read_word)) + MCFG_I8237_OUT_MEMW_CB(WRITE8(southbridge_device, pc_dma_write_word)) + MCFG_I8237_IN_IOR_1_CB(READ8(southbridge_device, pc_dma8237_5_dack_r)) + MCFG_I8237_IN_IOR_2_CB(READ8(southbridge_device, pc_dma8237_6_dack_r)) + MCFG_I8237_IN_IOR_3_CB(READ8(southbridge_device, pc_dma8237_7_dack_r)) + MCFG_I8237_OUT_IOW_1_CB(WRITE8(southbridge_device, pc_dma8237_5_dack_w)) + MCFG_I8237_OUT_IOW_2_CB(WRITE8(southbridge_device, pc_dma8237_6_dack_w)) + MCFG_I8237_OUT_IOW_3_CB(WRITE8(southbridge_device, pc_dma8237_7_dack_w)) + MCFG_I8237_OUT_DACK_0_CB(WRITELINE(southbridge_device, pc_dack4_w)) + MCFG_I8237_OUT_DACK_1_CB(WRITELINE(southbridge_device, pc_dack5_w)) + MCFG_I8237_OUT_DACK_2_CB(WRITELINE(southbridge_device, pc_dack6_w)) + MCFG_I8237_OUT_DACK_3_CB(WRITELINE(southbridge_device, pc_dack7_w)) + + MCFG_PIC8259_ADD( "pic8259_master", INPUTLINE(":maincpu", 0), VCC, READ8(southbridge_device, get_slave_ack) ) + MCFG_PIC8259_ADD( "pic8259_slave", DEVWRITELINE("pic8259_master", pic8259_device, ir2_w), GND, NULL ) + + MCFG_DEVICE_ADD("keybc", AT_KEYBOARD_CONTROLLER, XTAL_12MHz) + MCFG_AT_KEYBOARD_CONTROLLER_SYSTEM_RESET_CB(INPUTLINE(":maincpu", INPUT_LINE_RESET)) + MCFG_AT_KEYBOARD_CONTROLLER_GATE_A20_CB(INPUTLINE(":maincpu", INPUT_LINE_A20)) + MCFG_AT_KEYBOARD_CONTROLLER_INPUT_BUFFER_FULL_CB(DEVWRITELINE("pic8259_master", pic8259_device, ir1_w)) + MCFG_AT_KEYBOARD_CONTROLLER_KEYBOARD_CLOCK_CB(DEVWRITELINE("pc_kbdc", pc_kbdc_device, clock_write_from_mb)) + MCFG_AT_KEYBOARD_CONTROLLER_KEYBOARD_DATA_CB(DEVWRITELINE("pc_kbdc", pc_kbdc_device, data_write_from_mb)) + MCFG_DEVICE_ADD("pc_kbdc", PC_KBDC, 0) + MCFG_PC_KBDC_OUT_CLOCK_CB(DEVWRITELINE("keybc", at_keyboard_controller_device, keyboard_clock_w)) + MCFG_PC_KBDC_OUT_DATA_CB(DEVWRITELINE("keybc", at_keyboard_controller_device, keyboard_data_w)) + MCFG_PC_KBDC_SLOT_ADD("pc_kbdc", "kbd", pc_at_keyboards, STR_KBD_MICROSOFT_NATURAL) + + MCFG_DS12885_ADD("rtc") + MCFG_MC146818_IRQ_HANDLER(DEVWRITELINE("pic8259_slave", pic8259_device, ir0_w)) + MCFG_MC146818_CENTURY_INDEX(0x32) + + MCFG_BUS_MASTER_IDE_CONTROLLER_ADD("ide", ata_devices, "hdd", NULL, false) + MCFG_ATA_INTERFACE_IRQ_HANDLER(DEVWRITELINE("pic8259_slave", pic8259_device, ir6_w)) + MCFG_BUS_MASTER_IDE_CONTROLLER_SPACE(":maincpu", AS_PROGRAM) + + MCFG_BUS_MASTER_IDE_CONTROLLER_ADD("ide2", ata_devices, "cdrom", NULL, false) + MCFG_ATA_INTERFACE_IRQ_HANDLER(DEVWRITELINE("pic8259_slave", pic8259_device, ir7_w)) + MCFG_BUS_MASTER_IDE_CONTROLLER_SPACE(":maincpu", AS_PROGRAM) + + /* sound hardware */ + MCFG_SPEAKER_STANDARD_MONO("mono") + MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) + + MCFG_DEVICE_ADD("isabus", ISA16, 0) + MCFG_ISA16_CPU(":maincpu") + MCFG_ISA_OUT_IRQ2_CB(DEVWRITELINE("pic8259_slave", pic8259_device, ir2_w)) // in place of irq 2 on at irq 9 is used + MCFG_ISA_OUT_IRQ3_CB(DEVWRITELINE("pic8259_master", pic8259_device, ir3_w)) + MCFG_ISA_OUT_IRQ4_CB(DEVWRITELINE("pic8259_master", pic8259_device, ir4_w)) + MCFG_ISA_OUT_IRQ5_CB(DEVWRITELINE("pic8259_master", pic8259_device, ir5_w)) + MCFG_ISA_OUT_IRQ6_CB(DEVWRITELINE("pic8259_master", pic8259_device, ir6_w)) + MCFG_ISA_OUT_IRQ7_CB(DEVWRITELINE("pic8259_master", pic8259_device, ir7_w)) + MCFG_ISA_OUT_IRQ10_CB(DEVWRITELINE("pic8259_slave", pic8259_device, ir3_w)) + MCFG_ISA_OUT_IRQ11_CB(DEVWRITELINE("pic8259_slave", pic8259_device, ir4_w)) + MCFG_ISA_OUT_IRQ12_CB(DEVWRITELINE("pic8259_slave", pic8259_device, ir5_w)) + MCFG_ISA_OUT_IRQ14_CB(DEVWRITELINE("pic8259_slave", pic8259_device, ir6_w)) + MCFG_ISA_OUT_IRQ15_CB(DEVWRITELINE("pic8259_slave", pic8259_device, ir7_w)) + MCFG_ISA_OUT_DRQ0_CB(DEVWRITELINE("dma8237_1", am9517a_device, dreq0_w)) + MCFG_ISA_OUT_DRQ1_CB(DEVWRITELINE("dma8237_1", am9517a_device, dreq1_w)) + MCFG_ISA_OUT_DRQ2_CB(DEVWRITELINE("dma8237_1", am9517a_device, dreq2_w)) + MCFG_ISA_OUT_DRQ3_CB(DEVWRITELINE("dma8237_1", am9517a_device, dreq3_w)) + MCFG_ISA_OUT_DRQ5_CB(DEVWRITELINE("dma8237_2", am9517a_device, dreq1_w)) + MCFG_ISA_OUT_DRQ6_CB(DEVWRITELINE("dma8237_2", am9517a_device, dreq2_w)) + MCFG_ISA_OUT_DRQ7_CB(DEVWRITELINE("dma8237_2", am9517a_device, dreq3_w)) + // on board devices + MCFG_ISA16_SLOT_ADD("isabus","board1", pc_isa_onboard, "fdcsmc", true) + MCFG_ISA16_SLOT_ADD("isabus","board2", pc_isa_onboard, "comat", true) + MCFG_ISA16_SLOT_ADD("isabus","board3", pc_isa_onboard, "lpt", true) +MACHINE_CONFIG_END + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +machine_config_constructor southbridge_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( southbridge ); +} + +southbridge_device::southbridge_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + m_maincpu(*this, ":maincpu"), + m_pic8259_master(*this, "pic8259_master"), + m_pic8259_slave(*this, "pic8259_slave"), + m_dma8237_1(*this, "dma8237_1"), + m_dma8237_2(*this, "dma8237_2"), + m_pit8254(*this, "pit8254"), + m_keybc(*this, "keybc"), + m_isabus(*this, "isabus"), + m_speaker(*this, "speaker"), + m_ds12885(*this, "rtc"), + m_pc_kbdc(*this, "pc_kbdc"), + m_ide(*this, "ide"), + m_ide2(*this, "ide2") +{ +} +/********************************************************** + * + * Init functions + * + **********************************************************/ + +/// 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) +{ + return m_ide->read_cs1(space, 1, (UINT32) 0xff0000) >> 16; +} + +WRITE8_MEMBER(southbridge_device::ide_write_cs1_w) +{ + m_ide->write_cs1(space, 1, (UINT32) data << 16, (UINT32) 0xff0000); +} + +READ8_MEMBER(southbridge_device::ide2_read_cs1_r) +{ + return m_ide2->read_cs1(space, 1, (UINT32) 0xff0000) >> 16; +} + +WRITE8_MEMBER(southbridge_device::ide2_write_cs1_w) +{ + m_ide2->write_cs1(space, 1, (UINT32) data << 16, (UINT32) 0xff0000); +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void southbridge_device::device_start() +{ + address_space& 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_keybc_r),this), write8_delegate(FUNC(southbridge_device::at_keybc_w),this), 0xffffffff); + spaceio.install_readwrite_handler(0x0064, 0x0067, read8_delegate(FUNC(at_keyboard_controller_device::status_r),&(*m_keybc)), write8_delegate(FUNC(at_keyboard_controller_device::command_w),&(*m_keybc)), 0xffffffff); + spaceio.install_readwrite_handler(0x0070, 0x007f, read8_delegate(FUNC(ds12885_device::read),&(*m_ds12885)), write8_delegate(FUNC(ds12885_device::write),&(*m_ds12885)), 0xffffffff); + 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); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void southbridge_device::device_reset() +{ + m_at_spkrdata = 0; + m_pit_out2 = 0; + m_dma_channel = -1; + m_cur_eop = false; + m_nmi_enabled = 0; + m_refresh = false; +} + + +/************************************************************* + * + * pic8259 configuration + * + *************************************************************/ +READ8_MEMBER( southbridge_device::get_slave_ack ) +{ + if (offset==2) // IRQ = 2 + return m_pic8259_slave->acknowledge(); + + return 0x00; +} + +/************************************************************************* + * + * PC Speaker related + * + *************************************************************************/ + +void southbridge_device::at_speaker_set_spkrdata(UINT8 data) +{ + m_at_spkrdata = data ? 1 : 0; + m_speaker->level_w(m_at_spkrdata & m_pit_out2); +} + + + +/************************************************************* + * + * pit8254 configuration + * + *************************************************************/ + +WRITE_LINE_MEMBER( southbridge_device::at_pit8254_out0_changed ) +{ + if (m_pic8259_master) + m_pic8259_master->ir0_w(state); +} + +WRITE_LINE_MEMBER( southbridge_device::at_pit8254_out1_changed ) +{ + if(state) + m_refresh = !m_refresh; +} + +WRITE_LINE_MEMBER( southbridge_device::at_pit8254_out2_changed ) +{ + m_pit_out2 = state ? 1 : 0; + m_speaker->level_w(m_at_spkrdata & m_pit_out2); +} + +/************************************************************************* + * + * PC DMA stuff + * + *************************************************************************/ + +READ8_MEMBER( southbridge_device::at_page8_r ) +{ + UINT8 data = m_at_pages[offset % 0x10]; + + switch(offset % 8) + { + case 1: + data = m_dma_offset[BIT(offset, 3)][2]; + break; + case 2: + data = m_dma_offset[BIT(offset, 3)][3]; + break; + case 3: + data = m_dma_offset[BIT(offset, 3)][1]; + break; + case 7: + data = m_dma_offset[BIT(offset, 3)][0]; + break; + } + return data; +} + + +WRITE8_MEMBER( southbridge_device::at_page8_w ) +{ + m_at_pages[offset % 0x10] = data; + + switch(offset % 8) + { + case 1: + m_dma_offset[BIT(offset, 3)][2] = data; + break; + case 2: + m_dma_offset[BIT(offset, 3)][3] = data; + break; + case 3: + m_dma_offset[BIT(offset, 3)][1] = data; + break; + case 7: + m_dma_offset[BIT(offset, 3)][0] = data; + break; + } +} + + +WRITE_LINE_MEMBER( southbridge_device::pc_dma_hrq_changed ) +{ + m_maincpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE); + + /* Assert HLDA */ + m_dma8237_2->hack_w( state ); +} + +READ8_MEMBER(southbridge_device::pc_dma_read_byte) +{ + address_space& prog_space = m_maincpu->space(AS_PROGRAM); // get the right address space + if(m_dma_channel == -1) + return 0xff; + UINT8 result; + offs_t page_offset = (((offs_t) m_dma_offset[0][m_dma_channel]) << 16) & 0xFF0000; + + result = prog_space.read_byte(page_offset + offset); + return result; +} + + +WRITE8_MEMBER(southbridge_device::pc_dma_write_byte) +{ + address_space& prog_space = m_maincpu->space(AS_PROGRAM); // get the right address space + if(m_dma_channel == -1) + return; + offs_t page_offset = (((offs_t) m_dma_offset[0][m_dma_channel]) << 16) & 0xFF0000; + + prog_space.write_byte(page_offset + offset, data); +} + + +READ8_MEMBER(southbridge_device::pc_dma_read_word) +{ + address_space& prog_space = m_maincpu->space(AS_PROGRAM); // get the right address space + if(m_dma_channel == -1) + return 0xff; + UINT16 result; + offs_t page_offset = (((offs_t) m_dma_offset[1][m_dma_channel & 3]) << 16) & 0xFE0000; + + result = prog_space.read_word(page_offset + ( offset << 1 ) ); + m_dma_high_byte = result & 0xFF00; + + return result & 0xFF; +} + + +WRITE8_MEMBER(southbridge_device::pc_dma_write_word) +{ + address_space& prog_space = m_maincpu->space(AS_PROGRAM); // get the right address space + if(m_dma_channel == -1) + return; + offs_t page_offset = (((offs_t) m_dma_offset[1][m_dma_channel & 3]) << 16) & 0xFE0000; + + prog_space.write_word(page_offset + ( offset << 1 ), m_dma_high_byte | data); +} + + +READ8_MEMBER( southbridge_device::pc_dma8237_0_dack_r ) { return m_isabus->dack_r(0); } +READ8_MEMBER( southbridge_device::pc_dma8237_1_dack_r ) { return m_isabus->dack_r(1); } +READ8_MEMBER( southbridge_device::pc_dma8237_2_dack_r ) { return m_isabus->dack_r(2); } +READ8_MEMBER( southbridge_device::pc_dma8237_3_dack_r ) { return m_isabus->dack_r(3); } +READ8_MEMBER( southbridge_device::pc_dma8237_5_dack_r ) { return m_isabus->dack_r(5); } +READ8_MEMBER( southbridge_device::pc_dma8237_6_dack_r ) { return m_isabus->dack_r(6); } +READ8_MEMBER( southbridge_device::pc_dma8237_7_dack_r ) { return m_isabus->dack_r(7); } + + +WRITE8_MEMBER( southbridge_device::pc_dma8237_0_dack_w ){ m_isabus->dack_w(0, data); } +WRITE8_MEMBER( southbridge_device::pc_dma8237_1_dack_w ){ m_isabus->dack_w(1, data); } +WRITE8_MEMBER( southbridge_device::pc_dma8237_2_dack_w ){ m_isabus->dack_w(2, data); } +WRITE8_MEMBER( southbridge_device::pc_dma8237_3_dack_w ){ m_isabus->dack_w(3, data); } +WRITE8_MEMBER( southbridge_device::pc_dma8237_5_dack_w ){ m_isabus->dack_w(5, data); } +WRITE8_MEMBER( southbridge_device::pc_dma8237_6_dack_w ){ m_isabus->dack_w(6, data); } +WRITE8_MEMBER( southbridge_device::pc_dma8237_7_dack_w ){ m_isabus->dack_w(7, data); } + +WRITE_LINE_MEMBER( southbridge_device::at_dma8237_out_eop ) +{ + m_cur_eop = state == ASSERT_LINE; + if(m_dma_channel != -1) + m_isabus->eop_w(m_dma_channel, m_cur_eop ? ASSERT_LINE : CLEAR_LINE ); +} + +void southbridge_device::pc_select_dma_channel(int channel, bool state) +{ + if(!state) { + m_dma_channel = channel; + if(m_cur_eop) + m_isabus->eop_w(channel, ASSERT_LINE ); + + } else if(m_dma_channel == channel) { + m_dma_channel = -1; + if(m_cur_eop) + m_isabus->eop_w(channel, CLEAR_LINE ); + } +} + + +WRITE_LINE_MEMBER( southbridge_device::pc_dack0_w ) { pc_select_dma_channel(0, state); } +WRITE_LINE_MEMBER( southbridge_device::pc_dack1_w ) { pc_select_dma_channel(1, state); } +WRITE_LINE_MEMBER( southbridge_device::pc_dack2_w ) { pc_select_dma_channel(2, state); } +WRITE_LINE_MEMBER( southbridge_device::pc_dack3_w ) { pc_select_dma_channel(3, state); } +WRITE_LINE_MEMBER( southbridge_device::pc_dack4_w ) { m_dma8237_1->hack_w( state ? 0 : 1); } // it's inverted +WRITE_LINE_MEMBER( southbridge_device::pc_dack5_w ) { pc_select_dma_channel(5, state); } +WRITE_LINE_MEMBER( southbridge_device::pc_dack6_w ) { pc_select_dma_channel(6, state); } +WRITE_LINE_MEMBER( southbridge_device::pc_dack7_w ) { pc_select_dma_channel(7, state); } + +READ8_MEMBER( southbridge_device::at_portb_r ) +{ + UINT8 data = m_at_speaker; + data &= ~0xd0; /* AT BIOS don't likes this being set */ + + /* 0x10 is the dram refresh line bit on the 5170, just a timer here, 15.085us. */ + data |= m_refresh ? 0x10 : 0; + + if (m_pit_out2) + data |= 0x20; + else + data &= ~0x20; /* ps2m30 wants this */ + + return data; +} + +WRITE8_MEMBER( southbridge_device::at_portb_w ) +{ + m_at_speaker = data; + m_pit8254->write_gate2(BIT(data, 0)); + at_speaker_set_spkrdata( BIT(data, 1)); + m_channel_check = BIT(data, 3); + m_isabus->set_nmi_state((m_nmi_enabled==0) && (m_channel_check==0)); +} + +READ8_MEMBER( southbridge_device::at_dma8237_2_r ) +{ + return m_dma8237_2->read( space, offset / 2); +} + +WRITE8_MEMBER( southbridge_device::at_dma8237_2_w ) +{ + m_dma8237_2->write( space, offset / 2, data); +} + +READ8_MEMBER( southbridge_device::at_keybc_r ) +{ + switch (offset) + { + case 0: return m_keybc->data_r(space, 0); + case 1: return at_portb_r(space, 0); + } + + return 0xff; +} + +WRITE8_MEMBER( southbridge_device::at_keybc_w ) +{ + switch (offset) + { + case 0: m_keybc->data_w(space, 0, data); break; + case 1: at_portb_w(space, 0, data); break; + } +} + + +WRITE8_MEMBER( southbridge_device::write_rtc ) +{ + if (offset==0) { + m_nmi_enabled = BIT(data,7); + m_isabus->set_nmi_state((m_nmi_enabled==0) && (m_channel_check==0)); + m_ds12885->write(space,0,data); + } + else { + m_ds12885->write(space,offset,data); + } +} diff --git a/src/emu/bus/lpci/southbridge.h b/src/emu/bus/lpci/southbridge.h new file mode 100644 index 00000000000..1fde011f414 --- /dev/null +++ b/src/emu/bus/lpci/southbridge.h @@ -0,0 +1,129 @@ +#pragma once + +#ifndef __SOUTHBRIDGE_H__ +#define __SOUTHBRIDGE_H__ + +#include "emu.h" + +#include "machine/ins8250.h" +#include "machine/ds128x.h" +#include "machine/pic8259.h" +#include "machine/pit8253.h" + +#include "machine/ataintf.h" +#include "machine/at_keybc.h" + +#include "imagedev/harddriv.h" +#include "pci.h" + +#include "sound/dac.h" +#include "sound/speaker.h" +#include "machine/ram.h" +#include "machine/nvram.h" +#include "bus/isa/isa.h" +#include "bus/isa/isa_cards.h" + +#include "machine/pc_lpt.h" +#include "bus/pc_kbd/pc_kbdc.h" + +#include "machine/am9517a.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> southbridge_device + +class southbridge_device : + public device_t +{ +public: + // construction/destruction + southbridge_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + + // optional information overrides + virtual machine_config_constructor device_mconfig_additions() const; + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); +public: + + required_device<cpu_device> m_maincpu; + required_device<pic8259_device> m_pic8259_master; + required_device<pic8259_device> m_pic8259_slave; + required_device<am9517a_device> m_dma8237_1; + required_device<am9517a_device> m_dma8237_2; + required_device<pit8254_device> m_pit8254; + required_device<at_keyboard_controller_device> m_keybc; + required_device<isa16_device> m_isabus; + required_device<speaker_sound_device> m_speaker; + required_device<ds12885_device> m_ds12885; + required_device<pc_kbdc_device> m_pc_kbdc; + required_device<bus_master_ide_controller_device> m_ide; + required_device<bus_master_ide_controller_device> m_ide2; + DECLARE_READ8_MEMBER(at_page8_r); + DECLARE_WRITE8_MEMBER(at_page8_w); + DECLARE_READ8_MEMBER(at_portb_r); + DECLARE_WRITE8_MEMBER(at_portb_w); + DECLARE_READ8_MEMBER(get_slave_ack); + DECLARE_WRITE_LINE_MEMBER(at_pit8254_out0_changed); + DECLARE_WRITE_LINE_MEMBER(at_pit8254_out1_changed); + DECLARE_WRITE_LINE_MEMBER(at_pit8254_out2_changed); + DECLARE_WRITE_LINE_MEMBER(pc_dma_hrq_changed); + DECLARE_READ8_MEMBER(pc_dma8237_0_dack_r); + DECLARE_READ8_MEMBER(pc_dma8237_1_dack_r); + DECLARE_READ8_MEMBER(pc_dma8237_2_dack_r); + DECLARE_READ8_MEMBER(pc_dma8237_3_dack_r); + DECLARE_READ8_MEMBER(pc_dma8237_5_dack_r); + DECLARE_READ8_MEMBER(pc_dma8237_6_dack_r); + DECLARE_READ8_MEMBER(pc_dma8237_7_dack_r); + DECLARE_WRITE8_MEMBER(pc_dma8237_0_dack_w); + DECLARE_WRITE8_MEMBER(pc_dma8237_1_dack_w); + DECLARE_WRITE8_MEMBER(pc_dma8237_2_dack_w); + DECLARE_WRITE8_MEMBER(pc_dma8237_3_dack_w); + DECLARE_WRITE8_MEMBER(pc_dma8237_5_dack_w); + DECLARE_WRITE8_MEMBER(pc_dma8237_6_dack_w); + DECLARE_WRITE8_MEMBER(pc_dma8237_7_dack_w); + DECLARE_WRITE_LINE_MEMBER(at_dma8237_out_eop); + DECLARE_WRITE_LINE_MEMBER(pc_dack0_w); + DECLARE_WRITE_LINE_MEMBER(pc_dack1_w); + DECLARE_WRITE_LINE_MEMBER(pc_dack2_w); + DECLARE_WRITE_LINE_MEMBER(pc_dack3_w); + DECLARE_WRITE_LINE_MEMBER(pc_dack4_w); + 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_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(at_keybc_r); + DECLARE_WRITE8_MEMBER(at_keybc_w); + DECLARE_WRITE8_MEMBER(write_rtc); + 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); +protected: + UINT8 m_at_spkrdata; + UINT8 m_pit_out2; + int m_dma_channel; + bool m_cur_eop; + UINT8 m_dma_offset[2][4]; + UINT8 m_at_pages[0x10]; + UINT16 m_dma_high_byte; + UINT8 m_at_speaker; + bool m_refresh; + void at_speaker_set_spkrdata(UINT8 data); + + UINT8 m_channel_check; + UINT8 m_nmi_enabled; + + void pc_select_dma_channel(int channel, bool state); +}; + +#endif /* __SOUTHBRIDGE_H__ */ |