Skip to content
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

Tek4404 work_in_progress. #12574

Open
wants to merge 99 commits into
base: master
Choose a base branch
from

Conversation

Elektraglide
Copy link
Contributor

@Elektraglide Elektraglide commented Jul 14, 2024

This is a WIP getting Tek4404 to run.
It now passes all the h/w tests apart from mouse. ( RAM, MMU, Serial, Timers, Sound, Video, Storage Devices)
A boot manages to load the OS from "system.boot", starts up and tries to write some swap data. After writing 512 bytes, it never receives a STATUS ACK and just spins forever running the idle job and checking whether the write has completed.

It implements a derived ncr5385 that drives an LED for disk activity

I do not have the knowledge around scsi and new_scsi_bus to understand what the emulated devices are not doing that Tek4404 expects, so this is where I have got to. Very close but no cigar.

@rb6502
Copy link
Contributor

rb6502 commented Jul 14, 2024

Can you fix the conflicts with the already-merged ncr5385 changes?

@Elektraglide
Copy link
Contributor Author

DATA IN finishes with a STATUS REQ shown below

[:scsi:7:led_ncr5385] scsi_ctrl_changed 0x029 phase DATA IN REQ
[:scsi:7:led_ncr5385] aux_status_r 0x88 (':maincpu' (747ADC))
[:scsi:7:led_ncr5385] xfi_in: data 0x75
[:scsi:7:led_ncr5385] scsi_ctrl_changed 0x049 phase DATA IN ACK
[:scsi:7:led_ncr5385] xfi_in: 0 remaining
[:scsi:7:led_ncr5385] scsi_ctrl_changed 0x00b phase STATUS
[:scsi:7:led_ncr5385] scsi_ctrl_changed 0x02b phase STATUS REQ
[:scsi:7:led_ncr5385] xfi_in: transfer complete
[:scsi:7:led_ncr5385] update_int 1
[:scsi:7:led_ncr5385] update_int 1  pc((no context))
[:scsi:7:led_ncr5385] aux_status_r 0x1a (':maincpu' (747E12))			<=  AUX_STATUS_CD | AUX_STATUS_IO | AUX_STATUS_PAUSED??
[:scsi:7:led_ncr5385] int_status_r 0x02 (':maincpu' (747E18))
[:scsi:7:led_ncr5385] update_int 0
[:scsi:7:led_ncr5385] update_int 0  pc(':maincpu' (747E18))
[:scsi:7:led_ncr5385] cmd_w 0x54 (':maincpu' (747964))
[:scsi:7:led_ncr5385] transfer info (pio, single byte)
[:scsi:7:led_ncr5385] aux_status_r 0x9a (':maincpu' (747CD0))
[:scsi:7:led_ncr5385] xfi_in: data 0x00
[:scsi:7:led_ncr5385] scsi_ctrl_changed 0x04b phase STATUS ACK

DATA OUT finishes with a STATUS REQ shown below and never gets a STATUS ACK

[:scsi:7:led_ncr5385] scsi_ctrl_changed 0x028 phase DATA OUT REQ
[:scsi:7:led_ncr5385] aux_status_r 0x00 (':maincpu' (01258C))
[:scsi:7:led_ncr5385] dat_w 0x00 (':maincpu' (01259C))
[:scsi:7:led_ncr5385] xfi_out: data 0x00
[:scsi:7:led_ncr5385] scsi_ctrl_changed 0x048 phase DATA OUT ACK
[:scsi:7:led_ncr5385] xfi_out: 0 remaining
[:scsi:7:led_ncr5385] scsi_ctrl_changed 0x00b phase STATUS
[:scsi:7:led_ncr5385] scsi_ctrl_changed 0x02b phase STATUS REQ
[:scsi:7:led_ncr5385] xfi_out: transfer complete
[:scsi:7:led_ncr5385] update_int 1
[:scsi:7:led_ncr5385] update_int 1  pc((no context))
[:scsi:7:led_ncr5385] aux_status_r 0x1a (':maincpu' (012844))			<= why is the same as for a READ?
[:scsi:7:led_ncr5385] int_status_r 0x02 (':maincpu' (01284E))
[:scsi:7:led_ncr5385] update_int 0
[:scsi:7:led_ncr5385] update_int 0  pc(':maincpu' (01284E))
[:scsi:7:led_ncr5385] aux_status_r 0x1a (':maincpu' (012866))

Copy link
Contributor

@pmackinlay pmackinlay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a few stray blank lines, some possible accidental whitespace changes, and some instances of inconsistent formatting that should be cleaned up prior to merging, but since this is a WIP asking for assistance, I haven't tried to nitpick those here.

m_screen(*this, "screen"),
m_acia(*this, "acia"),
m_printer(*this, "printer"),
m_prom(*this, "maincpu"), // FIXME why is the bootrom called 'maincpu'?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The region can be called anything, it just needs to match the name given in the ROM_REGION macro, and the parameter to the .region() function in the memory map.

m_led_1(*this, "led_1"),
m_led_2(*this, "led_2"),
m_led_4(*this, "led_4"),
m_led_8(*this, "led_8"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to combine these into a single output_finder<4>, and use the m_led(*this, "led_%u", 0U) syntax here, and m_led[N] = ...; elsewhere.

m_led_8.resolve();

m_led_disk.resolve();
m_maincpu->space(AS_PROGRAM).install_write_tap(0x7be002, 0x7be003, "led_tap", [this](offs_t offset, u16 &data, u16 mem_mask) { m_led_disk = !BIT(data, 3);});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the tap is 16 bits wide and the ncr5385 is hooked up to the high byte on the bus, you should probably be testing bit 11 instead of bit 3 here.

}
}

u8 tek440x_state::rtc_r(offs_t offset)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's really an mc146818, then it's already in the machine config should be added to the memory map and these stubs won't be required.

@@ -245,6 +246,9 @@ u8 ncr5385_device::aux_status_r()

if (!m_int_status)
{
// AB mask out any bits
data &= ~(AUX_STATUS_MSG | AUX_STATUS_CD | AUX_STATUS_IO);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be necessary; resetting and latching of these bits should be properly controlled by changes to the interrupt status. Did you find a bug in the logic?

// clear data and ACK
scsi_bus->data_w(scsi_refid, 0);
scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
#else
// clear ACK except after last byte of message output phase
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is correct; this logic only applies for the message input phase, to allow the initiator the chance to raise ATN to reject a message from the target if necessary. The same thing does not apply during message output.

Comment on lines 19 to 20

* 8255 Centronics printer interface

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indentation is way off here, and the blank line has trailing spaces.

Comment on lines 59 to 62
#include "machine/ncr5385.h"
#include "machine/ns32081.h"
#include "machine/i8255.h"
#include "machine/nscsi_bus.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep the #include statements for headers from src/devices sorted.

Comment on lines +74 to +89
// mapcntl bits
#define MAP_VM_ENABLE 4
#define MAP_SYS_WR_ENABLE 5
// mapcntrl result bits
#define MAP_BLOCK_ACCESS 6
#define MAP_CPU_WR 7

#define OFF8_TO_OFF16(A) ((A)>>1)
#define OFF16_TO_OFF8(A) ((A)<<1)

#define MAXRAM 0x200000 // +1MB
//#define MAXRAM 0x400000 // +3MB (which was never a Thing)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use cosntexpr variables and functions for these, there’s no need to use preprocessor macros.

Comment on lines +92 to +101
class m68010_tekmmu_device : public m68010_device
{
using m68010_device::m68010_device;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You’ll get a validity error if you do this because the device type for the instance won’t match what you instantiated it with.

Comment on lines 103 to 259
bool memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) override
{

target_space = &space(spacenum);

//if (m_emmu_enabled)
if (spacenum == AS_PROGRAM)
if ((get_fc() & 4) == 0) // only in User mode
if (BIT(*m_map_control, MAP_VM_ENABLE))
{
if (intention == TR_WRITE)
if (BIT(m_map[address >> 12], 14) == 0) // read only
{
LOG("memory_translate: write fail\n");
return false;
}

// dont try and translate a null page
if (BIT(m_map[address >> 12], 11, 3) != 0)
{
LOG("memory_translate: map %08x => paddr(%08x)\n",(address), (BIT(address, 0, 12) | (BIT(m_map[address >> 12], 0, 11) << 12) ) );

address = BIT(address, 0, 12) | (BIT(m_map[address >> 12], 0, 11) << 12);
}
}

return true;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation is off, and this style is confusing and error-prone. Just you know you can use && in the conditions for if statements.

Comment on lines 135 to 268
if (!buserror_occurred)
if (*m_map_control & (1 << MAP_BLOCK_ACCESS))
if ((get_fc() & 4) == 0) // only in User mode
if (BIT(*m_map_control, MAP_VM_ENABLE))
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here – please don’t use this style.

Comment on lines 187 to 212
u16 PTEread(offs_t address)
{
// selftest does a read and expects it to fail iff !MAP_SYS_WR_ENABLE; its not WR enable, its enable..
if (!BIT(*m_map_control, MAP_SYS_WR_ENABLE))
{
LOG("PTEread: bus error: PID(%d) %08x fc(%d) pc(%08x)\n", BIT(m_map[(address >> 12) & 0x7ff], 11, 3), (address), get_fc(), pc());
buserror_occurred = true;
set_buserror_details(address, 1, get_fc(), true);
return 0;
}

return m_map[(address>>12) & 0x7ff];
}

void PTEwrite(offs_t address, u16 data)
{
if (((address>>12) & 0x7ff) < 20)
LOG("PTEwrite: %08x <= %04x paddr(%08x) PID(%d) dirty(%d) write_enable(%d)\n",
(address>>12) & 0x7ff, data,
(BIT(data, 0, 12)<<12), BIT(data, 11, 3), data & 0x8000 ? 1 : 0, data & 0x4000 ? 1 : 0);

if (BIT(*m_map_control, MAP_SYS_WR_ENABLE))
{
m_map[(address>>12) & 0x7ff] = data;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation is off here:

  • These functions are at the left margin while the other inline member function bodies are indented.
  • You should use one level of indentation per nested scope level.
  • Please use braces for any multi-line if/else body even if it’s technically only a single statement.
  • Please indent statement continuations by two tabs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already explained on one of your previous pull requests why these logging changes are undesirable.

@@ -105,7 +105,7 @@ class m68010_tekmmu_device : public m68010_device

//if (m_emmu_enabled)
if (spacenum == AS_PROGRAM)
if ((get_fc() & 4) == 0) // only in User mode
if (!(m_s_flag & 4)) // only in User mode
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can't be right. External hardware like the MMU can't see the 68k's status register. Bit 2 of the FC lines determines user vs. supervisor, like you had it before.

@rb6502
Copy link
Contributor

rb6502 commented Nov 26, 2024

Is this in a state where we could look at getting it applied as a checkpoint?

Because it's very difficult to review a PR with this much churn I went and looked directly at your source branch, and I have a few notes. I think Vas touched on some of these already but I want to reiterate them.

  • Use LOGMASKED() so that logging can be controlled by category instead of being all or nothing.
  • Always use braces with if statements. memory_translate() and similar functions are very hard to track when you're reading them because of the lack of braces.
  • Because the Tektronix MMU is external to the 680x0 it should not be a superclass of the 68K core. I realize I set a poor example here with the Mac II and LC external MMUs so I won't hold that against merging this right now, but it's something to keep in mind for later. sun3.cpp is a better example of what an external 68K MMU should look like.

And addressing some comments I see in the code:

  • The boot prom is called "maincpu" because a ROM region with the same tag name as a CPU will inherit that CPU's endianness and bus width properties.
  • .mirror() is an inverse AND mask on the address. "1" bits in the .mirror() field are ignored when looking up the address.

Adam added 22 commits January 19, 2025 19:59
- some comments in trying to understand how to attach a target scsi device
- MAP_SYS_WR_ENABLE eppears to really mean read/write enable
- page table needs to be accessible without MAP_VM_ENABLE
- need to find a way of faking a connection so we can get debug output
- mouse position (gray codes?)  seems borked
…lftest now passes but not sure this is right solution

- Timer selftest fails; need a way of resetting interrupt when writing to 0x1xx
- hook writes to m_timer 0x1xx and clear IRQ1
- helped by Lord Nightmare; Interval Timer now passes
- added 8255 mapped to 0x7b2000 to handle Centronics interface;  not working
Adam added 29 commits January 19, 2025 19:59
- testing CMD_INT check is correct
- fixes runaway key repeating on input
- video panning not right
- not sure about FCMP / DCMP return values.
- added FGetStat and FSetStat to set ns32081 status register
- comment out log of every memory_r and memory_w
…e many things work

- what we actually want is a way of knowing its a prefetch memory_r()
- unsure if this is a Mac keyboard mapping issue or just wrong
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants