(MESS) Modernized StrataFlash device. (nw)

This commit is contained in:
Michael Zapf 2014-03-12 13:13:10 +00:00
parent 9ebd171738
commit e7868ca66f
4 changed files with 435 additions and 412 deletions

View File

@ -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<strataflash_device *>(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::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; i<strata->wrbuf_len; i++)
strata->data_ptr[BYTE_XOR_LE(strata->wrbuf_base+i)] &= strata->wrbuf[i];
strata->mode = FM_READSTATUS;
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(strata, offset >> 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);
}

View File

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

View File

@ -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_image_device>("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 )

View File

@ -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<strataflash_device> m_flash;
};
#endif