summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/strata.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/strata.cpp')
-rw-r--r--src/devices/machine/strata.cpp675
1 files changed, 675 insertions, 0 deletions
diff --git a/src/devices/machine/strata.cpp b/src/devices/machine/strata.cpp
new file mode 100644
index 00000000000..01651eb90bd
--- /dev/null
+++ b/src/devices/machine/strata.cpp
@@ -0,0 +1,675 @@
+// license:BSD-3-Clause
+// copyright-holders:Raphael Nabet, Michael Zapf
+/*
+ Intel 28F640J5 Flash ROM emulation (could also handle 28F320J5 with minor
+ changes, and possibly 28F256J3, 28F128J3, 28F640J3 and 28F320J3)
+
+ The 28F640J5 is a 64Mbit FEEPROM that can be accessed either on an 8-bit or
+ a 16-bit bus.
+
+ References:
+ Datasheets were found on Intel's site (www.intel.com)
+
+ Raphael Nabet 2004, based on MAME's intelfsh.c core
+
+ Device is currently only used in ti99/tn_usbsm
+
+ Rewritten as class
+ Michael Zapf, 2014
+
+ TODO: Make it work
+*/
+
+#include "emu.h"
+#include "strata.h"
+
+#define MAX_STRATA 1
+
+#define FEEPROM_SIZE 0x800000 // 64Mbit
+#define BLOCK_SIZE 0x020000
+
+#define BLOCKLOCK_SIZE ((FEEPROM_SIZE/BLOCK_SIZE+7)/8)
+#define WRBUF_SIZE 32
+#define PROT_REGS_SIZE 18
+
+#define COMPLETE_SIZE FEEPROM_SIZE + WRBUF_SIZE + PROT_REGS_SIZE + BLOCKLOCK_SIZE
+
+#define ADDRESS_MASK 0x7fffff
+#define BLOCK_ADDRESS_MASK 0x7e0000
+#define BLOCK_ADDRESS_SHIFT 17
+#define BYTE_ADDRESS_MASK 0x01ffff
+
+/* accessors for individual block lock flags */
+#define READ_BLOCKLOCK(block) ((m_blocklock[(block) >> 3] >> ((block) & 7)) & 1)
+#define SET_BLOCKLOCK(block) (m_blocklock[(block) >> 3] |= 1 << ((block) & 7))
+#define CLEAR_BLOCKLOCK(block) (m_blocklock[(block) >> 3] &= ~(1 << ((block) & 7)))
+
+const device_type STRATAFLASH = &device_creator<strataflash_device>;
+
+strataflash_device::strataflash_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, STRATAFLASH, "Intel 28F640J5", tag, owner, clock, "strataflash", __FILE__),
+ device_nvram_interface(mconfig, *this)
+{
+}
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void strataflash_device::nvram_default()
+{
+ memset(m_flashmemory, 0, COMPLETE_SIZE);
+}
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void strataflash_device::nvram_read(emu_file &file)
+{
+ file.read(m_flashmemory, COMPLETE_SIZE);
+
+ // TODO
+
+ /*
+ UINT8 buf;
+ int i;
+
+ // version flag
+ if (file->read(& buf, 1) != 1)
+ return 1;
+ if (buf != 0)
+ return 1;
+
+ // chip state: master lock
+ if (file->read(& buf, 1) != 1)
+ return 1;
+ m_master_lock = buf & 1;
+
+ // main FEEPROM area
+ if (file->read(m_flashmemory, FEEPROM_SIZE) != FEEPROM_SIZE)
+ return 1;
+ for (i = 0; i < FEEPROM_SIZE; i += 2)
+ {
+ UINT16 *ptr = (UINT16 *) (&m_flashmemory[i]);
+ *ptr = LITTLE_ENDIANIZE_INT16(*ptr);
+ }
+
+ // protection registers
+ if (file->read(m_prot_regs, PROT_REGS_SIZE) != PROT_REGS_SIZE)
+ return 1;
+ for (i = 0; i < PROT_REGS_SIZE; i += 2)
+ {
+ UINT16 *ptr = (UINT16 *) (&m_prot_regs[i]);
+ *ptr = LITTLE_ENDIANIZE_INT16(*ptr);
+ }
+
+ // block lock flags
+ if (file->read(m_blocklock, BLOCKLOCK_SIZE) != BLOCKLOCK_SIZE)
+ return 1;
+
+ return 0;
+ */
+}
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void strataflash_device::nvram_write(emu_file &file)
+{
+ // TODO
+
+ /*
+ UINT8 buf;
+ int i;
+
+ // version flag
+ buf = 0;
+ if (file->write(& buf, 1) != 1)
+ return 1;
+
+ // chip state: lower boot block lockout, higher boot block lockout,
+ software data protect
+ buf = m_master_lock;
+ if (file->write(& buf, 1) != 1)
+ return 1;
+
+ // main FEEPROM area
+ for (i = 0; i < FEEPROM_SIZE; i += 2)
+ {
+ UINT16 *ptr = (UINT16 *) (&m_flashmemory[i]);
+ *ptr = LITTLE_ENDIANIZE_INT16(*ptr);
+ }
+ if (file->write(m_flashmemory, FEEPROM_SIZE) != FEEPROM_SIZE)
+ return 1;
+ for (i = 0; i < FEEPROM_SIZE; i += 2)
+ {
+ UINT16 *ptr = (UINT16 *) (&m_flashmemory[i]);
+ *ptr = LITTLE_ENDIANIZE_INT16(*ptr);
+ }
+
+ // protection registers
+ for (i = 0; i < PROT_REGS_SIZE; i += 2)
+ {
+ UINT16 *ptr = (UINT16 *) (&m_prot_regs[i]);
+ *ptr = LITTLE_ENDIANIZE_INT16(*ptr);
+ }
+ if (file->write(m_prot_regs, PROT_REGS_SIZE) != PROT_REGS_SIZE)
+ return 1;
+ for (i = 0; i < PROT_REGS_SIZE; i += 2)
+ {
+ UINT16 *ptr = (UINT16 *) (&m_prot_regs[i]);
+ *ptr = LITTLE_ENDIANIZE_INT16(*ptr);
+ }
+
+ // block lock flags
+ if (file->write(m_blocklock, BLOCKLOCK_SIZE) != BLOCKLOCK_SIZE)
+ return 1;
+
+ return 0;
+ */
+
+ file.write(m_flashmemory, COMPLETE_SIZE);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+void strataflash_device::device_start(void)
+{
+ m_mode = FM_NORMAL;
+ m_status = 0x80;
+ m_master_lock = 0;
+ m_flashmemory = auto_alloc_array(machine(), UINT8, COMPLETE_SIZE);
+
+ m_wrbuf = m_flashmemory + FEEPROM_SIZE;
+ m_prot_regs = m_wrbuf + WRBUF_SIZE;
+ m_blocklock = m_prot_regs + PROT_REGS_SIZE;
+
+ // clear various FEEPROM areas
+ memset(m_prot_regs, 0xff, 18);
+ memset(m_flashmemory, 0xff, FEEPROM_SIZE);
+ memset(m_blocklock, 0x00, BLOCKLOCK_SIZE);
+
+ // set-up factory-programmed protection register segment
+ m_prot_regs[BYTE_XOR_LE(0)] &= 0xfe;
+ for (int i=2; i<10; i++)
+ m_prot_regs[i] = machine().rand();
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void strataflash_device::device_config_complete()
+{
+}
+
+/*
+ read a 8/16-bit word from FEEPROM
+*/
+UINT16 strataflash_device::read8_16(address_space& space, offs_t offset, bus_width_t bus_width)
+{
+ switch (bus_width)
+ {
+ case bw_8:
+ offset &= ADDRESS_MASK;
+ break;
+ case bw_16:
+ offset &= ADDRESS_MASK & ~1;
+ }
+
+ switch (m_mode)
+ {
+ default:
+ case FM_NORMAL:
+ switch (bus_width)
+ {
+ case bw_8:
+ return m_flashmemory[BYTE_XOR_LE(offset)];
+ case bw_16:
+ return *(UINT16*)(m_flashmemory+offset);
+ }
+ break;
+ case FM_READSTATUS:
+ return m_status;
+ case FM_WRBUFPART1:
+ return 0x80;
+ case FM_READID:
+ if ((offset >= 0x100) && (offset < 0x112))
+ { /* protection registers */
+ switch (bus_width)
+ {
+ case bw_8:
+ return m_prot_regs[BYTE_XOR_LE(offset)];
+ case bw_16:
+ return *(UINT16*)(m_prot_regs+offset);
+ }
+ }
+ else
+ switch (offset >> 1)
+ {
+ case 0: // maker ID
+ return 0x89; // Intel
+ case 1: // chip ID
+ return 0x15; // 64 Mbit
+ default:
+ if (((offset & BYTE_ADDRESS_MASK) >> 1) == 2)
+ { // block lock config
+ return READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT);
+ }
+ return 0; // default case
+ case 3: // master lock config
+ if (m_master_lock)
+ return 1;
+ else
+ return 0;
+ }
+ break;
+ case FM_READQUERY:
+ switch (offset >> 1)
+ {
+ case 0x00: // maker ID
+ return 0x89; // Intel
+ case 0x01: // chip ID
+ return 0x15; // 64 Mbit
+ default:
+ if (((offset & BYTE_ADDRESS_MASK) >> 1) == 2)
+ { // block lock config
+ return READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT);
+ }
+ return 0; // default case
+#if 0
+ case 0x03: // master lock config
+ if (m_flash_master_lock)
+ return 1;
+ else
+ return 0;
+#endif
+
+ /* CFI query identification string */
+ case 0x10:
+ return 'Q';
+ case 0x11:
+ return 'R';
+ case 0x12:
+ return 'Y';
+ case 0x13:
+ return 0x01;
+ case 0x14:
+ return 0x00;
+ case 0x15:
+ return 0x31;
+ case 0x16:
+ return 0x00;
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ return 0x00;
+
+ /* system interface information: voltage */
+ case 0x1b:
+ return 0x45;
+ case 0x1c:
+ return 0x55;
+ case 0x1d:
+ return 0x00;
+ case 0x1e:
+ return 0x00;
+
+ /* system interface information: timings */
+ case 0x1f:
+ return /*0x07*/0x00;
+ case 0x20:
+ return /*0x07*/0x00;
+ case 0x21:
+ return /*0x0a*/0x00;
+ case 0x22:
+ return 0x00;
+ case 0x23:
+ return /*0x04*/0x00;
+ case 0x24:
+ return /*0x04*/0x00;
+ case 0x25:
+ return /*0x04*/0x00;
+ case 0x26:
+ return 0x00;
+
+ /* device geometry definition */
+ case 0x27:
+ return 0x17;
+ case 0x28:
+ return 0x02;
+ case 0x29:
+ return 0x00;
+ case 0x2a:
+ return 0x05;
+ case 0x2b:
+ return 0x00;
+ case 0x2c:
+ return 0x01;
+ case 0x2d:
+ return 0x3f;
+ case 0x2e:
+ return 0x00;
+ case 0x2f:
+ return 0x00;
+ case 0x30:
+ return 0x02;
+
+ /* primary vendor-specific extended query */
+ case 0x31:
+ return 'P';
+ case 0x32:
+ return 'R';
+ case 0x33:
+ return 'I';
+ case 0x34:
+ return '1';
+ case 0x35:
+ return '1';
+ case 0x36:
+ return 0x0a;
+ case 0x37:
+ return 0x00;
+ case 0x38:
+ return 0x00;
+ case 0x39:
+ return 0x00;
+ case 0x3a:
+ return 0x01;
+ case 0x3b:
+ return 0x01;
+ case 0x3c:
+ return 0x00;
+ case 0x3d:
+ return 0x50;
+ case 0x3e:
+ return 0x00;
+ case 0x3f:
+ return 0x00;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ write a 8/16-bit word to FEEPROM
+*/
+void strataflash_device::write8_16(address_space& space, offs_t offset, UINT16 data, bus_width_t bus_width)
+{
+ switch (bus_width)
+ {
+ case bw_8:
+ offset &= ADDRESS_MASK;
+ break;
+ case bw_16:
+ offset &= ADDRESS_MASK & ~1;
+ break;
+ }
+
+ switch (m_mode)
+ {
+ case FM_NORMAL:
+ case FM_READID:
+ case FM_READQUERY:
+ case FM_READSTATUS:
+ switch (data)
+ {
+ case 0xff: // read array
+ m_mode = FM_NORMAL;
+ break;
+ case 0x90: // read identifier codes
+ m_mode = FM_READID;
+ break;
+ case 0x98: // read query
+ m_mode = FM_READQUERY;
+ break;
+ case 0x70: // read status register
+ m_mode = FM_READSTATUS;
+ break;
+ case 0x50: // clear status register
+ m_mode = FM_READSTATUS;
+ m_status &= 0xC5;
+ break;
+ case 0xe8: // write to buffer
+ m_mode = FM_WRBUFPART1;
+ m_wrbuf_base = offset & BLOCK_ADDRESS_MASK;
+ /*m_status &= 0xC5;*/
+ break;
+ case 0x40:
+ case 0x10: // program
+ m_mode = FM_WRITEPART1;
+ m_status &= 0xC5;
+ break;
+ case 0x20: // block erase
+ m_mode = FM_CLEARPART1;
+ m_status &= 0xC5;
+ break;
+ case 0xb0: // block erase, program suspend
+ /* not emulated (erase is instantaneous) */
+ break;
+ case 0xd0: // block erase, program resume
+ /* not emulated (erase is instantaneous) */
+ break;
+ case 0xb8: // configuration
+ m_mode = FM_CONFPART1;
+ m_status &= 0xC5;
+ break;
+ case 0x60: // set master lock
+ m_mode = FM_SETLOCK;
+ m_status &= 0xC5;
+ break;
+ case 0xc0: // protection program
+ m_mode = FM_WRPROTPART1;
+ m_status &= 0xC5;
+ break;
+ default:
+ logerror("Unknown flash mode byte %x\n", data);
+ break;
+ }
+ break;
+ case FM_WRBUFPART1:
+ m_mode = FM_WRBUFPART2;
+ if (((offset & BLOCK_ADDRESS_MASK) != m_wrbuf_base) || (data >= 0x20))
+ {
+ m_status |= 0x30;
+ m_wrbuf_len = 0;
+ m_wrbuf_count = data;
+ }
+ else
+ {
+ switch (bus_width)
+ {
+ case bw_8:
+ m_wrbuf_len = data+1;
+ break;
+ case bw_16:
+ m_wrbuf_len = (data+1) << 1;
+ break;
+ }
+ m_wrbuf_count = data;
+ }
+ break;
+ case FM_WRBUFPART2:
+ m_mode = FM_WRBUFPART3;
+ if (((offset & BLOCK_ADDRESS_MASK) != m_wrbuf_base)
+ || (((offset & BYTE_ADDRESS_MASK) + m_wrbuf_len) > BLOCK_SIZE))
+ {
+ m_status |= 0x30;
+ m_wrbuf_len = 0;
+ m_wrbuf_base = 0;
+ }
+ else
+ m_wrbuf_base = offset;
+ memset(m_wrbuf, 0xff, m_wrbuf_len); /* right??? */
+ case FM_WRBUFPART3:
+ if ((offset < m_wrbuf_base) || (offset >= (m_wrbuf_base + m_wrbuf_len)))
+ m_status |= 0x30;
+ else
+ {
+ switch (bus_width)
+ {
+ case bw_8:
+ m_wrbuf[offset-m_wrbuf_base] = data;
+ break;
+ case bw_16:
+ m_wrbuf[offset-m_wrbuf_base] = data & 0xff;
+ m_wrbuf[offset-m_wrbuf_base+1] = data >> 8;
+ break;
+ }
+ }
+ if (m_wrbuf_count == 0)
+ m_mode = FM_WRBUFPART4;
+ else
+ m_wrbuf_count--;
+ break;
+ case FM_WRBUFPART4:
+ if (((offset & BLOCK_ADDRESS_MASK) != (m_wrbuf_base & BLOCK_ADDRESS_MASK)) || (data != 0xd0))
+ {
+ m_status |= 0x30;
+ }
+ else if (READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT) && !m_hard_unlock)
+ {
+ m_status |= 0x12;
+ }
+ else if (!(m_status & 0x30))
+ {
+ int i;
+ for (i=0; i<m_wrbuf_len; i++)
+ m_flashmemory[BYTE_XOR_LE(m_wrbuf_base+i)] &= m_wrbuf[i];
+ m_mode = FM_READSTATUS;
+ }
+ break;
+ case FM_WRITEPART1:
+ if (READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT) && !m_hard_unlock)
+ {
+ m_status |= 0x12;
+ }
+ else
+ {
+ switch (bus_width)
+ {
+ case bw_8:
+ m_flashmemory[BYTE_XOR_LE(offset)] &= data;
+ break;
+ case bw_16:
+ *(UINT16*)(m_flashmemory+offset) &= data;
+ break;
+ }
+ }
+ m_mode = FM_READSTATUS;
+ break;
+ case FM_CLEARPART1:
+ if (data == 0xd0)
+ {
+ // clear the 128k block containing the current address
+ // to all 0xffs
+ if (READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT) && !m_hard_unlock)
+ {
+ m_status |= 0x22;
+ }
+ else
+ {
+ offset &= BLOCK_ADDRESS_MASK;
+ memset(&m_flashmemory[offset], 0xff, BLOCK_SIZE);
+ }
+ m_mode = FM_READSTATUS;
+ }
+ break;
+ case FM_SETLOCK:
+ switch (data)
+ {
+ case 0xf1:
+ if (!m_hard_unlock)
+ m_status |= 0x12;
+ else
+ m_master_lock = 1;
+ break;
+ case 0x01:
+ if (m_master_lock && !m_hard_unlock)
+ m_status |= 0x12;
+ else
+ SET_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT);
+ break;
+ case 0xd0:
+ if (m_master_lock && !m_hard_unlock)
+ m_status |= 0x22;
+ else
+ CLEAR_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT);
+ break;
+ case 0x03: // Set Read configuration
+ /* ignore command */
+ break;
+ default:
+ m_status |= 0x30;
+ break;
+ }
+ m_mode = FM_READSTATUS;
+ break;
+ case FM_CONFPART1:
+ /* configuration register is not emulated because the sts pin is not */
+ //m_configuration = data;
+ m_mode = FM_READSTATUS; /* right??? */
+ break;
+ case FM_WRPROTPART1:
+ if ((offset < 0x100) || (offset >= 0x112))
+ m_status |= 0x10;
+ else if ((offset >= 0x102) && !((m_prot_regs[BYTE_XOR_LE(0)] >> ((offset - 0x102) >> 3)) & 1))
+ m_status |= 0x12;
+ else
+ {
+ switch (bus_width)
+ {
+ case bw_8:
+ m_prot_regs[BYTE_XOR_LE(offset-0x100)] &= data;
+ break;
+ case bw_16:
+ *(UINT16*)(m_prot_regs+(offset-0x100)) &= data;
+ break;
+ }
+ }
+ m_mode = FM_READSTATUS; /* right??? */
+ break;
+ }
+}
+
+/*
+ read a byte from FEEPROM
+*/
+READ8_MEMBER( strataflash_device::read8 )
+{
+ return read8_16(space, offset, bw_8);
+}
+
+/*
+ Write a byte to FEEPROM
+*/
+WRITE8_MEMBER( strataflash_device::write8 )
+{
+ write8_16(space, offset, data, bw_8);
+}
+
+/*
+ read a 16-bit word from FEEPROM
+*/
+READ16_MEMBER( strataflash_device::read16 )
+{
+ return read8_16(space, offset, bw_16);
+}
+
+/*
+ Write a byte to FEEPROM
+*/
+WRITE16_MEMBER( strataflash_device::write16 )
+{
+ write8_16(space, offset, data, bw_16);
+}