From e7868ca66f623fbfa13a21a85d494d5367c7ba66 Mon Sep 17 00:00:00 2001 From: Michael Zapf Date: Wed, 12 Mar 2014 13:13:10 +0000 Subject: [PATCH] (MESS) Modernized StrataFlash device. (nw) --- src/mess/machine/strata.c | 564 +++++++++++++++---------------- src/mess/machine/strata.h | 72 +++- src/mess/machine/ti99/tn_usbsm.c | 198 +++++------ src/mess/machine/ti99/tn_usbsm.h | 13 +- 4 files changed, 435 insertions(+), 412 deletions(-) diff --git a/src/mess/machine/strata.c b/src/mess/machine/strata.c index 8fbe3e4659a..b7460b05112 100644 --- a/src/mess/machine/strata.c +++ b/src/mess/machine/strata.c @@ -9,11 +9,17 @@ 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" -#include "devlegcy.h" #define MAX_STRATA 1 @@ -24,91 +30,174 @@ #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 -enum fm_mode_t -{ - FM_NORMAL, // normal read/write - FM_READID, // read ID - FM_READQUERY, // read query - FM_READSTATUS, // read status - FM_WRITEPART1, // first half of programming, awaiting second - FM_WRBUFPART1, // first part of write to buffer, awaiting second - FM_WRBUFPART2, // second part of write to buffer, awaiting third - FM_WRBUFPART3, // third part of write to buffer, awaiting fourth - FM_WRBUFPART4, // fourth part of write to buffer - FM_CLEARPART1, // first half of clear, awaiting second - FM_SETLOCK, // first half of set master lock/set block lock - FM_CONFPART1, // first half of configuration, awaiting second - FM_WRPROTPART1 // first half of protection program, awaiting second -}; -struct strata_t -{ - fm_mode_t mode; // current operation mode - int hard_unlock; // 1 if RP* pin is at Vhh (not fully implemented) - int status; // current status - int master_lock; // master lock flag - offs_t wrbuf_base; // start address in write buffer command - int wrbuf_len; // count converted into byte length in write buffer command - int wrbuf_count; // current count in write buffer command - UINT8 *wrbuf; // write buffer used by write buffer command - UINT8 *data_ptr; // main FEEPROM area - UINT8 *blocklock; // block lock flags - UINT8 *prot_regs; // protection registers -}; - /* accessors for individual block lock flags */ -#define READ_BLOCKLOCK(strata, block) (((strata)->blocklock[(block) >> 3] >> ((block) & 7)) & 1) -#define SET_BLOCKLOCK(strata, block) ((strata)->blocklock[(block) >> 3] |= 1 << ((block) & 7)) -#define CLEAR_BLOCKLOCK(strata, block) ((strata)->blocklock[(block) >> 3] &= ~(1 << ((block) & 7))) - -/* - Initialize one FEEPROM chip: may be called at driver init or image load - time (or machine init time if you don't use MESS image core) -*/ - -INLINE strata_t *get_safe_token(device_t *device) -{ - assert(device != NULL); - assert(device->type() == STRATAFLASH); - - return (strata_t *)downcast(device)->token(); -} - -static DEVICE_START( strataflash ) -{ - strata_t *strata = get_safe_token(device); - int i; - - strata->mode = FM_NORMAL; - strata->status = 0x80; - strata->master_lock = 0; - strata->data_ptr = auto_alloc_array(device->machine(), UINT8, FEEPROM_SIZE + WRBUF_SIZE + PROT_REGS_SIZE + BLOCKLOCK_SIZE); - strata->wrbuf = strata->data_ptr + FEEPROM_SIZE; - strata->prot_regs = strata->wrbuf + WRBUF_SIZE; - strata->blocklock = strata->prot_regs + PROT_REGS_SIZE; - /* clear various FEEPROM areas */ - memset(strata->prot_regs, 0xff, 18); - memset(strata->data_ptr, 0xff, FEEPROM_SIZE); - memset(strata->blocklock, 0x00, BLOCKLOCK_SIZE); - /* set-up factory-programmed protection register segment */ - strata->prot_regs[BYTE_XOR_LE(0)] &= 0xfe; - for (i=2; i<10; i++) - strata->prot_regs[i] = device->machine().rand(); -} +#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(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, STRATAFLASH, "Intel 28F640J5", tag, owner, clock, "strataflash", __FILE__) + : device_t(mconfig, STRATAFLASH, "Intel 28F640J5", tag, owner, clock, "strataflash", __FILE__), + device_nvram_interface(mconfig, *this) { - m_token = global_alloc_clear(strata_t); } -strataflash_device::~strataflash_device() { global_free(m_token); } +//------------------------------------------------- +// 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 @@ -120,131 +209,11 @@ void strataflash_device::device_config_complete() { } -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void strataflash_device::device_start() -{ - DEVICE_START_NAME( strataflash )(this); -} - - - -/* - load the FEEPROM contents from file -*/ -int strataflash_load(device_t *device, emu_file *file) -{ - strata_t *strata = get_safe_token(device); - 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; - strata->master_lock = buf & 1; - - /* main FEEPROM area */ - if (file->read(strata->data_ptr, FEEPROM_SIZE) != FEEPROM_SIZE) - return 1; - for (i = 0; i < FEEPROM_SIZE; i += 2) - { - UINT16 *ptr = (UINT16 *) (&strata->data_ptr[i]); - *ptr = LITTLE_ENDIANIZE_INT16(*ptr); - } - - /* protection registers */ - if (file->read(strata->prot_regs, PROT_REGS_SIZE) != PROT_REGS_SIZE) - return 1; - for (i = 0; i < PROT_REGS_SIZE; i += 2) - { - UINT16 *ptr = (UINT16 *) (&strata->prot_regs[i]); - *ptr = LITTLE_ENDIANIZE_INT16(*ptr); - } - - /* block lock flags */ - if (file->read(strata->blocklock, BLOCKLOCK_SIZE) != BLOCKLOCK_SIZE) - return 1; - - return 0; -} - -/* - save the FEEPROM contents to file -*/ -int strataflash_save(device_t *device, emu_file *file) -{ - strata_t *strata = get_safe_token(device); - 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 = strata->master_lock; - if (file->write(& buf, 1) != 1) - return 1; - - /* main FEEPROM area */ - for (i = 0; i < FEEPROM_SIZE; i += 2) - { - UINT16 *ptr = (UINT16 *) (&strata->data_ptr[i]); - *ptr = LITTLE_ENDIANIZE_INT16(*ptr); - } - if (file->write(strata->data_ptr, FEEPROM_SIZE) != FEEPROM_SIZE) - return 1; - for (i = 0; i < FEEPROM_SIZE; i += 2) - { - UINT16 *ptr = (UINT16 *) (&strata->data_ptr[i]); - *ptr = LITTLE_ENDIANIZE_INT16(*ptr); - } - - /* protection registers */ - for (i = 0; i < PROT_REGS_SIZE; i += 2) - { - UINT16 *ptr = (UINT16 *) (&strata->prot_regs[i]); - *ptr = LITTLE_ENDIANIZE_INT16(*ptr); - } - if (file->write(strata->prot_regs, PROT_REGS_SIZE) != PROT_REGS_SIZE) - return 1; - for (i = 0; i < PROT_REGS_SIZE; i += 2) - { - UINT16 *ptr = (UINT16 *) (&strata->prot_regs[i]); - *ptr = LITTLE_ENDIANIZE_INT16(*ptr); - } - - /* block lock flags */ - if (file->write(strata->blocklock, BLOCKLOCK_SIZE) != BLOCKLOCK_SIZE) - return 1; - - return 0; -} - -/* bus width for 8/16-bit handlers */ -enum bus_width_t -{ - bw_8, - bw_16 -}; - /* read a 8/16-bit word from FEEPROM */ -static int strataflash_r(device_t *device, offs_t offset, bus_width_t bus_width) +UINT16 strataflash_device::read8_16(address_space& space, offs_t offset, bus_width_t bus_width) { - strata_t *strata = get_safe_token(device); - switch (bus_width) { case bw_8: @@ -254,20 +223,20 @@ static int strataflash_r(device_t *device, offs_t offset, bus_width_t bus_width) offset &= ADDRESS_MASK & ~1; } - switch (strata->mode) + switch (m_mode) { default: case FM_NORMAL: switch (bus_width) { case bw_8: - return strata->data_ptr[BYTE_XOR_LE(offset)]; + return m_flashmemory[BYTE_XOR_LE(offset)]; case bw_16: - return *(UINT16*)(strata->data_ptr+offset); + return *(UINT16*)(m_flashmemory+offset); } break; case FM_READSTATUS: - return strata->status; + return m_status; case FM_WRBUFPART1: return 0x80; case FM_READID: @@ -276,9 +245,9 @@ static int strataflash_r(device_t *device, offs_t offset, bus_width_t bus_width) switch (bus_width) { case bw_8: - return strata->prot_regs[BYTE_XOR_LE(offset)]; + return m_prot_regs[BYTE_XOR_LE(offset)]; case bw_16: - return *(UINT16*)(strata->prot_regs+offset); + return *(UINT16*)(m_prot_regs+offset); } } else @@ -291,11 +260,11 @@ static int strataflash_r(device_t *device, offs_t offset, bus_width_t bus_width) default: if (((offset & BYTE_ADDRESS_MASK) >> 1) == 2) { // block lock config - return READ_BLOCKLOCK(strata, offset >> BLOCK_ADDRESS_SHIFT); + return READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT); } return 0; // default case case 3: // master lock config - if (strata->master_lock) + if (m_master_lock) return 1; else return 0; @@ -311,12 +280,12 @@ static int strataflash_r(device_t *device, offs_t offset, bus_width_t bus_width) default: if (((offset & BYTE_ADDRESS_MASK) >> 1) == 2) { // block lock config - return READ_BLOCKLOCK(strata, offset >> BLOCK_ADDRESS_SHIFT); + return READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT); } return 0; // default case #if 0 case 0x03: // master lock config - if (strata->flash_master_lock) + if (m_flash_master_lock) return 1; else return 0; @@ -434,10 +403,8 @@ static int strataflash_r(device_t *device, offs_t offset, bus_width_t bus_width) /* write a 8/16-bit word to FEEPROM */ -static void strataflash_w(device_t *device, offs_t offset, int data, bus_width_t bus_width) +void strataflash_device::write8_16(address_space& space, offs_t offset, UINT16 data, bus_width_t bus_width) { - strata_t *strata = get_safe_token(device); - switch (bus_width) { case bw_8: @@ -445,9 +412,10 @@ static void strataflash_w(device_t *device, offs_t offset, int data, bus_width_t break; case bw_16: offset &= ADDRESS_MASK & ~1; + break; } - switch (strata->mode) + switch (m_mode) { case FM_NORMAL: case FM_READID: @@ -456,34 +424,34 @@ static void strataflash_w(device_t *device, offs_t offset, int data, bus_width_t switch (data) { case 0xff: // read array - strata->mode = FM_NORMAL; + m_mode = FM_NORMAL; break; case 0x90: // read identifier codes - strata->mode = FM_READID; + m_mode = FM_READID; break; case 0x98: // read query - strata->mode = FM_READQUERY; + m_mode = FM_READQUERY; break; case 0x70: // read status register - strata->mode = FM_READSTATUS; + m_mode = FM_READSTATUS; break; case 0x50: // clear status register - strata->mode = FM_READSTATUS; - strata->status &= 0xC5; + m_mode = FM_READSTATUS; + m_status &= 0xC5; break; case 0xe8: // write to buffer - strata->mode = FM_WRBUFPART1; - strata->wrbuf_base = offset & BLOCK_ADDRESS_MASK; - /*strata->status &= 0xC5;*/ + m_mode = FM_WRBUFPART1; + m_wrbuf_base = offset & BLOCK_ADDRESS_MASK; + /*m_status &= 0xC5;*/ break; case 0x40: case 0x10: // program - strata->mode = FM_WRITEPART1; - strata->status &= 0xC5; + m_mode = FM_WRITEPART1; + m_status &= 0xC5; break; case 0x20: // block erase - strata->mode = FM_CLEARPART1; - strata->status &= 0xC5; + m_mode = FM_CLEARPART1; + m_status &= 0xC5; break; case 0xb0: // block erase, program suspend /* not emulated (erase is instantaneous) */ @@ -492,16 +460,16 @@ static void strataflash_w(device_t *device, offs_t offset, int data, bus_width_t /* not emulated (erase is instantaneous) */ break; case 0xb8: // configuration - strata->mode = FM_CONFPART1; - strata->status &= 0xC5; + m_mode = FM_CONFPART1; + m_status &= 0xC5; break; case 0x60: // set master lock - strata->mode = FM_SETLOCK; - strata->status &= 0xC5; + m_mode = FM_SETLOCK; + m_status &= 0xC5; break; case 0xc0: // protection program - strata->mode = FM_WRPROTPART1; - strata->status &= 0xC5; + m_mode = FM_WRPROTPART1; + m_status &= 0xC5; break; default: logerror("Unknown flash mode byte %x\n", data); @@ -509,198 +477,198 @@ static void strataflash_w(device_t *device, offs_t offset, int data, bus_width_t } break; case FM_WRBUFPART1: - strata->mode = FM_WRBUFPART2; - if (((offset & BLOCK_ADDRESS_MASK) != strata->wrbuf_base) || (data >= 0x20)) + m_mode = FM_WRBUFPART2; + if (((offset & BLOCK_ADDRESS_MASK) != m_wrbuf_base) || (data >= 0x20)) { - strata->status |= 0x30; - strata->wrbuf_len = 0; - strata->wrbuf_count = data; + m_status |= 0x30; + m_wrbuf_len = 0; + m_wrbuf_count = data; } else { switch (bus_width) { case bw_8: - strata->wrbuf_len = data+1; + m_wrbuf_len = data+1; break; case bw_16: - strata->wrbuf_len = (data+1) << 1; + m_wrbuf_len = (data+1) << 1; break; } - strata->wrbuf_count = data; + m_wrbuf_count = data; } break; case FM_WRBUFPART2: - strata->mode = FM_WRBUFPART3; - if (((offset & BLOCK_ADDRESS_MASK) != strata->wrbuf_base) - || (((offset & BYTE_ADDRESS_MASK) + strata->wrbuf_len) > BLOCK_SIZE)) + m_mode = FM_WRBUFPART3; + if (((offset & BLOCK_ADDRESS_MASK) != m_wrbuf_base) + || (((offset & BYTE_ADDRESS_MASK) + m_wrbuf_len) > BLOCK_SIZE)) { - strata->status |= 0x30; - strata->wrbuf_len = 0; - strata->wrbuf_base = 0; + m_status |= 0x30; + m_wrbuf_len = 0; + m_wrbuf_base = 0; } else - strata->wrbuf_base = offset; - memset(strata->wrbuf, 0xff, strata->wrbuf_len); /* right??? */ + m_wrbuf_base = offset; + memset(m_wrbuf, 0xff, m_wrbuf_len); /* right??? */ case FM_WRBUFPART3: - if ((offset < strata->wrbuf_base) || (offset >= (strata->wrbuf_base + strata->wrbuf_len))) - strata->status |= 0x30; + if ((offset < m_wrbuf_base) || (offset >= (m_wrbuf_base + m_wrbuf_len))) + m_status |= 0x30; else { switch (bus_width) { case bw_8: - strata->wrbuf[offset-strata->wrbuf_base] = data; + m_wrbuf[offset-m_wrbuf_base] = data; break; case bw_16: - strata->wrbuf[offset-strata->wrbuf_base] = data & 0xff; - strata->wrbuf[offset-strata->wrbuf_base+1] = data >> 8; + m_wrbuf[offset-m_wrbuf_base] = data & 0xff; + m_wrbuf[offset-m_wrbuf_base+1] = data >> 8; break; } } - if (strata->wrbuf_count == 0) - strata->mode = FM_WRBUFPART4; + if (m_wrbuf_count == 0) + m_mode = FM_WRBUFPART4; else - strata->wrbuf_count--; + m_wrbuf_count--; break; case FM_WRBUFPART4: - if (((offset & BLOCK_ADDRESS_MASK) != (strata->wrbuf_base & BLOCK_ADDRESS_MASK)) || (data != 0xd0)) + if (((offset & BLOCK_ADDRESS_MASK) != (m_wrbuf_base & BLOCK_ADDRESS_MASK)) || (data != 0xd0)) { - strata->status |= 0x30; + m_status |= 0x30; } - else if (READ_BLOCKLOCK(strata, offset >> BLOCK_ADDRESS_SHIFT) && !strata->hard_unlock) + else if (READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT) && !m_hard_unlock) { - strata->status |= 0x12; + m_status |= 0x12; } - else if (!(strata->status & 0x30)) + else if (!(m_status & 0x30)) { int i; - for (i=0; iwrbuf_len; i++) - strata->data_ptr[BYTE_XOR_LE(strata->wrbuf_base+i)] &= strata->wrbuf[i]; - strata->mode = FM_READSTATUS; + for (i=0; i> BLOCK_ADDRESS_SHIFT) && !strata->hard_unlock) + if (READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT) && !m_hard_unlock) { - strata->status |= 0x12; + m_status |= 0x12; } else { switch (bus_width) { case bw_8: - strata->data_ptr[BYTE_XOR_LE(offset)] &= data; + m_flashmemory[BYTE_XOR_LE(offset)] &= data; break; case bw_16: - *(UINT16*)(strata->data_ptr+offset) &= data; + *(UINT16*)(m_flashmemory+offset) &= data; break; } } - strata->mode = FM_READSTATUS; + 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(strata, offset >> BLOCK_ADDRESS_SHIFT) && !strata->hard_unlock) + if (READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT) && !m_hard_unlock) { - strata->status |= 0x22; + m_status |= 0x22; } else { offset &= BLOCK_ADDRESS_MASK; - memset(&strata->data_ptr[offset], 0xff, BLOCK_SIZE); + memset(&m_flashmemory[offset], 0xff, BLOCK_SIZE); } - strata->mode = FM_READSTATUS; + m_mode = FM_READSTATUS; } break; case FM_SETLOCK: switch (data) { case 0xf1: - if (!strata->hard_unlock) - strata->status |= 0x12; + if (!m_hard_unlock) + m_status |= 0x12; else - strata->master_lock = 1; + m_master_lock = 1; break; case 0x01: - if (strata->master_lock && !strata->hard_unlock) - strata->status |= 0x12; + if (m_master_lock && !m_hard_unlock) + m_status |= 0x12; else - SET_BLOCKLOCK(strata, offset >> BLOCK_ADDRESS_SHIFT); + SET_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT); break; case 0xd0: - if (strata->master_lock && !strata->hard_unlock) - strata->status |= 0x22; + if (m_master_lock && !m_hard_unlock) + m_status |= 0x22; else - CLEAR_BLOCKLOCK(strata, offset >> BLOCK_ADDRESS_SHIFT); + CLEAR_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT); break; case 0x03: // Set Read configuration /* ignore command */ break; default: - strata->status |= 0x30; + m_status |= 0x30; break; } - strata->mode = FM_READSTATUS; + m_mode = FM_READSTATUS; break; case FM_CONFPART1: /* configuration register is not emulated because the sts pin is not */ - //strata->configuration = data; - strata->mode = FM_READSTATUS; /* right??? */ + //m_configuration = data; + m_mode = FM_READSTATUS; /* right??? */ break; case FM_WRPROTPART1: if ((offset < 0x100) || (offset >= 0x112)) - strata->status |= 0x10; - else if ((offset >= 0x102) && !((strata->prot_regs[BYTE_XOR_LE(0)] >> ((offset - 0x102) >> 3)) & 1)) - strata->status |= 0x12; + 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: - strata->prot_regs[BYTE_XOR_LE(offset-0x100)] &= data; + m_prot_regs[BYTE_XOR_LE(offset-0x100)] &= data; break; case bw_16: - *(UINT16*)(strata->prot_regs+(offset-0x100)) &= data; + *(UINT16*)(m_prot_regs+(offset-0x100)) &= data; break; } } - strata->mode = FM_READSTATUS; /* right??? */ + m_mode = FM_READSTATUS; /* right??? */ break; } } /* - read a 8-bit word from FEEPROM + read a byte from FEEPROM */ -UINT8 strataflash_8_r(device_t *device, offs_t offset) +READ8_MEMBER( strataflash_device::read8 ) { - return strataflash_r(device, offset, bw_8); + return read8_16(space, offset, bw_8); } /* - write a 8-bit word to FEEPROM + Write a byte to FEEPROM */ -void strataflash_8_w(device_t *device, offs_t offset, UINT8 data) +WRITE8_MEMBER( strataflash_device::write8 ) { - strataflash_w(device, offset, data, bw_8); + write8_16(space, offset, data, bw_8); } /* read a 16-bit word from FEEPROM */ -UINT16 strataflash_16_r(device_t *device, offs_t offset) +READ16_MEMBER( strataflash_device::read16 ) { - return strataflash_r(device, offset, bw_16); + return read8_16(space, offset, bw_16); } /* - write a 16-bit word to FEEPROM + Write a byte to FEEPROM */ -void strataflash_16_w(device_t *device, offs_t offset, UINT16 data) +WRITE16_MEMBER( strataflash_device::write16 ) { - strataflash_w(device, offset, data, bw_16); + write8_16(space, offset, data, bw_16); } diff --git a/src/mess/machine/strata.h b/src/mess/machine/strata.h index 6b954f832c5..2341549172e 100644 --- a/src/mess/machine/strata.h +++ b/src/mess/machine/strata.h @@ -2,32 +2,72 @@ strata.h: header file for strata.c */ -class strataflash_device : public device_t +class strataflash_device : public device_t, public device_nvram_interface { public: strataflash_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - ~strataflash_device(); - // access to legacy token - struct strata_t *token() const { assert(m_token != NULL); return m_token; } + // 8-bit access + DECLARE_READ8_MEMBER( read8 ); + DECLARE_WRITE8_MEMBER( write8 ); + + // 16-bit access + DECLARE_READ16_MEMBER( read16 ); + DECLARE_WRITE16_MEMBER( write16 ); + protected: // device-level overrides - virtual void device_config_complete(); - virtual void device_start(); + void device_config_complete(); + + void device_start(); + + void nvram_default(); + void nvram_read(emu_file &file); + void nvram_write(emu_file &file); + private: - // internal state - struct strata_t *m_token; + + // bus width for 8/16-bit handlers + enum bus_width_t + { + bw_8, + bw_16 + }; + + UINT16 read8_16(address_space& space, offs_t offset, bus_width_t bus_width); + void write8_16(address_space& space, offs_t offset, UINT16 data, bus_width_t bus_width); + + enum fm_mode_t + { + FM_NORMAL, // normal read/write + FM_READID, // read ID + FM_READQUERY, // read query + FM_READSTATUS, // read status + FM_WRITEPART1, // first half of programming, awaiting second + FM_WRBUFPART1, // first part of write to buffer, awaiting second + FM_WRBUFPART2, // second part of write to buffer, awaiting third + FM_WRBUFPART3, // third part of write to buffer, awaiting fourth + FM_WRBUFPART4, // fourth part of write to buffer + FM_CLEARPART1, // first half of clear, awaiting second + FM_SETLOCK, // first half of set master lock/set block lock + FM_CONFPART1, // first half of configuration, awaiting second + FM_WRPROTPART1 // first half of protection program, awaiting second + }; + + fm_mode_t m_mode; // current operation mode + int m_hard_unlock; // 1 if RP* pin is at Vhh (not fully implemented) + int m_status; // current status + int m_master_lock; // master lock flag + offs_t m_wrbuf_base; // start address in write buffer command + int m_wrbuf_len; // count converted into byte length in write buffer command + int m_wrbuf_count; // current count in write buffer command + UINT8* m_wrbuf; // write buffer used by write buffer command + UINT8* m_flashmemory; // main FEEPROM area + UINT8* m_blocklock; // block lock flags + UINT8* m_prot_regs; // protection registers }; extern const device_type STRATAFLASH; - #define MCFG_STRATAFLASH_ADD(_tag) \ MCFG_DEVICE_ADD(_tag, STRATAFLASH, 0) - -int strataflash_load(device_t *device, emu_file *file); -int strataflash_save(device_t *device, emu_file *file); -UINT8 strataflash_8_r(device_t *device, UINT32 address); -void strataflash_8_w(device_t *device, UINT32 address, UINT8 data); -UINT16 strataflash_16_r(device_t *device, offs_t offset); -void strataflash_16_w(device_t *device, offs_t offset, UINT16 data); diff --git a/src/mess/machine/ti99/tn_usbsm.c b/src/mess/machine/ti99/tn_usbsm.c index 51fb0cc423b..ffcc5c84bcc 100644 --- a/src/mess/machine/ti99/tn_usbsm.c +++ b/src/mess/machine/ti99/tn_usbsm.c @@ -40,9 +40,9 @@ *****************************************************************************/ #include "tn_usbsm.h" -#include "machine/strata.h" #define BUFFER_TAG "ram" +#define STRATA_TAG "strata" enum { @@ -53,86 +53,11 @@ enum }; nouspikel_usb_smartmedia_device::nouspikel_usb_smartmedia_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) -: ti_expansion_card_device(mconfig, TI99_USBSM, "Nouspikel USB/Smartmedia card", tag, owner, clock, "ti99_usbsm", __FILE__) +: ti_expansion_card_device(mconfig, TI99_USBSM, "Nouspikel USB/Smartmedia card", tag, owner, clock, "ti99_usbsm", __FILE__), + m_flash(*this, STRATA_TAG) { } -/* - demultiplexed read in USB-SmartMedia DSR space -*/ -UINT16 nouspikel_usb_smartmedia_device::usbsm_mem_16_r(offs_t offset) -{ - UINT16 reply = 0; - - if (offset < 0x2800) - { /* 0x4000-0x4fff range */ - if ((m_cru_register & IO_REGS_ENABLE) && (offset >= 0x27f8)) - { /* SmartMedia interface */ - if (offset == 0) - reply = m_smartmedia->data_r() << 8; - } - else - { /* FEEPROM */ - if (!(m_cru_register & FEEPROM_WRITE_ENABLE)) - reply = strataflash_16_r(m_strata, offset); - } - } - else - { /* 0x5000-0x5fff range */ - if ((m_cru_register & IO_REGS_ENABLE) && (offset >= 0x2ff8)) - { /* USB controller */ - } - else - { /* SRAM */ - reply = m_ram[m_sram_page*0x800+(offset-0x2800)]; - } - } - return reply; -} - -/* - demultiplexed write in USB-SmartMedia DSR space -*/ -void nouspikel_usb_smartmedia_device::usbsm_mem_16_w(offs_t offset, UINT16 data) -{ - if (offset < 0x2800) - { /* 0x4000-0x4fff range */ - if ((m_cru_register & IO_REGS_ENABLE) && (offset >= 0x27f8)) - { /* SmartMedia interface */ - switch (offset & 3) - { - case 0: - m_smartmedia->data_w(data >> 8); - break; - case 1: - m_smartmedia->address_w(data >> 8); - break; - case 2: - m_smartmedia->command_w(data >> 8); - break; - case 3: - /* bogus, don't use(?) */ - break; - } - } - else - { /* FEEPROM */ - if (m_cru_register & FEEPROM_WRITE_ENABLE) - strataflash_16_w(m_strata, offset, data); - } - } - else - { /* 0x5000-0x5fff range */ - if ((m_cru_register & IO_REGS_ENABLE) && (offset >= 0x2ff8)) - { /* USB controller */ - } - else - { /* SRAM */ - m_ram[m_sram_page*0x800+(offset-0x2800)] = data; - } - } -} - /* CRU read */ @@ -183,15 +108,21 @@ WRITE8_MEMBER(nouspikel_usb_smartmedia_device::cruwrite) case 0: m_selected = data; break; - - case 1: /* enable I/O registers */ - case 2: /* enable interrupts */ - case 3: /* enable SmartMedia card */ - case 4: /* enable FEEPROM writes (and disable reads) */ - if (data) - m_cru_register |= 1 << bit; - else - m_cru_register &= ~ (1 << bit); + case 1: + // enable I/O registers + m_enable_io = data; + break; + case 2: + // enable interrupts + m_enable_int = data; + break; + case 3: + // enable SmartMedia card + m_enable_sm = data; + break; + case 4: + // enable FEEPROM writes (and disable reads) + m_write_flash = data; break; case 5: /* FEEPROM page */ case 6: @@ -238,11 +169,42 @@ READ8Z_MEMBER(nouspikel_usb_smartmedia_device::readz) if (((offset & m_select_mask)==m_select_value) && m_selected) { if (m_tms9995_mode ? (!(offset & 1)) : (offset & 1)) - { /* first read triggers 16-bit read cycle */ - m_input_latch = usbsm_mem_16_r((offset >> 1)&0xffff); + { + // first read triggers 16-bit read cycle + + if (offset < 0x5000) + { + // 0x4000-0x4fff range + if (m_enable_io && (offset >= 0x4ff0)) + { + // SmartMedia interface (4ff0-4ff7) + if ((offset & 8) == 0) + m_input_latch = m_smartmedia->data_r() << 8; + } + else + { + // FEEPROM + if (!m_write_flash) + m_input_latch = m_flash->read16(space, (offset>>1)&0xffff); + } + } + else + { + // 0x5000-0x5fff range + if (m_enable_io && (offset >= 0x5ff0)) + { + // USB controller. Not implemented. + logerror("tn_usbsm: Reading from USB\n"); + } + else + { + // SRAM + m_input_latch = m_ram[m_sram_page*0x800+((offset>>1)&0x07ff)]; + } + } } - /* return latched input */ + // return latched input *value = ((offset & 1) ? (m_input_latch) : (m_input_latch >> 8)) & 0xff; } } @@ -263,8 +225,48 @@ WRITE8_MEMBER(nouspikel_usb_smartmedia_device::write) m_output_latch = (m_output_latch & 0x00ff) | (data << 8); if ((m_tms9995_mode)? (offset & 1) : (!(offset & 1))) - { /* second write triggers 16-bit write cycle */ - usbsm_mem_16_w((offset >> 1)&0xffff, m_output_latch); + { + // second write triggers 16-bit write cycle + if (offset < 0x5000) + { + // 0x4000-0x4fff range + if (m_enable_io && (offset >= 0x4ff0)) + { + // SmartMedia interface + switch (offset & 3) + { + case 0: + m_smartmedia->data_w(m_output_latch >> 8); + break; + case 1: + m_smartmedia->address_w(m_output_latch >> 8); + break; + case 2: + m_smartmedia->command_w(m_output_latch >> 8); + break; + case 3: + /* bogus, don't use(?) */ + break; + } + } + else + { // FEEPROM + if (m_write_flash) + m_flash->write16(space, (offset>>1)&0xffff, m_output_latch); + } + } + else + { /* 0x5000-0x5fff range */ + if (m_enable_io && (offset >= 0x5ff0)) + { + // USB controller. Not implemented. + logerror("tn_usbsm: Writing to USB controller.\n"); + } + else + { // SRAM + m_ram[m_sram_page*0x800+((offset>>1) & 0x07ff)] = m_output_latch; + } + } } } } @@ -274,7 +276,6 @@ void nouspikel_usb_smartmedia_device::device_start() m_ram = (UINT16*)(*memregion(BUFFER_TAG)); /* auto_alloc_array(device->machine(), UINT16, 0x100000/2); */ m_smartmedia = subdevice("smartmedia"); - m_strata = subdevice("strata"); } void nouspikel_usb_smartmedia_device::device_reset() @@ -282,8 +283,11 @@ void nouspikel_usb_smartmedia_device::device_reset() m_feeprom_page = 0; m_sram_page = 0; m_cru_register = 0; - m_tms9995_mode = false; - // m_tms9995_mode = (device->type()==TMS9995); + m_tms9995_mode = (ioport("BYTEORDER")->read() == 0x01); + m_enable_io = false; + m_enable_int = false; + m_enable_sm = false; + m_write_flash = false; if (m_genmod) { @@ -324,6 +328,10 @@ INPUT_PORTS_START( tn_usbsm ) PORT_DIPSETTING( 0x1d00, "1D00" ) PORT_DIPSETTING( 0x1e00, "1E00" ) PORT_DIPSETTING( 0x1f00, "1F00" ) + PORT_START( "BYTEORDER" ) + PORT_DIPNAME( 0x01, 0x00, "Multiplex mode" ) + PORT_DIPSETTING( 0x00, "TI mode") + PORT_DIPSETTING( 0x01, "Geneve mode") INPUT_PORTS_END MACHINE_CONFIG_FRAGMENT( tn_usbsm ) diff --git a/src/mess/machine/ti99/tn_usbsm.h b/src/mess/machine/ti99/tn_usbsm.h index 269e6e2cb48..05cedd05585 100644 --- a/src/mess/machine/ti99/tn_usbsm.h +++ b/src/mess/machine/ti99/tn_usbsm.h @@ -18,6 +18,7 @@ #include "ti99defs.h" #include "peribox.h" #include "machine/smartmed.h" +#include "machine/strata.h" extern const device_type TI99_USBSM; @@ -39,19 +40,25 @@ protected: virtual ioport_constructor device_input_ports() const; private: - UINT16 usbsm_mem_16_r(offs_t offset); - void usbsm_mem_16_w(offs_t offset, UINT16 data); + smartmedia_image_device* m_smartmedia; - device_t* m_strata; int m_feeprom_page; int m_sram_page; int m_cru_register; bool m_tms9995_mode; + bool m_enable_io; + bool m_enable_int; + bool m_enable_sm; + bool m_write_flash; + UINT16 m_input_latch; UINT16 m_output_latch; UINT16* m_ram; + + // Link to the FEEPROM containing the DSR (driver) + required_device m_flash; }; #endif