-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Tek4404 wip #14519
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Tek4404 wip #14519
Changes from all commits
0d1a642
eac5313
49be4d1
162cc78
3e906ff
3e5c404
deb3f44
53d07b3
8207717
cbd4240
2929d2c
744f40d
a0631b0
c19e41f
586dced
6007ec8
7dfcf70
d241e46
5a10bcc
ae502d5
04701f0
99917da
1fbbba5
c559103
be58a32
20d4b2f
ff57abd
24891bb
4dc1ee1
7d27942
8f6cfa4
acdaa96
9695738
61c43ff
625d409
da05f4b
51d98b8
e9df650
965657a
6be1e38
c6b77d6
bded0ef
00b3dae
581b8e5
49fae5c
defabf0
6ef13fb
7db1c78
aa58d88
77bef29
aeab71c
1f7bc6b
bb8647c
f4c955d
62fc6fd
648cd5a
4a41077
7f9e1ea
c45703f
fba5c28
17bbbc5
b3e1adf
bc9e295
12d31d7
1a247e4
90cf3be
c3f52a2
5f3fef7
9796643
5879363
4ef6b4d
54b3e10
28a41e5
c135ba6
e737ea2
5cc28f1
877c146
2b4181f
1045ab4
0713abe
67af90f
7d1e33b
b576ffd
78bf13a
7026abe
3cab62b
8213145
55cbcd7
9c0857e
b6dfc78
049f4e4
df59ee3
6ba8bc6
7486538
0e1b304
711c2e0
4695fb1
f659865
b808b09
41bb1db
2b0bc46
e512354
9e2f0b0
a5b18bf
09cdb3a
3411ec3
5abc6c3
8faa18d
9c45c03
fa568ee
06b3cb7
46189e0
9fd3202
31d8b74
2b9c6ed
73147af
67d174b
3aaa83c
2712deb
9824f68
ddf726a
c1b2bea
76091ef
86deee9
c9417bb
443c4bd
be7a510
4a834b9
493093f
f655b90
f7dcbaa
b9c8c64
51973a7
320a0f9
dffd0e1
33f5da2
57b577d
65c62b1
bb73f1f
babbfa2
365801f
e8381f6
46b70eb
4085647
a278694
1765cff
99da289
00012e4
ec9f806
e1bf628
01e9460
63a407b
cbb2cca
b30367e
687b7f0
dc18e76
7de4e4e
4033730
4d40fea
6558c3c
fa5e435
654fbe6
87a26f5
5487388
a998398
720d8ab
ff30d07
e03b198
06b39fd
3ff44ca
9c89615
f594e0b
fd833e3
5b670a8
8a90825
e3696d3
62f1ba5
cefb0a6
6d270c1
6b4a9d7
29e51fa
7480bf3
1e28766
34e5823
3a15aff
4f4906f
10c6993
211b6d5
3d36743
7749d65
186ba4a
7243289
d2baa16
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,38 @@ | |
| * - disconnect/reselection | ||
| */ | ||
|
|
||
|
|
||
| // REQUIRED delay for tek4404 to write successfully | ||
|
|
||
| // Tek4404 expects to be able to call 2 functions that clear any pending state and setup an | ||
| // internal flag *BEFORE* the IRQ generated by XFI_OUT_ACK is received. Without this delay the IRQ arrives | ||
| // before the setup has been executed and IRQ handler fails to process the interrupt. => HANGS | ||
| // A correctly functioning call sequence looks like this: | ||
|
|
||
| // SCSI_wait | ||
| // scsi_update_pending_flags | ||
| // IRQ3_handler_scsi | ||
| // scsi_read_ncr5385_status | ||
|
|
||
| // A broken call sequence looks like this (note the setup functions are run too late) | ||
|
|
||
| // IRQ3_handler_scsi | ||
| // scsi_read_ncr5385_status | ||
| // SCSI_wait | ||
| // scsi_update_pending_flags | ||
|
|
||
| // scsi write code is ~90 cycles / loop | ||
|
|
||
| // then ~240 cycles before setting SR |= 0700 | ||
|
|
||
| // IRQ6 occasionally arrives between end of scsi write code and getting IRQ3. unclear why it isn't masked out. | ||
|
|
||
| // 40us | ||
| unsigned constexpr TEK4404_XFI_OUT_ACK_DELAY = 10'000; | ||
|
|
||
| // define USE_TEK4404_CHANGES to work on tek4404 driver | ||
|
|
||
|
|
||
| #include "emu.h" | ||
| #include "ncr5385.h" | ||
|
|
||
|
|
@@ -162,25 +194,35 @@ void ncr5385_device::device_reset() | |
| update_int(); | ||
| } | ||
|
|
||
| attotime ncr5385_device::scsi_data_byte_period() | ||
| { | ||
| #ifdef USE_TEK4404_CHANGES | ||
| return attotime::from_nsec(200); | ||
| #else | ||
| return attotime::zero; | ||
| #endif | ||
| } | ||
|
|
||
| void ncr5385_device::scsi_ctrl_changed() | ||
| { | ||
| u32 const ctrl = scsi_bus->ctrl_r(); | ||
|
|
||
| static char const *const nscsi_phase[] = { "DATA OUT", "DATA IN", "COMMAND", "STATUS", "*", "*", "MESSAGE OUT", "MESSAGE IN" }; | ||
|
|
||
| if ((ctrl & S_BSY) && !(ctrl & S_SEL)) | ||
| if (ctrl & S_BSY) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have previously suggested this change, and I confirm it's good; I think this is the only change required to ncr5385.cpp. |
||
| { | ||
| LOGMASKED(LOG_STATE, "scsi_ctrl_changed 0x%03x phase %s%s%s\n", ctrl, nscsi_phase[ctrl & S_PHASE_MASK], | ||
| ctrl & S_REQ ? " REQ" : "", ctrl & S_ACK ? " ACK" : ""); | ||
| if (ctrl & S_SEL) | ||
| LOGMASKED(LOG_STATE, "%10s: scsi_ctrl_changed 0x%03x arbitration/selection\n", machine().time().as_string(8), ctrl); | ||
| else | ||
| LOGMASKED(LOG_STATE, "%10s: scsi_ctrl_changed 0x%03x phase %s%s%s\n", machine().time().as_string(8), ctrl, nscsi_phase[ctrl & S_PHASE_MASK], | ||
| ctrl & S_REQ ? " REQ" : "", ctrl & S_ACK ? " ACK" : ""); | ||
|
|
||
| if (m_state != IDLE) | ||
| m_state_timer->adjust(attotime::zero); | ||
| m_state_timer->adjust(attotime::from_usec(80)); | ||
| } | ||
| else if (ctrl & S_BSY) | ||
| LOGMASKED(LOG_STATE, "scsi_ctrl_changed 0x%03x arbitration/selection\n", ctrl); | ||
| else | ||
| { | ||
| LOGMASKED(LOG_STATE, "scsi_ctrl_changed 0x%03x BUS FREE\n", ctrl); | ||
| LOGMASKED(LOG_STATE, "%10s: scsi_ctrl_changed 0x%03x BUS FREE\n", machine().time().as_string(8), ctrl); | ||
|
|
||
| if (m_mode == INITIATOR) | ||
| { | ||
|
|
@@ -253,7 +295,7 @@ u8 ncr5385_device::aux_status_r() | |
| if (ctrl & S_INP) | ||
| data |= AUX_STATUS_IO; | ||
| } | ||
| LOGMASKED(LOG_REGR, "aux_status_r 0x%02x (%s)\n", data, machine().describe_context()); | ||
| LOGMASKED(LOG_REGR, "%10s: aux_status_r 0x%02x (%s)\n", machine().time().as_string(8), data, machine().describe_context()); | ||
|
|
||
| return data; | ||
| } | ||
|
|
@@ -266,7 +308,7 @@ u8 ncr5385_device::own_id_r() | |
| u8 ncr5385_device::int_status_r() | ||
| { | ||
| u8 const data = m_int_status; | ||
| LOGMASKED(LOG_REGR, "int_status_r 0x%02x (%s)\n", data, machine().describe_context()); | ||
| LOGMASKED(LOG_REGR, "%10s: int_status_r 0x%02x (%s)\n", machine().time().as_string(8), data, machine().describe_context()); | ||
| m_aux_status &= ~AUX_STATUS_PARITY_ERR; | ||
| m_int_status = 0; | ||
| update_int(); | ||
|
|
@@ -315,7 +357,7 @@ void ncr5385_device::dat_w(u8 data) | |
|
|
||
| void ncr5385_device::cmd_w(u8 data) | ||
| { | ||
| LOGMASKED(LOG_REGW, "cmd_w 0x%02x (%s)\n", data, machine().describe_context()); | ||
| LOGMASKED(LOG_REGW, "%10s: cmd_w 0x%02x (%s)\n", machine().time().as_string(8), data, machine().describe_context()); | ||
| if (!(data & 0x18)) | ||
| { | ||
| // immediate commands | ||
|
|
@@ -449,6 +491,8 @@ template <unsigned N> void ncr5385_device::cnt_w(u8 data) | |
| m_aux_status &= ~AUX_STATUS_TC_ZERO; | ||
| else | ||
| m_aux_status |= AUX_STATUS_TC_ZERO; | ||
|
|
||
| LOGMASKED(LOG_REGW, "%10s: cnt_w %d (%d) \n", machine().time().as_string(8), m_cnt, N); | ||
| } | ||
|
|
||
| void ncr5385_device::tst_w(u8 data) | ||
|
|
@@ -556,7 +600,7 @@ int ncr5385_device::state_step() | |
| break; | ||
|
|
||
| case SEL_START: | ||
| LOGMASKED(LOG_STATE, "selection: SEL asserted\n"); | ||
| LOGMASKED(LOG_STATE, "%10s: selection: SEL asserted\n", machine().time().as_string(8)); | ||
| m_state = SEL_DELAY; | ||
| delay = SCSI_BUS_SKEW * 2; | ||
|
|
||
|
|
@@ -578,7 +622,7 @@ int ncr5385_device::state_step() | |
| case SEL_WAIT_BSY: | ||
| if (ctrl & S_BSY) | ||
| { | ||
| LOGMASKED(LOG_STATE, "selection: BSY asserted by target\n"); | ||
| LOGMASKED(LOG_STATE, "%10s: selection: BSY asserted by target\n", machine().time().as_string(8)); | ||
| m_state = SEL_COMPLETE; | ||
| delay = SCSI_BUS_SKEW * 2; | ||
| } | ||
|
|
@@ -594,7 +638,7 @@ int ncr5385_device::state_step() | |
| } | ||
| break; | ||
| case SEL_COMPLETE: | ||
| LOGMASKED(LOG_STATE, "selection: complete\n"); | ||
| LOGMASKED(LOG_STATE, "%10s: selection: complete\n", machine().time().as_string(8)); | ||
| m_int_status |= INT_FUNC_COMPLETE; | ||
| m_mode = INITIATOR; | ||
| m_state = SEL_WAIT_REQ; | ||
|
|
@@ -610,7 +654,7 @@ int ncr5385_device::state_step() | |
| // don't generate bus service interrupt until the function complete is cleared | ||
| if ((ctrl & S_REQ) && !m_int_state) | ||
| { | ||
| LOGMASKED(LOG_STATE, "selection: REQ asserted by target\n"); | ||
| LOGMASKED(LOG_STATE, "%10s: selection: REQ asserted by target\n", machine().time().as_string(8)); | ||
| m_int_status |= INT_BUS_SERVICE; | ||
| m_state = IDLE; | ||
|
|
||
|
|
@@ -647,7 +691,7 @@ int ncr5385_device::state_step() | |
| } | ||
| else | ||
| { | ||
| LOGMASKED(LOG_STATE, "xfi_in: %s\n", remaining() ? "phase change" : "transfer complete"); | ||
| //LOGMASKED(LOG_STATE, "xfi_in: %s\n", remaining() ? "phase change" : "transfer complete"); | ||
|
|
||
| m_int_status |= INT_BUS_SERVICE; | ||
| m_state = IDLE; | ||
|
|
@@ -661,7 +705,7 @@ int ncr5385_device::state_step() | |
| case XFI_IN_DRQ: | ||
| m_state = XFI_IN_ACK; | ||
|
|
||
| LOGMASKED(LOG_STATE, "xfi_in: data 0x%02x\n", m_dat); | ||
| //LOGMASKED(LOG_STATE, "%10s: xfi_in: data 0x%02x\n", machine().time().as_string(8), m_dat); | ||
|
|
||
| // assert ACK | ||
| scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK); | ||
|
|
@@ -675,7 +719,7 @@ int ncr5385_device::state_step() | |
| { | ||
| m_cnt--; | ||
|
|
||
| LOGMASKED(LOG_STATE, "xfi_in: %d remaining\n", m_cnt); | ||
| //LOGMASKED(LOG_STATE, "%10s: xfi_in: %d remaining\n", machine().time().as_string(8), m_cnt); | ||
|
|
||
| if (!m_cnt) | ||
| m_aux_status |= AUX_STATUS_TC_ZERO; | ||
|
|
@@ -686,6 +730,8 @@ int ncr5385_device::state_step() | |
| // clear ACK except after last byte of message input phase | ||
| if (!remaining() && (ctrl & S_PHASE_MASK) == S_PHASE_MSG_IN) | ||
| { | ||
| //LOGMASKED(LOG_STATE, "xfi_in: INT_FUNC_COMPLETE\n" ); | ||
|
|
||
| m_int_status |= INT_FUNC_COMPLETE; | ||
| m_state = IDLE; | ||
|
|
||
|
|
@@ -715,7 +761,8 @@ int ncr5385_device::state_step() | |
| } | ||
| else | ||
| { | ||
| LOGMASKED(LOG_STATE, "xfi_out: %s\n", remaining() ? "phase change" : "transfer complete"); | ||
| LOGMASKED(LOG_STATE, "%10s: xfi_out: %s\n", machine().time().as_string(8), remaining() ? "phase change" : "transfer complete"); | ||
|
|
||
| m_int_status |= INT_BUS_SERVICE; | ||
| m_state = IDLE; | ||
|
|
||
|
|
@@ -725,11 +772,12 @@ int ncr5385_device::state_step() | |
| else | ||
| delay = -1; | ||
| break; | ||
|
|
||
| case XFI_OUT_DRQ: | ||
| m_state = XFI_OUT_ACK; | ||
| m_aux_status &= ~AUX_STATUS_DATA_FULL; | ||
|
|
||
| LOGMASKED(LOG_STATE, "xfi_out: data 0x%02x\n", m_dat); | ||
| LOGMASKED(LOG_STATE, "%10s: xfi_out: data 0x%02x\n", machine().time().as_string(8), m_dat); | ||
|
|
||
| // assert data and ACK | ||
| scsi_bus->data_w(scsi_refid, m_dat); | ||
|
|
@@ -750,7 +798,7 @@ int ncr5385_device::state_step() | |
| { | ||
| m_cnt--; | ||
|
|
||
| LOGMASKED(LOG_STATE, "xfi_out: %d remaining\n", m_cnt); | ||
| LOGMASKED(LOG_STATE, "%10s: xfi_out: %d remaining\n", machine().time().as_string(8), m_cnt); | ||
|
|
||
| if (!m_cnt) | ||
| m_aux_status |= AUX_STATUS_TC_ZERO; | ||
|
|
@@ -761,6 +809,36 @@ int ncr5385_device::state_step() | |
| // clear data and ACK | ||
| scsi_bus->data_w(scsi_refid, 0); | ||
| scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); | ||
|
|
||
| if (m_cnt == 0) | ||
| { | ||
| #ifdef USE_TEK4404_CHANGES | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've tested simulating a slow hard disk instead of this change, and it can successfully complete the "diskrepair" and reach a login prompt. I don't have the knowledge of this system to test further, but I believe this change is wrong and the delay occur in the target, not this device. |
||
| // REQUIRED delay for tek4404 to write successfully | ||
|
|
||
| // Tek4404 expects to be able to call 2 functions that clear any pending state and setup an | ||
| // internal flag *BEFORE* the IRQ generated here is received. Without this delay the IRQ arrives | ||
| // before the setup has been executed and IRQ handler fails to process the interrupt. | ||
| // A correctly functioning call sequence looks like this: | ||
|
|
||
| // set_flags_handling_clear_pending | ||
| // scsi_update_pending_flags | ||
| // IRQ3_handler_scsi | ||
| // scsi_read_ncr5385_status | ||
|
|
||
| // A broken call sequence looks like this (note the setup functions are run too late) | ||
|
|
||
| // IRQ3_handler_scsi | ||
| // scsi_read_ncr5385_status | ||
| // set_flags_handling_clear_pending | ||
| // scsi_update_pending_flags | ||
|
|
||
| // scsi write code is ~90 cycles / loop | ||
|
|
||
| delay = TEK4404_XFI_OUT_ACK_DELAY; | ||
| LOGMASKED(LOG_STATE, "%10s: XFI_OUT_ACK delay %d\n", machine().time().as_string(8), delay); | ||
| #endif | ||
| } | ||
|
|
||
| } | ||
| else | ||
| delay = -1; | ||
|
|
@@ -773,7 +851,7 @@ int ncr5385_device::state_step() | |
| m_state = XFI_OUT_DRQ; | ||
| else | ||
| { | ||
| LOGMASKED(LOG_STATE, "xfi_out: %s\n", remaining() ? "phase change" : "transfer complete"); | ||
| LOGMASKED(LOG_STATE, "%10s: xfi_out: %s\n", machine().time().as_string(8), remaining() ? "phase change" : "transfer complete"); | ||
| m_int_status |= INT_BUS_SERVICE; | ||
| m_state = IDLE; | ||
|
|
||
|
|
@@ -821,7 +899,7 @@ void ncr5385_device::update_int() | |
|
|
||
| if (m_int_state != int_state) | ||
| { | ||
| LOG("update_int %d\n", int_state); | ||
| LOG("%10s: update_int %d\n", machine().time().as_string(8), int_state); | ||
|
|
||
| m_aux_status &= ~(AUX_STATUS_MSG | AUX_STATUS_CD | AUX_STATUS_IO); | ||
| if (int_state) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -63,6 +63,7 @@ class ncr5385_device | |
| virtual void device_reset() override ATTR_COLD; | ||
|
|
||
| // ncsci_device implementation | ||
| virtual attotime scsi_data_byte_period(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How this is not overriding the base method and manages to compile anyway? Is this |
||
| virtual void scsi_ctrl_changed() override; | ||
|
|
||
| // read handlers | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -204,8 +204,10 @@ void device_serial_interface::set_data_frame(int start_bit_count, int data_bit_c | |
| { | ||
| m_rcv_bit_count++; | ||
| } | ||
|
|
||
| #ifndef USE_TEK4404_CHANGES | ||
| receive_register_reset(); | ||
| #endif | ||
|
Comment on lines
+207
to
+209
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of hacking diserial, do this: index dbefa1507be..e19716e8661 100644
--- a/src/devices/machine/mc68681.cpp
+++ b/src/devices/machine/mc68681.cpp
@@ -1641,6 +1641,7 @@ void duart_channel::write_chan_reg(int reg, uint8_t data)
void duart_channel::write_MR(uint8_t data)
{
+ bool const frame_change = (MR_ptr == 0) ? ((MR1 ^ data) & 0x1f) : ((MR2 ^ data) & 0x0f);
if (MR_ptr == 0)
{
MR1 = data;
@@ -1650,7 +1651,8 @@ void duart_channel::write_MR(uint8_t data)
{
MR2 = data;
}
- recalc_framing();
+ if (frame_change)
+ recalc_framing();
update_interrupts();
}``` |
||
|
|
||
| } | ||
|
|
||
| void device_serial_interface::receive_register_reset() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| <?xml version="1.0"?> | ||
| <!-- | ||
| license:CC0-1.0 | ||
| authors: Elektraglide | ||
|
|
||
| Tektronix 4404 Artificial Intelligence System. | ||
| --> | ||
| <mamelayout version="2"> | ||
| <element name="static_black"><rect><color red="0.0" green="0.0" blue="0.0" /></rect></element> | ||
| <element name="led_round" defstate="1"> | ||
| <disk state="1"> | ||
| <color red="0.2" green="0.0" blue="0.0" /> | ||
| </disk> | ||
| <disk state="0"> | ||
| <color red="1.0" green="0.0" blue="0.0" /> | ||
| </disk> | ||
| </element> | ||
| <element name="led_rect" defstate="1"> | ||
| <rect state="1"> | ||
| <color red="0.2" green="0.0" blue="0.0" /> | ||
| </rect> | ||
| <rect state="0"> | ||
| <color red="1.0" green="0.1" blue="0.1" /> | ||
| </rect> | ||
| </element> | ||
| <view name="Graphics"> | ||
| <bounds x="0" y="0" width="640" height="496" /> | ||
|
|
||
| <screen index="0"> | ||
| <bounds x="0" y="0" width="640" height="480" /> | ||
| </screen> | ||
| <element name="spacer" ref="static_black"> | ||
| <bounds x="0" y="480" width="640" height="16" /> | ||
| </element> | ||
|
|
||
| <element name="led_1" ref="led_round"> | ||
| <bounds x="46" y="484" width="8" height="8" /> | ||
| </element> | ||
| <element name="led_2" ref="led_round"> | ||
| <bounds x="34" y="484" width="8" height="8" /> | ||
| </element> | ||
| <element name="led_4" ref="led_round"> | ||
| <bounds x="22" y="484" width="8" height="8" /> | ||
| </element> | ||
| <element name="led_8" ref="led_round"> | ||
| <bounds x="10" y="484" width="8" height="8" /> | ||
| </element> | ||
| <element name="led_disk" ref="led_rect"> | ||
| <bounds x="614" y="485" width="16" height="6" /> | ||
| </element> | ||
| </view> | ||
| </mamelayout> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hate C/C++ compile switches with a passion.
attotime::zerois a fallback that obviously needs changing depending on the controller needs.Also: where this magic number comes from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change does not make sense and will have no effect;
ncr5385_deviceis not derived fromnscsi_full_device.