The Last piece of the puzzle - the software. Take a look at the listing. See the title? 1DE38.ASM That is the 38th version of the IDE code that I have done. And, it will not be my last. Let's talk about how an IDE drive is programmed.
IDE Overview
One of the great things about an IDE drive is that it very simple to run. No low-level
formatting is required, you tell it how many heads and sectors per track (not the other way
around), and you only need two instructions, read and write! You communicate with the drive using
two sets of registers - in our case at $Dl5x and $D166. You load the sector number(s) into the
proper registers and just ask the drive to read or write. If you are using a late-model, buffered
drive, data is read or written as fast as you like from the data register until the transfer is
complete. From an 8-bit standpoint, the real deal here is that all sectors are 256 bytes. No double
read buffer gyrations needed. Of course, there is a loss of half of your drive's capacity since the
interface is 16 bits wide and we're only using 8 Yep, you only get to use 40 megs from an 80 MB
drive. Or, 600 megs on a 1.2 GIG unit. SO? That's the price you pay for such a clean, fast, and
simple design. At today's prices, who can complain? (don't even ask me about using the whole drive
- I am not going to do a 16 bit interface. It would be slow, expensive and messy.)
Reset
OK, on to the registers. First is $D166. This is the reset register. The interface has
hardware reset from the 1200XL connected to pin 1 of the drive. Every time you push RESET on your
1200XL, the drive gets reset (you may even notice the drive start to spin down). When you are doing
IDE development, you may want to disconnect the hardware reset and just use the soft reset at
$D166. This will allow you to reset only your 1200XL if the system is hung, preserving the IDE
register status for examination. Either way, you must assert reset for at least 5 microseconds to
clear the drive. It will then take a little while for the drive to get itself back together and go
not busy (all regs will read $DO during reset). Currently, I am not using $D166 reset, so don't
look for it in the 1DE38 code.
Registers
Next are the $Dl5x regs. I'll list them in order:
ADDR | READ | WRITE |
50 | data reg | data reg |
51 | error reg | write comp |
52 | sector count | sector count |
53 | sector number | sector num |
54 | cylinder low | cylinder low |
55 | cylinder high | cylinder hi |
56 | SDH | SDH |
57 | status | command |
Most of those may be self-explanatory. Data is the read or write data. The error reg has error codes if $57 has bit 0 set (xxxxxxx 1). Sector count allows you to read multiple sectors with one command - set it to 1. Sector number is the number of the sector you wish to read or write ($01 - $10). Cylinder low and high are the cylinder number you are accessing ($0000 - $FFFF). SDH contains three parameters: the sector size in bits 5 and 6 (01), the head number in bits 0 - 3 ($0 - $F), and the drive (master or slave) in bit 4. For example $A7 selects the master drive and head 07. $B9 selects the slave drive on head 09. (I have been able to run two drives at once with some success.... but it needs some s/w yet).
Code Overview
The driver code and the configuration table sit in the space newly acquired at $D600 thru
$D7FF. This may allow some software that poaches in the OS space for its own routines to run with
an IDE drive, since $D6xx and $D7xx are never usable from a software routine. The IDE drivers will
run with a DOS that is not HD intelligent. Many of my partitions boot good old DOS 2.0, both single
and double density. Just the ticket for AtariWriter on cartridge. In fact, the IDE drive runs
without any DOS at all, as in SCOPY and other M/L utilities. It just looks like any other disk
drive to the SIO code. There is currently space for 16 partitions in HDTABL, but 63 would be
supported in the current code. And, the HDTABL could be loaded from disk as many times as
necessary, giving you unlimited partitions - 16 at a time. No or little error checking is done in
IDE38 code. This is NOT a great idea. While I am using new, modern drives, I don't seem to have a
problem. Some of my old, high-mileage clunkers do not fare so well. The older drives do not seem to
like having 16 heads and 16 SPT, either. So, beware. This IDE stuff is not all perfect in the
software department. Of course, the value of the SmartIDE modification is to develop OS routines
steadly - in particular, the IDE code. So folks, get on the ball and do some of this stuff. Write
some good hacks to the code and send it to AC for future articles! Once we have some really
effective code you can add an IDE with just the HC138 and a new ROM. The hardware seems to be
pretty solid. That is not to say that it does not have any problems - the Sweet 16 will not work
with it, I'm afraid. But, on a standard machine, it is at least consistent and reliable.
OK, on to the code itself.
IDE vs. SIO
The IDE drive has a hook into the normal SIO code at $C95B. We JSR into the new routine to see
if the I/O is pointed to an IDE partition. The first check is the SELECT key (line 360-380). I have
allowed the SELECT key to override the IDE code. If you want to bypass all of the active IDE
partitions, just hold SELECT down and your system will use only SIO devices. This makes it quick to
peek at a directory or copy a single file to or from a floppy. For example, you have a floppy set
as D2: and an IDE partition set as D2:. The IDE drive at D2: will always answer for D2: since the
IDE code has priority. But, if you want to read from the floppy D2:, you can simply hold SELECT
down and all D2: access will be on the SIO. To copy a file from the floppy D2: to the IDE D2: you
can hold SELECT when DOS asks for the source and release SELECT when DOS asks for the destination
drive. Works just fine. The next test is for the device in the OS DDEVIC ($0300). If it is not a
$31, then we are not talking to a disk drive and we can exit IDE code. The last test is to find the
device address, DUNIT ($0301) in the HDTABL at $D7C0.
HDTABL
The HDTABL is a 64 byte data field that contains 16 four byte entries. Each entry represents a
partition or range of sectors on the IDE drive. The first byte is the high order byte of the first
sector in the partition and the second byte is the low order byte of the first sector in the is to
develop OS routines easily - in partition. The third byte is the number of particular, the IDE
code. So, you folks 256 sector clusters in the partition (max sectors is still 65K or 16mb). The
fourth byte is a composite - bits 5-7 are density tags that are returned on a STATUS command. $8x
is a 1050 in dual density (1024 sectors). $6x is a double density disk. And $Ox is a single density
disk. Bit 4 is the IDE drive bit (which I do not use in the current code). Setting bit 4 will
select the slave drive on the IDE buss instead of the master drive. This will be great help when
you want to back up your I-ID data on one of those SyQuest 135mb removable drives. Just add it as a
slave drive and copy from one IDE drive to another! Finally, bits 0-3 are the drive address itself.
As an example, a $64 in byte 4 would indicate a DD partition on the master drive that will respond
to D4: on the SIO. A $92 would be a 1050 density partition on the slave drive that would answer as
$D2:. Any drive that has bits 0-3 set off is not active or disabled. Examine the data loaded in the
HDTABL in 1DE38.ASM. The first partition at line 2730 is a DD drive set as Dl: on the master drive.
It is 4096 sectors long and starts on sector $0000 of the IDE drive. The entry at line 2760 is a SD
drive that is unassigned and is 1536 sectors long starting at IDE sector $001C. And, as I write
this I notice that the next partition starts at IDE sector $0020 - which does not allow enough
space for the previous partition! You be very careful when you set up HDTABL, OK? That little error
in line 2770 would eat my 8 meg partition if I used the previous partition past 1024 sectors,
wouldn't it? Note that the HDTABL is not required to be in any specific order except for the first
three entries, which we will cover later. This allows you to overlay any of the entries you wish in
order to change which partitions are "mounted" on a particular "drive".
Searching HDTABL
Finding the device address in HDTABL is just a matter of checking byte four of each entry for
a match to $0301, DUNIT. line 420 loads the an index to the end of the table and the search
progresses backwards until a match is found or the index is less than zero. If no match has been
found, then that drive is not an active IDE drive. The first drive found starting from the bottom
will cause a branch into IDE code at line 580.
R We Busy?
Before we try to access the drive, we check for BUSY at line 590. This code just loops forever
if the drive is hung. A better approach would be to branch out into a routine that would determine
the reason for the BUSY and take action. Maybe later.... As I said earlier, a new drive never has a
problem here. Older drives, not so true. OK?
Command Dcode
Now we are into the real code at line 630. Here we determine the command. No real cute coding;
just compare DCOMND at $0302 with all valid IDE commands. If we do not find one, return a command
reject at line 790. Notice that the $4E command in line 760 just branches into the STATUS routine.
This command and the $4F command are the read and write configuration commands used by the PERCOM
standards. If you want to use SpartaDOS or any other DOS that needs this data, you must implement
these two commands. And, yes that means that any DOS using these commands will not recognize the
IDE drives as anything other than an 810 or 1050. Gives us something to work on, doesn't it? MYDOS
works just fine without the $4E and $4F.
SETREGS
So, now we get to the command itself. The only commands that do anything with the IDE drives
are the read and write commands. The first step in both commands is to JSR to to SETREGS. This is
where we convert the logical sector number from SIO to a physical sector, head and cylinder on the
IDE drive. Lines 1540 to 1580 sets the data address for the transfer. Lines 1590 to 1630 loads the
IDE sector number ($D153) from the low order SIO sector number ($030A). Notice how simple that is?
Later on, we'll discuss the IDE INIT code where we tell the IDE drive that he has 16 sectors per
track and 16 heads per cylinder. This makes it simple to convert the SIO sector number to the IDE
parameters. Lines 1640 to 1710 loads the IDE physical head ($D156) from the remaining low order SIO
sector value. Lines 1720 to 1790 adds the HDTABL partition offset in bytes 1 and 2 to the high
order SIO sector ($030B) and stores the result in the IDE cylinder low ($D154) and cylinder high
($D155). It also checks the range of the SIO sectors at line 1730 to insure that we don't overrun
the next HDTABL partition. Last, but not least, we tell the IDE drive that we will only read one
sector (lines 1800 to 1810) and clear the carry bit to signify no sector error. Back in the read or
write command, we check for a sector overrun and start the command.
Read Command
The IDE read command is a $20. Just loading that value into the command register at $D157 will
initiate the seek to the data sector and read all the data into the IDE buffer. Once the drive is
not BUSY (lines 1190 to 1210), you are ready to read your data. By checking the data ready bit (bit
3) in the STATUS register ($D157), we can determine when the sector may be transferred into our
memory (at ($32) ,Y). Once the first data byte is ready, by the way, it is not really necessary to
check status to see if any subsequent bytes are available since we are reading a memory buffer, not
a mechanical device at this point. There are two sector sizes on the Atari, 128 and 256 bytes, as
defined in DBYTLO at $0308. If we are reading a 128 byte sector, the last 128 bytes just get thrown
away (lines 1300 to 1340). We do not want to read them into memory. A 256 byte sector will read all
256 bytes into memory (lines 1220 to 1290). At that point, bit 3 of the IDE STATUS register will be
reset to 0. That's it. Set a few flags in the SIO and you're done (lines 970 to 990 and 840 to
880). Cut out all the unnecessary code and you can read a 720 sector DD disk in about 4 seconds not
too bad!
Write Command
The write command is similar to the read command except the command code is a $30. We do not
need to check the sector size here since the last half of the sector is not used for 128 byte
sectors anyway. The code simply writes the 256 bytes starting at the SIO data address into the IDE
data register. The drive will do the seek and store the data after the transfer. Be aware! As
written, this code does not keep you from writing 256 DD sectors to a SD drive as would normally be
the case. You can hose yourself all up if you are not careful in the HDTABL configuration. It would
be a good idea to check the sector length against the HDTABL size Maybe later.
OK, other stuff....
IDE Initialization
IDE drives must be initialized before you use them. You must tell the drive how many sectors
per track and how many heads per cylinder they should configure themselves into or the drive will
use it's native values. We want to have a drive that has 16 sectors per track and 16 heads - this
makes the code very simple. So, we do this every time we RESET the drive. Line 320 patches the OS
to init the IDE drive. INITCODE (at line 1850) first checks for the IDE drive to have completed
it's RESET and then stores the number of sector in $D152 and the number of heads in $D156. Storing
a $91 in the command reg at $D157 initializes the drive with our values (line 1940 to 1950). Simple.
Dynamic Selection
There are a couple of bells and whistles in this code that I like. The first three HDTABL
entries are reserved for Dl:. I have patched the OS to respond to CNTL-F1 in lines 180 to 200 so
that this keystroke now selects Dl: from one of four options. SIO Dl:, if it is connected, or any
of the first three HDTABL entries. The purpose of this feature is to allow you to change
"diskettes" in Dl: on the fly. Or, you can switch from the IDE drive to the SIO drive with
just a keystroke. I also use the two L1 and L2 indicators on the 1200XL to indicate just who's on
Dl:. 00 is the SIO drive, 01 is HDTABL entry 1 (at $D7C0), 10 is HDTABL entry 2 ($D7C4), and 11 is
HDTABL entry 3 ($D7D0). This code is in SELNXTHD at lines 205 thru 2100 and SETL1L2 at lines 2430
thru 2540. I also allow D2: to be toggled between the HDTABL IDE drive and the SIO drive using the
CNTL-F2 keystroke (lines 220 thru 260 and 2590 thru 2680). Overall, I can select IDE drives 1-3 or
the SIO drive on Dl: and IDE drive or SIO drive on D2: from within any program that has not
overlaid the OS too badly. Works really great!
FINIS
Anything else? I guess not in this issue. I will really, really try not to screw up the
publication schedule any more. I know a number of you subscribers are wondering about our viability
- I would rather print something useful on an irregular basis than just print whatever we have on a
fixed schedule. I hope at least some of you agree and continue to support us. For the others, we'll
work on it, OK? Don't give up - better yet, volunteer! We could use the help. That way, I may not
have to have either a project or a magazine - we can have both.
You can download the disk with all the code here.
about 13k in ZIP format.