ti99: Remove redundant variables; fix problem with TI FDC in Geneve where SIDSEL signal is lost when no drive is selected.

This commit is contained in:
Michael Zapf 2019-04-09 22:33:17 +02:00
parent e16e8ddfe5
commit 042bcdabe6
2 changed files with 70 additions and 67 deletions

View File

@ -19,12 +19,14 @@
#define LOG_WARN (1U<<1) // Warnings
#define LOG_CONFIG (1U<<2)
#define LOG_RW (1U<<3)
#define LOG_CRU (1U<<4)
#define LOG_READY (1U<<5)
#define LOG_SIGNALS (1U<<6)
#define LOG_DATA (1U<<7)
#define LOG_MOTOR (1U<<8)
#define LOG_ADDRESS (1U<<9)
#define LOG_PORTS (1U<<4) // too noisy in RW
#define LOG_CRU (1U<<5)
#define LOG_READY (1U<<6)
#define LOG_SIGNALS (1U<<7)
#define LOG_DRQ (1U<<8) // too noisy in SIGNALS
#define LOG_DATA (1U<<9)
#define LOG_MOTOR (1U<<10)
#define LOG_ADDRESS (1U<<11)
#define VERBOSE ( LOG_CONFIG | LOG_WARN )
#include "logmacro.h"
@ -46,13 +48,12 @@ ti_fdc_device::ti_fdc_device(const machine_config &mconfig, const char *tag, dev
m_address(0),
m_DRQ(0),
m_IRQ(0),
m_HLD(0),
m_crulatch(*this, "crulatch"),
m_DVENA(0),
m_inDsrArea(false),
m_WAITena(false),
m_WDsel(false),
m_DSEL(0),
m_SIDSEL(0),
m_motor_on_timer(nullptr),
m_fd1771(*this, FDC_TAG),
m_dsrrom(nullptr),
@ -66,15 +67,13 @@ ti_fdc_device::ti_fdc_device(const machine_config &mconfig, const char *tag, dev
void ti_fdc_device::operate_ready_line()
{
// This is the wait state logic
LOGMASKED(LOG_SIGNALS, "address=%04x, DRQ=%d, INTRQ=%d, MOTOR=%d\n", m_address & 0xffff, m_DRQ, m_IRQ, m_DVENA);
line_state nready = (m_WDsel && // Are we accessing 5ffx (even addr)?
m_WAITena && // and the wait state generation is active (SBO 2)
(m_DRQ==CLEAR_LINE) && // and we are waiting for a byte
(m_IRQ==CLEAR_LINE) && // and there is no interrupt yet
(m_DVENA==ASSERT_LINE) // and the motor is turning?
)? ASSERT_LINE : CLEAR_LINE; // In that case, clear READY and thus trigger wait states
LOGMASKED(LOG_READY, "READY line = %d\n", (nready==CLEAR_LINE)? 1:0);
LOGMASKED(LOG_READY, "Address=%04x, DRQ=%d, INTRQ=%d, MOTOR=%d -> READY=%d\n", m_address & 0xffff, m_DRQ, m_IRQ, m_DVENA, (nready==CLEAR_LINE)? 1:0);
m_slot->set_ready((nready==CLEAR_LINE)? ASSERT_LINE : CLEAR_LINE);
}
@ -91,10 +90,17 @@ WRITE_LINE_MEMBER( ti_fdc_device::fdc_irq_w )
WRITE_LINE_MEMBER( ti_fdc_device::fdc_drq_w )
{
m_DRQ = state? ASSERT_LINE : CLEAR_LINE;
LOGMASKED(LOG_SIGNALS, "DRQ callback = %d\n", m_DRQ);
LOGMASKED(LOG_DRQ, "DRQ callback = %d\n", m_DRQ);
operate_ready_line();
}
WRITE_LINE_MEMBER( ti_fdc_device::fdc_hld_w )
{
m_HLD = state? ASSERT_LINE : CLEAR_LINE;
LOGMASKED(LOG_SIGNALS, "HLD callback = %d\n", m_HLD);
}
// bool ti_fdc_device::dvena_r()
// {
// LOGMASKED(LOG_SIGNALS, "reading DVENA = %d\n", m_DVENA);
@ -111,7 +117,7 @@ SETADDRESS_DBIN_MEMBER( ti_fdc_device::setaddress_dbin )
if (!m_inDsrArea || !m_selected) return;
LOGMASKED(LOG_ADDRESS, "set address = %04x\n", offset & 0xffff);
LOGMASKED(LOG_ADDRESS, "Set address = %04x\n", offset & 0xffff);
// Is the WD chip on the card being selected?
m_WDsel = m_inDsrArea && ((m_address & 0x1ff1)==0x1ff0);
@ -150,18 +156,21 @@ READ8Z_MEMBER(ti_fdc_device::readz)
if (m_WDsel && ((m_address & 9)==0))
{
if (!machine().side_effects_disabled()) reply = m_fd1771->read((offset >> 1)&0x03);
LOGMASKED(LOG_PORTS, "%04x -> %02x\n", offset & 0xffff, reply);
}
else
{
reply = m_dsrrom[m_address & 0x1fff];
LOGMASKED(LOG_RW, "%04x -> %02x\n", offset & 0xffff, reply);
}
*value = reply;
LOGMASKED(LOG_RW, "%04x -> %02x\n", offset & 0xffff, *value);
}
}
void ti_fdc_device::write(offs_t offset, uint8_t data)
{
// As this is a memory-mapped access we must prevent the debugger
// from messing with the operation
if (machine().side_effects_disabled()) return;
if (m_inDsrArea && m_selected)
@ -175,12 +184,17 @@ void ti_fdc_device::write(offs_t offset, uint8_t data)
// flags may be reset by the read operation.
// Note that incoming/outgoing data are inverted for FD1771
LOGMASKED(LOG_RW, "%04x <- %02x\n", offset & 0xffff, ~data & 0xff);
if (m_WDsel && ((m_address & 9)==8))
if (m_WDsel)
{
// As this is a memory-mapped access we must prevent the debugger
// from messing with the operation
if (!machine().side_effects_disabled()) m_fd1771->write((offset >> 1)&0x03, data);
if ((m_address & 9)==8)
{
m_fd1771->write((offset >> 1)&0x03, data);
LOGMASKED(LOG_PORTS, "%04x <- %02x\n", offset & 0xffff, ~data & 0xff);
}
else
{
LOGMASKED(LOG_RW, "%04x <- %02x (ignored)\n", m_address & 0xffff, ~data & 0xff);
}
}
}
}
@ -190,30 +204,31 @@ void ti_fdc_device::write(offs_t offset, uint8_t data)
7 6 5 4 3 2 1 0
+-----+-----+-----+------+-----+-----+-----+-----+
| Side| 1 | 0 |DVENA*| DSK3| DSK2| DSK1| HLD |
| Side| 1 | 0 |DVENA*| D3C*| D2C*| D1C*| HLD |
+-----+-----+-----+------+-----+-----+-----+-----+
We have only 8 bits for query; within this implementation this means
we only use the base address (offset 0).
See schematics for the meaning of the bits.
*/
READ8Z_MEMBER(ti_fdc_device::crureadz)
{
if ((offset & 0xff00)==m_cru_base)
{
uint8_t reply = 0;
if ((offset & 0x0070) == 0)
{
// Selected drive
reply |= ((m_DSEL)<<1);
// The DVENA state is returned as inverted
if (m_DVENA==CLEAR_LINE) reply |= 0x10;
// Always 1
reply |= 0x40;
// Selected side
if (m_SIDSEL==ASSERT_LINE) reply |= 0x80;
switch ((offset >> 1) & 0x07)
{
case 0: *value = (m_HLD==ASSERT_LINE)? 1:0; break;
case 1: *value = (m_crulatch->q4_r()==ASSERT_LINE && m_DVENA==ASSERT_LINE)? 1:0; break;
case 2: *value = (m_crulatch->q5_r()==ASSERT_LINE && m_DVENA==ASSERT_LINE)? 1:0; break;
case 3: *value = (m_crulatch->q6_r()==ASSERT_LINE && m_DVENA==ASSERT_LINE)? 1:0; break;
case 4: *value = (m_DVENA==CLEAR_LINE)? 1:0; break;
case 5: *value = 0; break;
case 6: *value = 1; break;
case 7: *value = (m_crulatch->q7_r()==ASSERT_LINE)? 1:0; break;
}
}
*value = BIT(reply, (offset >> 1) & 0x07);
LOGMASKED(LOG_CRU, "Read CRU = %02x\n", *value);
else *value = 0;
LOGMASKED(LOG_CRU, "Read CRU %04x = %02x\n", offset, *value);
}
}
@ -235,7 +250,7 @@ WRITE_LINE_MEMBER(ti_fdc_device::kaclk_w)
// Activate motor
if (state)
{ // On rising edge, set motor_running for 4.23s
LOGMASKED(LOG_CRU, "trigger motor (bit 1)\n");
LOGMASKED(LOG_CRU, "Trigger motor (bit 1)\n");
set_floppy_motors_running(true);
}
}
@ -248,32 +263,25 @@ WRITE_LINE_MEMBER(ti_fdc_device::waiten_w)
// OR the motor stops rotating - rotates for 4.23s after write
// to CRU bit 1
m_WAITena = state;
LOGMASKED(LOG_CRU, "arm wait state logic (bit 2) = %d\n", state);
LOGMASKED(LOG_CRU, "Arm wait state logic (bit 2) = %d\n", state);
}
WRITE_LINE_MEMBER(ti_fdc_device::hlt_w)
{
// Load disk heads (HLT pin) (bit 3). Not implemented.
LOGMASKED(LOG_CRU, "set head load (bit 3) = %d\n", state);
}
WRITE_LINE_MEMBER(ti_fdc_device::dsel_w)
{
m_DSEL = m_crulatch->q4_r() | (m_crulatch->q5_r() << 1) | (m_crulatch->q6_r() << 2);
set_drive();
LOGMASKED(LOG_CRU, "Set head load (bit 3) = %d\n", state);
}
WRITE_LINE_MEMBER(ti_fdc_device::sidsel_w)
{
// Select side of disk (bit 7)
m_SIDSEL = state ? ASSERT_LINE : CLEAR_LINE;
LOGMASKED(LOG_CRU, "set side (bit 7) = %d\n", state);
LOGMASKED(LOG_CRU, "Set side (bit 7) = %d\n", state);
if (m_current != NONE) m_floppy[m_current]->ss_w(state);
}
void ti_fdc_device::set_drive()
WRITE_LINE_MEMBER(ti_fdc_device::dsel_w)
{
int dsel = m_DSEL;
int dsel = m_crulatch->q4_r() | (m_crulatch->q5_r() << 1) | (m_crulatch->q6_r() << 2);
// If the selected floppy drive is not attached, remove that line
if (m_floppy[2] == nullptr) dsel &= 0x03; // 011
@ -284,7 +292,7 @@ void ti_fdc_device::set_drive()
{
case 0:
m_current = NONE;
LOGMASKED(LOG_CRU, "all drives deselected\n");
LOGMASKED(LOG_CRU, "All drives deselected\n");
break;
case 1:
m_current = 0;
@ -306,9 +314,18 @@ void ti_fdc_device::set_drive()
LOGMASKED(LOG_WARN, "Warning - multiple drives selected\n");
break;
}
LOGMASKED(LOG_CRU, "new DSEL = %d\n", m_DSEL);
LOGMASKED(LOG_CRU, "New DSEL = %d\n", dsel);
m_fd1771->set_floppy((m_current == NONE)? nullptr : m_floppy[m_current]);
if (m_current != NONE)
{
// When a new drive is selected, propagate the SIDSEL signal to that drive
m_fd1771->set_floppy(m_floppy[m_current]);
m_floppy[m_current]->ss_w(m_crulatch->q7_r());
}
else
{
m_fd1771->set_floppy(nullptr);
}
}
/*
@ -362,8 +379,6 @@ void ti_fdc_device::device_start()
save_item(NAME(m_inDsrArea));
save_item(NAME(m_WAITena));
save_item(NAME(m_WDsel));
save_item(NAME(m_DSEL));
save_item(NAME(m_SIDSEL));
save_item(NAME(m_current));
}
@ -384,7 +399,6 @@ void ti_fdc_device::device_reset()
m_DVENA = CLEAR_LINE;
m_fd1771->set_force_ready(false);
m_DSEL = 0;
m_WAITena = false;
m_selected = false;
m_inDsrArea = false;
@ -433,6 +447,7 @@ void ti_fdc_device::device_add_mconfig(machine_config& config)
FD1771(config, m_fd1771, 1_MHz_XTAL);
m_fd1771->intrq_wr_callback().set(FUNC(ti_fdc_device::fdc_irq_w));
m_fd1771->drq_wr_callback().set(FUNC(ti_fdc_device::fdc_drq_w));
m_fd1771->hld_wr_callback().set(FUNC(ti_fdc_device::fdc_hld_w));
FLOPPY_CONNECTOR(config, "0", tifdc_floppies, "525dd", ti_fdc_device::floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, "1", tifdc_floppies, "525dd", ti_fdc_device::floppy_formats).enable_sound(true);

View File

@ -51,6 +51,7 @@ private:
DECLARE_WRITE_LINE_MEMBER(fdc_irq_w);
DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
DECLARE_WRITE_LINE_MEMBER(fdc_hld_w);
DECLARE_WRITE_LINE_MEMBER(dskpgena_w);
DECLARE_WRITE_LINE_MEMBER(kaclk_w);
@ -65,17 +66,14 @@ private:
// Wait state logic
void operate_ready_line();
// Set the current floppy
void set_drive();
// Operate the floppy motors
void set_floppy_motors_running(bool run);
// Recent address
int m_address;
// Holds the status of the DRQ and IRQ lines.
int m_DRQ, m_IRQ;
// Holds the status of the DRQ, IRQ, and HLD lines.
int m_DRQ, m_IRQ, m_HLD;
// Latched CRU outputs
required_device<ls259_device> m_crulatch;
@ -92,16 +90,6 @@ private:
// WD chip selected
bool m_WDsel;
// Indicates which drive has been selected. Values are 0, 1, 2, and 4.
// 000 = no drive
// 001 = drive 1
// 010 = drive 2
// 100 = drive 3
int m_DSEL;
// Signal SIDSEL. 0 or 1, indicates the selected head.
int m_SIDSEL;
// count 4.23s from rising edge of motor_on
emu_timer* m_motor_on_timer;