• Please review our updated Terms and Rules here

Early scsi emulation help

Elektraglide

Experienced Member
Joined
Mar 24, 2023
Messages
60
Location
UK
Iv'e decided to write a Tektronix 4404 emulator so everyone can experience Smalltalk-80 on a 68010.

I've started with Brad Parkers amazing sun2 emulator as its 68010, b/w display, MMU. So roughly similar, but much more sophisticated than tek4404.

So far the emulator starts (yay), prints some diagnostics:
Pegasus
% Adr: 00


..and tests memory, tests ACIA and DUART, clears the MMU pte and now its ready to start the SCSI disk.

I see it writing some 1 byte commands in order:
cmd=0 => disassembly of the boot rom shows it expects 0x80 reply to continue
cmd=1 => ??
cmd=255 => disassembly of the boot rom shows its expecting this to do an IRQ_3. I have no idea why.

While I have been writing low level stuff for decades I have not a clue what I am doing and no idea how you drive (early) scsi.
(I have written and shipped pure m68k assembly video games in the distant past and thought I knew m68k, yet the whole SFC and DFC register stuff was totally new to me.. Embarrassing)

ANY thoughts, suggestions as to how to approach this would be most appreciated!
 
the 4404 uses a Xebec 1410 controller, which is SASI, not SCSI, and very much not SCSI Common Command Set
4404 uses as Adaptec 4000 chipset for the controller. The minimal docs for 4404 do talk a lot about SCSI - is that just sloppy language?

I made my code always fire an IRQ for every write and now I get past Device Not Found and get Device Not Ready.

adaptec.png
 
can you dump the eprom on the adaptec? i'm really curious if they modified the firmware
which would mean it wouldn't match the adaptec docs
 
There are a few different levels required for this answer.

At the lowest level, a SCSI device is kind of intelligent. You send it commands (packets) and it response. The more common commands are read, write, seek, etc. The command packet structure evolved over the years so you have six byte, 10 bytes, and other variants of the packets. There are many other possible commands, some specialized, and not all used. You need a general model of a SCSI device that given an ID, read, or WRITE command generates results. The good news is that after the command gets to the device, it's a black box.

Then you need to model the controller. The controller is responsible for taking commands from the host (your OS) and translating them into SCSI commands for the device. At a really low level there are all sorts of bus transactions you can model, but the simple version is take an OS command and convert it to a SCSI command to be executed by a device. The controller will need to do things like keep the state of the current in-flight commands and possibly do some SCSI bus locking if you implement the more esoteric commands.

And then there is the host layer. Does the host form a structure in memory and then pass that to the controller? Is it in I/O space? What's the mechanism by which the controller interrupts the host when it is done?
 
There are a few different levels required for this answer.
...
And then there is the host layer. Does the host form a structure in memory and then pass that to the controller? Is it in I/O space? What's the mechanism by which the controller interrupts the host when it is done?
Yes, its all in some mapped I/O space. And this will be an emulator, so I just need to decode enough to go fetch blocks from a file - not a physical scsi device.

The sequence I see is:
scsi(007be002) write <= 00
scsi(007be012) read 1
scsi(007be002) write <= 01
scsi(007be002) write <= ff
scsi(007be008) read 1
scsi(007be00c) read 1

Then some MMU setup
MMU(00780000) <= 20
VirtualMem: DISABLE
Write Map Table: ENABLE
PTE pid: 00

<clear 2k of PTEs>

MMU(00780000) <= 00
VirtualMem: DISABLE
Write Map Table: DISABLE
PTE pid: 00
XXX write VBR 0 @ pc 74068e

Then some writing to I/O mapped "scsi bus register" (presuming its an autoincrementing register) so is that 0x8007 or 0x0780? ie LSB,MSB or MSB,LSB
scsi_bus_address(007bc000) write <= 80
scsi_bus_address(007bc000) write <= 07

Then some more hitting the scsi I/O mapped
scsi(007be002) write <= 00
scsi(007be012) read 1
scsi(007be00a) write <= 07
scsi(007be004) write <= 00
scsi(007be006) write <= 00
scsi(007be018) write <= 00
scsi(007be01a) write <= 13
scsi(007be01c) write <= 88
scsi(007be002) write <= 09
 
I have the start of a Tektronix 4404 emulator here if you're interested in looking it over / getting ideas / grabbing anything. Sadly, I didn't make it very far, it's really skeletal. I did not actually implement very much of the SCSI stuff yet, so that won't be helpful to you, but there may be other useful things about the memory map in it.

 
I have the start of a Tektronix 4404 emulator here if you're interested in looking it over / getting ideas / grabbing anything. Sadly, I didn't make it very far, it's really skeletal. I did not actually implement very much of the SCSI stuff yet, so that won't be helpful to you, but there may be other useful things about the memory map in it.

Seth, your Rust emulator inspired me to start writing an emulator in C :ROFLMAO:
Most helpful.

I could not see in your code how you handle the ROM being mapped into all addresses at startup and no mention of FunctionCodes either. Tek4404 alternately writes to SFC & DFC (sys data / user data) as it strides up thru memory to find the maximum before a bus error - for now I've given my Tek4404 emulator 6M so it never fails :)
 
Last edited:
I am slowly annotating the 68k boot code.

I am reasonably sure the:
scsi(007be018) write <= 00
scsi(007be01a) write <= 13
scsi(007be01c) write <= 88
...Is writing a 3 byte address of some sort (logical block?)

and
scsi(007be002) write <= 00
scsi(007be012) read 1

is a UNIT_READY cmd as its used at the top of many scsi functions.
 
I have the start of a Tektronix 4404 emulator here if you're interested in looking it over / getting ideas / grabbing anything. Sadly, I didn't make it very far, it's really skeletal. I did not actually implement very much of the SCSI stuff yet, so that won't be helpful to you, but there may be other useful things about the memory map in it.

Neat! Since I use Rust (mostly for embedded projects) I just tried building it on my FreeBSD workstation. Not only does it build, but it runs too:
tek4404_Screenshot_2024-05-17_16-54-29.png
 
I could not see in your code how you handle the ROM being mapped into all addresses at startup and no mention of FunctionCodes either. Tek4404 alternately writes to SFC & DFC (sys data / user data) as it strides up thru memory to find the maximum before a bus error - for now I've given my Tek4404 emulator 6M so it never fails :)

The ROM is mapped into RAM space by default at startup (0x000000 to 0x1fffff). This is turned off when the sound generator is initialized by writing to 0x788000. This is sort of documented in the service manual (http://www.bitsavers.org/pdf/tektro...em_Component-Level_Service_Manual_Jun1987.pdf ) on pages 2.1-54 through 2.1-56, but it seems like a weird choice to me!
 
Neat! Since I use Rust (mostly for embedded projects) I just tried building it on my FreeBSD workstation. Not only does it build, but it runs too:
View attachment 1279907

It "runs", but it really is such a skeletal system that it isn't doing anything useful yet! :) I like Elektraglide's idea of using Brad Parker's Sun-2 emulator as a starting point, it makes a lot of sense.
 
I was sure I looked before, but I found a mame plugin for tek4404 that appears to have a scsi implementation!
Going to see if I can get it building.
 
Back
Top