1571-3.TXT rev 1a 96-11-01
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
THIS DOCUMENT IS COPYRIGHT (C) 1988, 1996 BY HERNE DATA
SYSTEMS LTD. THE MATERIAL CONTAINED HEREIN MAY BE FREELY
USED FOR PERSONAL INFORMATION ONLY. IF YOU REPRODUCE IT,
THIS COPYRIGHT NOTICE MUST NOT BE REMOVED. THIS MATERIAL
MAY NOT BE EXPLOITED FOR COMMERCIAL PURPOSES.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Herne Data Systems Ltd.,
PO Box 250, Tiverton, ON N0G 2T0 CANADA.
Voice/fax 519-366-2732,
e-mail herne@herne.com
internet: http://www.herne.com
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
The 1571 Disk Operating System
The 1571 disk drive is an intelligent device. It contains its
own microprocessor, interface hardware, RAM, and a ROM based
operating system. The ROM based disk operating system (DOS)
contains the software which normally controls the operation of
the drive. The various DOS functions are activated by sending
specific mnemonic type commands to the disk drive over the
command channel. The disk drive then executes the command
independently and reports back a status to the computer,
generally over the same command channel.
The DOS can be divided into two main segments: the command
interpreter and the controller. The interpreter receives the
command from the computer and breaks it down into a series of
elemental steps, such as requests to read or write specific disk
sectors. The sector parameters are passed to the controller
routines, which perform the actual task. The interpreter takes
the result of the series of controller steps and passes it back
to the computer as applicable.
The current models of the 1571 operate on CBM DOS version 3.0.
The DOS program is contained in the disk drive's ROM at address
locations $8000 to $FFFF. Address location $8000 to $BFFF
generally contains the new 1571 DOS routines, while $C000 to
$FFFF contains the 1541 emulation DOS, essentially a duplicate of
the true 1541 DOS with minor modifications to allow some of the
new 1571 commands to be used in 1541 mode.
The DOS commands can be sent to the drive either explicitly (via
a PRINT# statement to the previously opened command channel) or
indirectly using one of the BASIC 3.5 or 7.0 disk related
commands (such as HEADER, COPY, etc.) The BASIC 3.5 and 7.0 disk
commands work by translating the BASIC parameters into a series
of DOS commands and sending them to the disk drive. Explicit
commands must be used with BASIC 2.0 and are also used
extensively with machine language programs. Because they are
strictly user controlled, explicit DOS commands can also be more
versatile than BASIC 3.5/7.0 disk commands. Unlike the BASIC
disk commands, the explicit DOS commands generally will not
suspend computer operations while they are being executed (unless
further disk activity has been requested). This increases the
apparent speed of operation of most disk intensive programs by
allowing the computer and disk drive to operate independently.
This document describes the use and operation of the disk drive
command channel along with the function and use of each of the
1571 DOS commands, complete with examples. The examples are
given in BASIC. A description of assembly language routines for
performing similar functions can be found in 1571-4.TXT (DOS &
The KERNAL). When listing the syntax for a particular command,
square brackets, "[]", are used to enclose parts of the command
which are optional. All other parts must be entered as listed.
The DOS commands are generally grouped into five sets: general
utility commands, block commands, memory commands, user commands
and burst mode commands. The first four will be described in
this document, while the burst mode commands are detailed in
another document. The first four groups of commands will only
work with Commodore GCR disks, while most burst mode commands can
be used with either GCR or MFM disks.
Each group of commands performs a range of functions, some of
which may appear to be overlapping. In such cases, however,
there are subtle differences in the way the commands act. These
differences are detailed where they occur.
The Command Channel
All commands from the computer to the disk drive are passed
through a special communication channel called the command
channel. This channel is also used for passing error and status
information from the drive back to the computer. Physically, the
data are transferred to/from the disk drive over the serial bus,
just like normal data. However, the command data are handled
differently by the disk drive.
The command channel can be opened with a standard BASIC 2.0 OPEN
statement using the reserved secondary address, or channel
number, of 15. For example:
OPEN 1,8,15 [,"{command string}"]
will open the command channel on disk drive device number 8 as
logical file number 1 and, if specified, immediately send the
command specified by {command string} to the drive. In this case
and all cases outlined below, {command string} can be either a
constant or a variable, or some combination of both. If
variables are used, the quote marks should not be used around the
variable portions. The command channel can be opened in either
program or immediate mode. The BASIC 3.5/7.0 DOPEN command
cannot be used to open the command channel because it has no
provision for explicitly specifying a channel number.
All subsequent communication to the disk drive can now be handled
with a:
PRINT#1,"{command string}"
statement, where {command string} is chosen from one of the
formats outlined in the remainder of this document based on the
desired function. As in the previous case, the command string is
sent to the input buffer of the 1571 drive, located in the disk
drive RAM at address $200 (dec 512). Output to the command
channel can be made in either program or immediate mode.
The command input buffer of the 1571 drive is 41 bytes long.
Therefore, the command string, complete with all anciliary
options specified, must be less than 41 characters long to be
able to fit in this command buffer. This is not normally a
problem, except when specifying multiple long file names during
copy, scratch, rename, etc. type operations. The DOS commands
can be abbreviated to two or three characters, which helps to
alleviate the congestion.
The command channel is also used for passing error and status
reports, as well as data in some cases, from the drive back to
the computer. In this case, it is often referred to as the
"error channel" and can be read using standard INPUT# and GET#
statements. Since Commodore BASIC can normally only accept input
in program mode, the error channel is difficult to read in
immediate mode without special programming techniques such as DOS
wedges.
The following example demonstrates reading the error channel in
program mode:
10 OPEN 1,8,15
20 INPUT#1,A1,A2$,A3$,A4$
30 PRINT A1;A2$;A3$;A4$
40 CLOSE 1
In this example, A1 will return the numeric value of the DOS
error code, similar to reserved variable DS in BASIC 3.5 and 7.0.
A2$ will return the description of the error, while A3$ and A4$
will return the track and sector where the error occured, if
applicable. The text string formed by the combination of A1,
A2$, A3$, and A4$ is the equivalent of the reserved variable DS$
in BASIC 3.5 and 7.0. This example will work with all versions
of Commodore BASIC. Reading the error channel in this manner
will also extinguish the flashing error light on the drive if it
is on.
It should be noted that when the command channel is closed, all
other open disk channels (i.e. disk files and random buffers) on
the device are closed within the drive and their internal
channels and buffers are de-allocated. However, the logical
files in the computer associated with these disk files remain
open. If a subsequent attempt is made to read or write one of
the de-allocated direct access buffers, a DOS error code 70, NO
CHANNEL, error will be generated. For an open read file, an end
of file indication will be returned in the status variable ST
along with null data. For an open write file, a DOS error code
61, FILE NOT OPEN, error message will be generated. A BASIC
CLOSE type of statement must be used for each OPEN file in order
to properly close the file in the computer. This is especially
important for write files.
General Utility Commands
The 1571 general utility commands provide housekeeping and file
management functions. The commands are summarized in Table 1 and
outlined below in alphabetical order. In all cases, either the
full or abbreviated form can be used. However, the abbreviated
version is often preferred due to the limitation of the size of
the 1571's command input buffer, especially if many options are
specified. All utility commands work identically in both 1571
mode and 1541 mode.
TABLE 1: General Utility Commands
..............................................................
Command Syntax
..............................................................
COPY "C0:{target file}={sourcefile1}
[,{sourcefile2}...]"
INITIALIZE "I0"
NEW "N0:{diskname},{ID code}" (full format)
"N0:{diskname}" (short format)
POSITION "P"+CHR$({channel#}+96)+CHR$({rec#lo})+
CHR$({rec#hi})+CHR$({byte})
RENAME "R0:{new name}={old name}"
SCRATCH "S0:{pattern}[={filetype}]"
VALIDATE "V0"
............................................................
Copy
The COPY command is used to make a duplicate of a file or combine
several files into a longer one on the same device. Since the
1571 is a single drive device, the copy must be on the same disk
as the original. It must also have a different filename. COPY
works by reading a sector from the source file, then writing it
to the target file. This is repeated for as many sectors as
there are in the file.
The syntax for the command is:
"COPY{drive#}:{target file}={drive}:{source1}[,{source2},...]"
{target file} is the name of the file created by the copying
process, while {source1} etc. are the file(s) being copied from.
By specifying more than one source filename, each separated by a
comma, several files can be joined into a single file. However,
all files must of the same type and generally only SEQ files will
produce meaningful results when combined in this manner. Multiple
REL files cannot be combined in this way.
With the 1571, {drive#} is always 0 (numeral zero). The total
length of the command string cannot exceed 41 characters. Wild
cards and pattern matching can be used in the source filenames,
but the target filename must be unique. Alternatively, the word
COPY can be abbreviated to the single letter "C" resulting in the
following format:
"C0:{target file}=0:{source1}[,{source2}...etc]"
For example, the following will create a new file named FRUIT
which will contain the combined contents of the three source
files, in the specified order:
OPEN 15,8,15,"C0:FRUIT=0:APPLES,0:ORANGES,0:PEACHES":CLOSE 15
The source files will remain untouched on the disk. If one of
the specified source files does not exist, then a DOS error code
62, FILE NOT FOUND, error will be generated and the copying
process will stop. If a file exists under the same name as the
new file being created, a DOS error code 63, FILE EXISTS, error
will occur and the copying process will stop.
The following example demonstrates the use of variables in the
command string in program mode:
10 OPEN 15,8,15
20 INPUT "FILE TO COPY FROM";F1$
30 INPUT "FILE TO COPY TO";F2$
40 PRINT#15,"C0:"+F1$+"=0:"+F2$
50 INPUT#15,A,B$:IF A=0 THEN PRINT"DONE":CLOSE 15:END
60 PRINT"DISK ERROR "A;B$:GOTO 20
This short program will copy any file that you specify to any
other filename. It is a simple method for making multiple backup
copies of a program or data file on a single disk.
It should be noted that the order of specifying source and target
files for the DOS COPY command (target=source) is the opposite of
the equivalent BASIC 3.5/7.0 command (COPY "source" TO "target").
This syntax is, however, identical to that used by CP/M's PIP
utility for copying files (PIP target=source).
Initialize
INITIALIZE is used to log in a disk and read the block allocation
(or availability) map (BAM) sectors into the disk drive RAM
buffer #5 at memory location $700 (dec 1792) of the 1571 drive.
The primary BAM sector is track 18, sector 0. A double sided
disk also contains a copy of the second side BAM on track 53,
sector 0 (corresponding to track 18, but on side 1). Performing
an initialization is often useful as a precaution after changing
disks to ensure that the correct BAM information has been read
into the drive for future input and output operations.
Initialization should also be performed after any disk error has
been detected because certain errors and disk operations may
leave an incorrect version of BAM in the drive buffer. It is
especially important before performing any write operations (such
as a SAVE) or any of the BLOCK commands described in the next
section of this document.
The syntax is:
"INITIALIZE{drive#}"
No options or filenames are specified with this command. As with
all 1571 commands, {drive#} is always 0. Alternatively, the
command can be abbreviated to:
"I0"
An example of a disk initialization would be:
OPEN 2,8,15,"I0":CLOSE 2
INITIALIZE will de-allocate the disk drive's internal channels
associated with all open files thus cancelling but not properly
closing them, so make sure that all of your open write files have
been properly closed before you change disks and use this
command. The logical files in the computer are also not closed
by an INITIALIZE, and must therefore be closed separately.
The INITIALIZE procedure is often used as a "soft reset" for the
disk drive. It will also clear the disk error channel. If no
disk is in the drive or the BAM sector (track 18, sector 0)
cannot be found or read, a DOS error code 74, DRIVE NOT READY,
error will occur. INITIALIZE can only be used with Commodore GCR
type disks. Other disk types will produce the DRIVE NOT READY
error.
New
The NEW command is used to "new" or format a fresh disk or to
erase a previously used disk that you wish to re-use. It is
identical in function to the BASIC 3.5/7.0 HEADER command. The
syntax is:
"NEW{drive#}:{disk name}[,{id code}]"
Alternatively, the command can be abbreviated to:
"N0:{disk name}[,{id code}]"
If {id code} is not specified, then only the disk directory and
BAM are erased and the name is changed. In this case, the actual
data on the disk are not destroyed. However, they are not
readily accessible because the directory has been erased. This
procedure is often referred to as a "short format".
For example:
OPEN 1,8,15,"N0:MYDISK,AA":CLOSE 1
will completely format (or re-format) a disk and give it the name
"MYDISK" with an ID code of "AA".
Unlike BASIC 3.5/7.0 HEADER command, NEW does not ask you to
confirm your desire to format the disk. It also does not cause
the computer to lock up until the formatting cycle has been
completed.
When in 1571 mode, NEW will always produce double sided disks.
The formatting time for a full format is approximately 40
seconds, while for a short format the time is 5 seconds. In
1541 mode, single sided disk can be produced on either side of
the disk. In this case, the full format time is approximately 80
seconds but the short formatting time remains at about 5 seconds.
For a full description of formatting single sided disks, see the
"U0>H" commands in the User Commands section at the end of this
document.
Position
The POSITION command is used in conjunction with relative files.
It is similar in function to the BASIC 3.5/7.0 RECORD# command
for selecting the relative file record number and starting byte
number to be used for a subsequent input or output operation.
The syntax for the command is:
"P"+CHR$({channel#}+96)+CHR$({lo})+CHR$({hi})[+CHR$({byte#})]
where {channel#} is the secondary address used in the OPEN
statement for the relative file, {lo} and {hi} are the low and
high bytes respectively of the record number desired, and {byte#}
is the optional starting byte in the record for the input/output
operation. Although the starting byte is considered to be
optional by Commodore DOS, it is a good idea to always specify it
as a value of 1 when you want to start at the beginning of the
record. This ensures that the record pointer is not left
incorrectly positioned by any previous positioning commands and
thus reduces the chance of positioning errors.
For example,
20 PRINT#15,"P"+CHR$(98)+CHR$(3)+CHR$(1)+CHR$(5)
will position the relative file pointer of the file associated
with disk channel #2 to byte 5 of record 259 (1 x 256 + 3),
assuming that the command channel has already been opened as
logical file #15. As with the BASIC 3.5/7.0 equivalent, the P
command should be given once before and again after a record has
been accessed.
If the requested record number is beyond the current end of file,
a DOS error code 50, RECORD NOT PRESENT, error will be generated.
If this error occurs prior to a write operation, the file will be
expanded to include this new record, as well as any missing
records between the previous end of the file and the requested
one, when the write operation is actually performed. The missing
records in between will be filled with blanks. If the error
occurs prior to a read, you have gone past the current end of the
file. This can be used to detect the highest record number in
the file. Relative files are described in greater detail in
"Effective Use of Files".
Rename
The RENAME command is used to change the name of an existing file
in the disk directory to something else. The syntax of the
command is:
"RENAME{drive#}:{new name}={old name}"
Alternatively, on the 1571, it can be abbreviated to:
"R0:{new name}={old name}"
DOS RENAME is identical in function to the BASIC 3.5/7.0 command
of the same name. However, as with the COPY command, the order
of specifying the file names is reversed to that of the BASIC
command. The following example will rename the file APPLES to
ORANGES:
PRINT#1,"R0:ORANGES=APPLES"
assuming that the disk command channel has been opened as logical
file #1. The file type remains unchanged. If the file APPLES
does not exist, a DOS error code 62, FILE NOT FOUND, error will
occur. If a file named ORANGES already exists, regardless of its
type, a DOS error code 63, FILE EXISTS, error will occur.
As shown in the following example, variables can also be used
with the RENAME command:
10 OPEN 15,8,15
20 INPUT "OLD FILE NAME";F1$
30 INPUT "NEW FILE NAME";F2$
40 PRINT#15,"R0:"+F2$+"="+F1$
50 INPUT#15,A,B$:IF A=0 THEN PRINT"DONE":CLOSE 15:END
60 PRINT"DISK ERROR "A;B$:GOTO 20
In all cases, wild cards and pattern matching can be used in the
old file name, but not in the new name. If pattern matching is
used, DOS will rename the first file which matches the pattern.
Scratch
The SCRATCH command allows you to erase one or more files from
the disk directory to get rid of old files and free up their disk
space for re-use. The syntax of the command is:
"SCRATCH{drive#}:{pattern1}[,{pattern2}...][={filetype}]"
{pattern1}, {pattern2}, etc. can be single filenames or may
include wild card and pattern matching characters. The total
length of the command with all specified patterns cannot exceed
41 characters. On the 1571, the command string can be
abbreviated to:
"S0:{pattern1}[,{pattern2}...][={filetype}]"
For example,
OPEN 1,8,15,"S0:DATA*,FILE1":CLOSE 1
will erase any file beginning with the four characters "DATA" as
well as a file named "FILE1". After scratching files, DOS will
return with the status message error code 01, FILES SCRATCHED X,
on the error channel where X represents the number of files
actually erased. This confirms that files where in fact deleted.
The indication of the number of files scratched is convenient as
a check, especially if wild cards and pattern matching have been
used in the filenames. To read the status message after using
DOS SCRATCH, the error channel must be read manually.
Unlike the BASIC 3.5/7.0 version of the command, you will not be
asked to confirm your desire to perform the task. However, you
will be able to carry on with other tasks while the disk drive is
doing its job. DOS SCRATCHed files can be recovered under the
same conditions described for BASIC's SCRATCH command in 1571-
2.TXT.
WARNING: SCRATCH should not be used on SPLAT files.
This could corrupt other valid files on the disk. To
remove a SPLAT file, use the VALIDATE command described
next.
Validate
A frequently used disk may contain a few blocks (or sectors)
which have been "over looked" by DOS, especially if random files
have been used, or SPLAT files are present. The VALIDATE command
is used to "clean up" the BAM of a disk to recover these lost
blocks. Lost blocks can be detected by adding up the number of
blocks associated with each file, combined with the number of
blocks free, and comparing the total to 664 for a single sided
disk or 1328 for a double sided. If the total is less than the
allowable maximum, then either some blocks have been allocated as
random access files (see the BLOCK-ALLOCATE command below) or
have been lost to SPLAT files. If SPLAT files are present, as
indicated by an asterisk, "*", next to the file type in a
directory listing, then the disk should be VALIDATEd to remove
the SPLAT file. However, it should be noted that VALIDATE will
also de-allocate any blocks which have been allocated by the
BLOCK-ALLOCATE command, regardless of whether or not they contain
data that you wish to keep.
If the total of the block count is greater than the maximum
values specified above, then some valid blocks may have been
de-allocated as random access files, or two or more files have
become "crossed" and corrupted. This is a dangerous situation.
The disk should be VALIDATEd immediately before writing anything
further to it. Failure to do so may result in hopelessly
corrupted files. If the disk will not properly VALIDATE, some
files might be hopelessly corrupted. In this case, all files
should be immediately copied to a new disk, one at a time (i.e.
do not use a whole disk duplicating program). The files can then
be inspected individually to see which ones have been corrupted.
The syntax for VALIDATE is:
"VALIDATE{drive#}"
On the 1571, this can be abbreviated to:
"V0"
For example:
OPEN 15,8,15,"V0":CLOSE 15
will perform a validation of the disk in device 8, drive 0.
Similar to the INITIALIZE command, no file names or options are
specified with VALIDATE. The command serves the same purpose as
the BASIC 3.5/7.0 COLLECT command, but will allow you to procede
with other computer functions while the disk drive is performing
its function.
As mentioned previously, VALIDATE should not be used on disks
containing random files because the blocks associated with these
files will become de-allocated and may be overwritten by DOS at a
later time. This is especially important for C-128 programmers
who use the BOOT sector on the disk. In addition, VALIDATE
should not be used on a double sided disk when the 1571 drive is
in 1541 mode or a 1541 drive is used. This action will reset the
double sided flag in the BAM sector (track 18, sector 0, byte 3)
to a value of 0 to indicate single sided and you will lose any
data stored on the second side. It should be noted that this
problem has been corrected with 1571 ROM releases of 4 and later
(when used in 1541 mode). The disk can be reset to double sided
mode using the following procedure:
10 OPEN 15,8,15,"I0"
20 OPEN 3,8,3,"#"
30 PRINT#15,"U1: 3 0 18 0"
40 PRINT#15,"B-P: 3 3"
50 PRINT#3,CHR$(128); : REM FLAG = 128 FOR DOUBLE SIDED
60 PRINT#15,"U2: 3 0 18 0"
70 CLOSE 3:CLOSE 15
The disk should then be re-VALIDATEd in 1571 mode to ensure that
side 1 has been properly done.
The following short program can be used to VALIDATE a disk which
contains a BOOT sector:
10 OPEN 15,8,15,"V0"
20 PRINT#15,"B-A: 0 1 0" : REM RE-ALLOCATE BOOT SECTOR
30 CLOSE 15
The above two examples do not perform any error checking, which
can be added if you desire.
DOS VALIDATE and BASIC COLLECT should not be used on GEOS disks.
The GEOS "validate disk" option should be used to preserve the
special structure of the GEOS disk.
Block Commands
The block commands are used to access a disk on a sector by
sector basis. In Commodore DOS, this type of disk access is
known as a "random file", meaning random access to sectors on the
disk. The commands all take the following format:
BLOCK-{action}:{target}
where {action} represents the primary function of the command and
{target} generally represents the block (i.e. track and sector)
affected by the specified action. The command syntax is
generally quite loose with numerous alternate formats as outlined
below. The most frequently used formats are summarized in Table
2.
TABLE 2: The BLOCK commands
..............................................................
Command Syntax
..............................................................
BLOCK ALLOCATE "B-A: 0 {track#} {sector#}"
BLOCK EXECUTE "B-E: {channel} 0 {track#} {sector#}"
BLOCK FREE "B-F: 0 {track#} {sector#}"
BLOCK POINTER "B-P: {channel} {byte#}"
BLOCK READ "B-R: {channel} 0 {track#} {sector#}"
BLOCK WRITE "B-W: {channel} 0 {track#} {sector#}"
..............................................................
In order to use the BLOCK commands, two OPEN statements must be
used: one to open the disk command channel, and the other to open
a direct access buffer in the disk drive. The direct access
buffer is opened with a statement similar to the following
example:
10 OPEN 1,8,3,"#"
This specific example will request the drive to open any
available buffer as logical file #1, channel #3 on device 8.
When the "#" symbol is used as a filename in an open statement,
it indicates to DOS to assign any available buffer to that
channel. If a specific buffer is requested, the format of the
command becomes:
10 OPEN 1,8,3,"#2"
where #2 represents the number of the buffer (from 0 to 3)
requested, 2 in this case. (Buffer #4 is reserved for BAM
operations and cannot be accessed with an OPEN command but it can
be read or written using memory read and write commands.) In the
first case if a buffer is not available, or in the second case if
the requested buffer is not available, a DOS error code 70, NO
CHANNEL, error will occur.
The BLOCK commands are sent to the drive over the command
channel, while data being read from or written to the block as a
result of the BLOCK command are transferred via the buffer
channel outlined above. Once the random access buffer has been
opened, data can be either read or written to it randomly. For
example,
20 PRINT#1,"DATA"
will write the specified data to the buffer opened above.
It should be noted that the PRINT# and GET# statements for
transferrring data use the logical file number associated with
the buffer (#1 in the case of this example) while the BLOCK
commands sent via the command channel use the channel number (#3
in this case) to identify the buffer. The computer uses the
logical file number for I/O operations while the disk drive uses
the channel number. This can be confusing at times, so a good
practice is to use the same number in the OPEN statement for both
the logical file number and the channel number, such as:
OPEN 3,8,3,"#"
When using BLOCK operations, it is a good idea to INITIALIZE the
disk with an "IO" command before you start, and certainly after
changing disks. This ensures that the most recent BAM
information has been logged in the drive.
Block-Allocate
The BLOCK-ALLOCATE command is used to "allocate" blocks in the
BAM so that they will not be overwritten by other DOS operations
at a future time. The acceptable formats of the command are:
"BLOCK-ALLOCATE:0" {track#};{sector#}
"B-A:0" {track#};{sector#}
"B-A 0" {track#};{sector#}
where {track#} and {sector#} represent the track and sector of
the block to be allocated. In the above examples, these
parameters can be either constants or variables. If they are
constants, then the parameters can be included inside the
quotation marks, without the semi-colon delimiters in the form
of:
"B-A 0 {track#} {sector#}"
It should be noted that with all of the BLOCK commands, the
parameters are specified as an ASCII string, not as CHR$(x). For
example, a zero is specified as "0" (CHR$(49)), the ASCII code
for the character 0, not as CHR$(0).
The following example will allocate track 1, sector 0 (i.e. the
BOOT sector for a C-128 disk), assuming that logical file #1 is
the disk command channel:
PRINT#1,"B-A 0 1 0"
To prevent existing data from being overwritten, you should
always attempt to allocate a block before writing to it. If a
DOS error code 65, NO BLOCK, error occurs, then the requested
block is already in use by another file. The track and sector
numbers returned with the error message indicate the next higher
block available. If the track number is zero, all remaining
higher blocks are full. If the disk is not yet full, try to
allocate a lower track and sector number. Because of this, it is
often convenient to start trying to allocating blocks beginning
with track 1.
Remember: Always re-initialize the disk with the "I0"
command after a NO BLOCK error.
Block-Execute
BLOCK-EXECUTE is a little used command that allows you to load a
specific sector into one of the RAM buffers of the 1571 and
execute it as a program. This is similar to the BOOT"{filename}"
command in BASIC 7.0, except that the program is being executed
entirely within the disk drive and it can be a maximum of 256
bytes long.
The following syntaxes can be used:
"BLOCK-EXECUTE:"{channel#}; 0; {track#};{sector#}
"B-E:"{channel#}; 0; {track#};{sector#}
"B-E" {channel#}; 0; {track#};{sector#}
An example of the procedure is:
10 OPEN 1,8,3,"#"
20 OPEN 15,8,15,"B-E 3 0 2 4"
30 CLOSE 1:CLOSE 15
This example will load track 2, sector 4 into the buffer
associated with logical file # 1 (channel #3) and execute it
within the disk drive, assuming that it contains a valid machine
language program. Note that you should be very careful using
this procedure because you could easily crash you disk drive, or
worse, corrupt your disk if you inadvertantly program the drive
incorrectly. A safer and more versatile approach is to use "&"
type disk utility files, described in more detail in Effective
Use of Files.
Block-Free
BLOCK-FREE is the opposite of BLOCK-ALLOCATE: it is used to
de-allocate blocks that been allocated, either by DOS or by
BLOCK-ALLOCATE. Once a block has been freed, it can used by
either DOS or for further BLOCK-ALLOCATE operations. The syntax
of the command is similar to the BLOCK-ALLOCATE command:
"BLOCK-FREE:"0; {track#};{sector#}
"B-F:"0; {track#};{sector#}
"B-F" 0; {track#};{sector#}
Because there is no way to tell whether a block has been
allocated by DOS (i.e. it is part of a regular file) or by the
BLOCK-ALLOCATE command, BLOCK-FREE should be used with a good
deal of caution. If you de-allocate a block which belongs to a
file, that block may be used by DOS for another file. If that
happens, the first file will be corrupted and will be composed of
part of the original file plus part of the second. The sector
linkage to the remainder of the first file will also be lost,
making this file virtually impossible to recover.
Block-Pointer
BLOCK-POINTER (also referred to as the buffer-pointer) is used to
position the byte counter in a random access buffer to a specific
byte. The syntax is:
"BLOCK-POINTER:" {channel#};{byte#}
"B-P:" {channel#};{byte#}
"B-P"; {channel#};{byte#}
The B-P command is used mainly in conjunction with the BLOCK-READ
and -WRITE commands (and their replacements UA and UB or U1 and
U2) outlined below. It allows access to a given byte in any
given track and sector on the disk.
Block-Read
The BLOCK-READ command is used to read a specified block into one
of the random access buffers. The syntax for the command is:
"BLOCK-READ:"{channel#}; 0; {track#};{sector#}
"B-R:"{channel#}; 0; {track#};{sector#}
"B-R" {channel#}; 0; {track#};{sector#}
The BLOCK-READ command is rarely used as it has been virtualy
replaced by the more versatile "UA" or "U1" command described
later. There is, however, an important difference in how the
two commands operate. BLOCK-READ uses the first byte of the
block to indicate the number of bytes in the block that are to be
read. Unfortunately, this is not desirable for most random disk
read operations. (The first byte of a block written as part of a
regular file contains the track number of the next block in the
file.) U1 (or UA) will read the entire block into the buffer.
Block-Write
BLOCK-WRITE is the opposite of BLOCK-READ: it is used to write
the data in a buffer to a specific block on the disk. The syntax
is similar to the BLOCK-READ command:
"BLOCK-WRITE:"{channel#}; 0; {track#};{sector#}
"B-W:"{channel#}; 0; {track#};{sector#}
"B-W" {channel#}; 0; {track#};{sector#}
Similar to BLOCK-READ, BLOCK-WRITE uses the first byte of the
buffer to indicate the number of bytes to write to the block and
has been replaced by the more versatile command "UB" or U2".
The Memory Commands
The memory commands are used to access the RAM and ROM of the
1571 directly. Unlike other DOS commands, the syntax of the
memory commands is quite rigid. Only abbreviated forms are used.
Paramters are specified as CHR$(x) values rather than as ASCII
string characters "x".
Memory-Execute
The memory-execute command is the equivalent of the SYS command
in BASIC. The syntax is:
"M-E" CHR$({lo}); CHR$({hi})
where {lo} and {hi} are the low and high bytes, respectively of
the address in 1571 ROM or RAM where you wish to begin execution.
This command allows to you access specific routines in the disk
drive's ROM or to activate other routines which you have
programmed into one of the RAM buffers of the drive. The
following example will turn on the motor of the drive for a few
seconds then turn it off again:
10 OPEN 15,8,15,"M-E" CHR$(100)CHR$(135):REM MOTOR ON
20 FOR I=1 TO 100:NEXT I:REM TIME DELAY
30 PRINT#15,"M-E" CHR$(112)CHR$(135):REM MOTOR OFF
40 CLOSE 15
This example can be used in conjunction with disk drive head
cleaner, for example. The time delay can be adjusted to suit
your needs by increasing or decreasing the value "100" in line
20. The motor on routine is at $8764 and the motor off is at
$8770 of the drive's ROM. Other useful ROM routines can be found
in the 1571 memory map listing in Appendix D.
Memory Read
Memory-read is equivalent to BASIC's PEEK() command, except that
it operates in the disk drive's memory and more than one byte can
be PEEKed at once. Up to 256 bytes can be read using memory
read. The syntax for the command is:
"M-R" CHR$({lo}); CHR$({hi}); CHR$({#bytes})
where {lo} and {hi} represent the low and high bytes,
respectively, of the address in the 1571's RAM or ROM to begin
reading at. {#bytes} specifies the number of bytes to read, from
0 to 255. If 0 is specified, then 256 bytes are read. The
memory bytes are transferred back to the computer via the command
channel and can be read with GET#'s or the KERNAL equivalent.
The following example will read any part of the 1571's RAM or ROM
and print out the decimal equivalent of the bytes:
10 OPEN 15,8,15
20 INPUT"STARTING MEMORY ADDRESS";SA
30 INPUT"# OF BYTES TO READ";NB:IF NB>255 THEN NB=0
40 SH=INT(SA/256):SL=SA-256*SH
50 PRINT#15,"M-R"CHR$(SL);CHR$(SH);CHR$(NB)
60 IF NB=0 THEN NB=256
70 FOR I=1 TO NB
80 GET#1,A$:PRINT ASC(A$);:NEXT I
90 CLOSE 15
Memory-read can also be used for accessing MFM type disks without
resorting to burst mode data transfer. For a description of this
procedure, see Burst Mode and BASIC.
Memory-Write
Memory-write is equivalent to BASIC's POKE command except that it
operates in the disk drive's memory and more than one byte can be
POKEd at once. Up to 34 bytes can be written at once using
memory-write. This limitation is due to the length of the 1571's
command input buffer (6 bytes for the command + 34 data bytes + 1
end of line marker = 41 bytes). The syntax for the command is:
"M-W" CHR$({lo}); CHR$({hi}); CHR$({#bytes}); CHR$(data bytes)
The number of data bytes included should match the number of
bytes specified by the {#bytes} parameter. However, if more
bytes are included, then the extra ones are ignored. If fewer
bytes are included, then the extra memory spaces are left
untouched.
Memory-write is most frequently used for creating custom disk
program routines in one of the drive's RAM buffers or for
changing some of the various flags and pointers in the 1571's
RAM. It can also be used for directly programming the interface
chips and the MFM disk controller chip. In the first case, the
buffer should be "protected" from use by DOS by opening the
specified buffer as a direct access buffer as outlined with the
block commands. Under these circumstances, data can also be
transfered to the buffer by writing to the file associated with
the buffer.
Memory-write can also be used for writing to the DOS buffers for
MFM disks.
User Commands
The user commands perform a variety of tasks as outlined below.
Most of the User commands are similar to those of other Commodore
disk drives. However, the extended "U0>" set is unique to the
1571 and its close cousins, the 1570 and the 128-D (A slightly
different set is also present in the new 1581 3-1/2 inch disk
drive). The user commands all jump through an indirect vector at
$0075 of the drive's RAM. This can be changed to point to your
own routines if desired. The user commands are summarized in
Table 4.
TABLE 4: The USER commands
..............................................................
Command Syntax
..............................................................
Soft Reset "U0"
Device number change "U0>"+CHR$({device#})
Head (side) select "U0>H0" (side 0)
"U0>H1" (side 1)
Mode select "U0>M0" (1541 emulation mode)
"U0>M1" (1571 mode)
Number of error retries "U0>R"+CHR$({#tries})
DOS Sector interleave "U0>S"+CHR$({interleave})
ROM selftest "U0>T"
Read sector "U1: {channel#} 0 {track#} {sector#}"
Write sector "U2: {channel#} 0 {track#} {sector#}"
Jump table "U3"; "U4"; ...; "U8"
Reset "U9"
Power up reset "U:"
Execute NMI "U;"
..............................................................
Soft Reset
The "U0" command with no additional characters specified is a
"soft reset" which restores the default jump vector table in the
disk drive's memory. This table, which is used to access some of
the more important internal functions of the disk operating
system via indirect jumps, (similar to some of the KERNAL jump
vectors in most Commodore computers) can be changed by the
experienced programmer to point to custom routines. The "U0"
command clears the changed vectors and restores the original
ones.
This is also a harmless command which can be used to test the
speed or mode of operation of the drive (i.e. 1571 mode or 1541
mode). It does not cause the drive motor to come on and will be
recognized by other Commodore disk drives as a legitimate
command. If the C-128's fast serial flag at $0a1c is set after
issuing this command (or any other disk command) to the drive,
the drive is in 1571 mode. If the flag is cleared, the drive is
either a 1541 or a 1571 in 1541 mode.
Device Number Change
The device number of the 1571 drive can be temporarily changed
using the following command:
"U0>"CHR$({device#})
where {device#} is the desired new device number. The device
number specified by this command takes precedence over that set
by the hardware switches. The new device number remains in
effect until it is changed with another device number change
command or the drive is reset by either a power off-power on
sequence or with the "UJ" command discussed below. The
acceptable device number range is 8 to 30, although generally
only 8 to 11 are used for disk drives.
This procedure is equivalent to, but considerably easier than,
the memory-write command required for earlier Commodore disk
drives. The device number parameters are stored in disk drive
memory location $77 and $78 (dec. 119 and 120), similar to other
Commodore drives.
Head Select
The 1571 is normally a double sided drive. That is, it uses both
the top and bottom surfaces of the floppy disk for recording
data. When operating in single sided 1541 mode, the 1571 drive
can use either side 0 or side 1 of the disk. (A true 1541 disk
will only use side 0.)
The command for selecting side 0 is:
"U0>H0"
To select side 1, the command is:
"U0>H1"
This feature allows you to use the second side of single sided
disks without converting them to "flippies" (i.e. taking them out
and turning them over to use the second side). The procedure
will not, however, allow you to read or write flippy disks
because the rotation direction of the disk is reversed when it is
flipped over. It is, therefore, garbled when read this way
(similar to playing an audio tape or record backwards). The only
data which can be picked up in either direction are the synch
bytes. This is what sometimes causes the 1571 with the older ROM
versions to hunt around for a few moments when initializing a
flippy disk. It can detect synch bytes on side 1, but cannot
read anything else so it tries again a few times before it can
decide whether the disk is single or double sided.
The head select command can also be used to "hide" secret data on
the back side of a disk for security or copy protection purposes.
Of course, such data cannot be accessed with a true single sided
drive, such as the 1541, which has no way of reading the second
side.
After selecting a side, the drive will perform an "I0" type
initialization and attempt to read a BAM sector. If the selected
side has not been formatted, the drive will report a read error.
Head select can also be used in 1571 mode to access the back side
of a single sided disk.
Mode Select
The 1571 has two operating modes: double sided 1571 and single
sided 1541. The 1571 mode is automatically selected when the
drive is connected to a C-128. In this case, the fast serial bus
is also enabled. The 1541 emulation mode can be specifically
switched in during C-128 operation with the command:
"U0>M0"
This converts the drive into a single sided drive, using the side
specified in a "U0>Hx" type command (or side 0 if no such command
has been issued to the drive). In 1541 mode, the fast serial bus
is disconnected and only the normal 1541 slow bus is available.
Burst mode commands are not available in 1541 mode, although the
"U0>" series is. The 1571 microprocessor clock speed is set to 1
MHz when in 1541 mode.
If the 1571 drive is connected to any other computer, 1541
emulation mode is automatically enabled on startup. In order to
access some of the advanced features of the 1571, the drive can
be forced into 1571 mode with the following command:
"U0>M1"
It should be noted that only the C-128 will support the fast
serial bus and burst mode data transfers. However, other
computers can still access many of the burst mode features, such
as the ability to read and write MFM disks, using memory reads
and writes over the 1541 serial bus. In 1571 mode, the disk
drive's microprocessor speed is set to 2 MHz, regardless of which
serial bus speed is selected.
The following example demonstrates the head select and mode
select commands by formatting both the top and bottom sides of a
disk as separate single sided disks.
10 OPEN 15,8,15,"U0>M0":REM SELECT 1541 MODE
20 PRINT#15,"U0>H0":REM SELECT SIDE 0
30 PRINT#15,"N0:FRONT SIDE,00":REM FORMAT SIDE 0
40 INPUT#15,A:REM WAIT TILL DONE
50 PRINT#15,"U0>H1":REM SELECT SIDE 1
60 PRINT#15,"N0:BACK SIDE,11":REM FORMAT SIDE 1
70 INPUT#15,A:REM WAIT TIL DONE
80 PRINT#15,"U0>H0": REM BACK TO SIDE 0
90 CLOSE 15
Now to test the effect, write a small program (or even the above
test program) and save it to disk. Use the directory command to
check that the file is indeed there. The disk name should also
be displayed. Switch to side 1 with:
OPEN 15,8,15,"U0>H1":CLOSE 15
Check the directory again. The file is not there! Save a second
program on this side under a different name. Check the directory
again to confirm it, then go back to side 0. Check the directory
again, and the first program will be there but not the second.
While this technique may seem to be a bit of a gimmick, it can be
used to recover "unused" disk space on the flip side of disks
which were formatted on single sided drives.
Try Again
Occassionaly while reading data from a disk, an error may occur.
This is detected by the disk drive when it compares its
calculated checksum for a sector with that recorded as part of
the sector data. If the two don't agree, the drive will attempt
to re-read the sector. Normally, three attempts will be made
before a read error is reported. The number of re-tries can be
set to any other value by the following command:
"U0>R" CHR$({#})
where {#} represents the number of re-tries to be performed after
an error.
If the error was caused by a transient, such as electronic noise
or a slightly dirty head, re-reading the sector a couple of times
may often result in getting a matched checksum and therefore an
acceptable read. If, however, there is a definite physical
reason for the error, such as bad disk, misaligned head, or a
deliberate error used by a disk copy protection scheme, the drive
head may chatter around a few times while successive read
attempts are being made. Although the 1571 does not have the
physical head stops which cause the loud knocks in other
Commodore disk drives, head bouncing can be a serious problem
eventually leading to alignment problems.
The head knocking can be eliminated by setting the number of
re-tries to 1. However, in doing so, you also run the risk of
getting more disk read errors because the drive will stop and
report an error after the first attempt, even if it may have been
able to extract the data on a second or third attempt.
Conversely, if you are trying to extract data from an old or
damaged disk, the number of re-tries can be temporarily increased
to improve the chances of being able to recover at least some of
the data.
Sector Interleaves
On a Commodore DOS disk, the sectors on a given track are
arranged in numerical order. That is, sector 0 is next to sector
1, which is next to sector 2, etc. However, DOS does not fill
the sectors in sequential order. The reason for this is to
improve disk access speed. Consider the case of reading a file
(LOADing a program, for example) which contains a number of
linked sectors. We will start at say track 20, sector 0. This
first sector is read. The data are then decoded from GCR to
ASCII format and transmitted to the computer, one at a time. All
the while that this is happening, the disk is rotating at a speed
of about 300 RPM. By the time the drive is ready to read the
next sector, the head might be over say sector 4 or 5. If the
next sector in the file was sector 1, the drive must wait almost
one complete revolution before it will come to sector 1 again.
Even at 300 RPM, one revolution takes about 0.2 seconds. That is
200 milliseconds, a long time in computer terms. If the file
contains 100 sectors, a full 20 seconds are wasted just waiting
for the next sector.
On the 1571, data sectors normally are filled with an interleave
of 6. This means that the next sector to be filled in our
example above would be track 20, sector 6. Since this sector has
not been passed during the data processing and transmission time,
it can be read in quick succession. The next sector in this
sequence would be sector 12, then 18. Since track 20 only goes
up to sector 18, it will then loop back to sector 5. The process
then repeats: sector 5, sector 11, sector 17, etc. This of
course, assumes that none of the sectors in the series has been
allocated to other files. In a disk which contains numerous
scratched files, many files will be disjointed or scattered
throughout the disk. Sectors in the 1571 directory are normally
filled with an interleave of 3, starting at track 18, sector 1.
(This does not include the BAM sector at track 18 sector 0.)
The sector interleave for the data area can be changed using the
command:
"U0>S" CHR$({#})
where {#} is a value from 0 to 255 which represents the
interleave factor. A value of 0 has the same effect as a value
of 1 (i.e. sequential filling of the sectors) while values
greater than about 10 will result in very complicated sector
interleave patterns and may produce unpredictable results. The
sector interleave on the directory track is 3 and is not affected
by this command.
Changing the interleave factor can speed up file access in
certain well defined circumstances. Setting it to a number other
than 6 may improve the file read speed of some files, while
slowing down access to other files. Table 5 is a summary of the
times required for the LOAD speed of a 27 block test file which
was SAVEd with different interleave factors. (To eliminate
possible errors caused by head movement times, the file was
erased and re-written to the same track of the disk with each new
interleave factor. Times were taken using CIA #2 TOD clock.)
Table 5: Effect of Interleave Factor on File LOAD Times
............................................................
Interleave Value LOAD Time (27 Blocks, in seconds)
............................................................
0 6.7
1 6.7
2 6.6
3 6.6
4 1.8
5 2.8
6 3.3
10 4.7
15 6.8
.............................................................
The file write speed is not normally affected by the sector
interleave because the freshly written sector is immediately
re-read to confirm that it has been properly written. This
process requires the disk to travel a minimum of one complete
revolution or 0.2 seconds for each sector written, in addition to
the data transmission, data write and read operations. This is
the major reason why disk write operations on the 1571 are much
slower than disk reads and are, in fact, only marginally faster
than the normally much slower 1541 drive.
It should be noted that this command is totally different in
function and application than the burst mode sector "interleave"
command discussed in "Burst Mode Commands".
ROM Check
The 1571 DOS contains a command for testing itself based on a
computed checksum for the machine language code contained in the
ROM. The command is:
"U0>T"
If the test fails (that is, if the computed checksum from memory
location $8002 to $FFFF does not match the value stored at ROM
location $8000-8001), the green "drive busy" light will flash.
This is the same self test that the drive goes through on power
up, and is a simple diagnostic procedure that can be used to test
the drive in the event that damage to the ROM's might be
suspected after the drive has been turned on. Otherwise, it
serves no real purpose.
Sector Read
As mentioned previously, the BLOCK-READ command does not work
quite the way that one might expect in most cases. To overcome
the problem, B-R has been replaced by the more versatile
"sector-read" command. The sector-read command will read the
entire specified sector into the indicated random access buffer.
Similar to the BLOCK-READ command, a random access buffer must be
opened along with the command channel prior to using the command.
The command has the following syntax:
"U1"{channel#};0;{track#};{sector#}
Similar to the B-R command, the "0" character refers to the drive
number. Since the 1571 is a single drive, this is always zero.
{channel#} specifies the channel (secondary address) which was
opened as the random buffer while {track#} and {sector#} specify
the track and sector to read. For a single sided disk, {track#}
can be in the range of 1 to 35, while for a double sided disk the
range is 1 to 70. All parameters are specified as ASCII strings
rather than CHR$(x) values. Note that similar to the Block
commands, the channel number is used in this command, not the
logical file number.
Alternatively, the "U1" can be replaced by any of: "U1:", "UA",
or "UA:". The remaining parameters are identical for each of the
alternate formats.
All disks are assumed to be single sided unless they have been
initialized by the "I0" command and the double sided flag in the
BAM sector (byte 2 of track 18, sector 0) has been set to a value
of $80 (decimal 128). However, you can still attempt to read the
second side of a "single sided" disk by using the head select
command to switch to side 1 of the disk ("U0>H1") before issueing
the sector-read command.
The {sector#} parameter must be in the valid range for the
specified track as given in Table 6.
Table 6: Sector Number Ranges
................................................
Track range Sector Numbers
................................................
side 0:
1 to 17 0 to 20
18 to 24 0 to 18
25 to 30 0 to 17
31 to 35 0 to 16
side 1:
36 to 52 0 to 20
53 to 59 0 to 18
60 to 65 0 to 17
66 to 70 0 to 16
.................................................
Attempting to access a track or sector outside of the valid range
will result in a DOS error code 66, ILLEGAL TRACK AND SECTOR
xx,yy error. The two numbers represented by xx and yy indicate
the illegal track and sector, respectively, that you tried to
access.
Once the sector has been read into the disk buffer, its contents
can be recovered using a series of GET#'s (or possibly INPUT#'s,
if you realize the implications of doing so) or the KERNAL
equivalent from the random buffer channel. The BLOCK-POINTER
command can be used to position the byte pointer before using a
GET#, if access to a specific byte is desired.
The following example can be used to read the BAM sector of a
disk in device 8 into the array BA(x):
10 DIM BA(255)
20 OPEN 15,8,15,"I0":OPEN 1,8,2,"#"
30 PRINT#15,"U1 2 0 18 0"
40 FOR I=0 TO 255:GET#1,A$
50 BA(I)=ASC(A$):NEXT
60 CLOSE 1:CLOSE 15
Once in the array BA(x), you can easily determine which sectors
of the disk are being used.
Sector-Write
Analogous to the Sector-Read command, a true Sector-Write command
is also provided in the 1571 DOS. The syntax is:
"U2" {channel#}; 0; {track#}; {sector#}
The parameters are identical to those used for the Sector-Read
command. Alternatively, the "U2" portion can be replaced by any
one of: "U2:", "UB", or "UB:".
The procedure for writing data to a specific track and sector on
the disk can be summarized as follows:
- OPEN the command channel
- OPEN the random channel buffer
- PRINT# data to the random channel buffer (use B-P first,
if desired)
- write sector to disk with U2 command
- repeat for other sectors, if desired
- CLOSE random buffer channel
- CLOSE command channel
The Sector-Write command is most often used for applications such
as modifying the directory track, copying disks, and writing BOOT
sectors on C-128 disks, editing the data stored directly on a
disk. It is also frequently used by some commercial data base
programs.
User Jumps
The U3 to U8 (or UC to UH) commands are used to access a mini
custom jump table in the disk drive's RAM. They are similar to
the memory-execute command discussed previously, but no address
is specified because each command will begin execution at a
specific address as listed in Table 7.
Table 7: User jump locations
.......................................
Command Begin Execution At
.......................................
"U3" or "UC" $0500
"U4" or "UD" $0503
"U5" or "UE" $0506
"U6" or "UF" $0509
"U7" or "UG" $050c
"U8" or "UH" $050f
......................................
Note that the entry points are spaced 3 bytes apart. This allows
you to create your own jump table. Each entry would be of the
form:
JMP $xxxx
where $xxxx is the address of your machine code in RAM or a
routine in the 1571's ROM. This instruction takes up three
bytes, hence the spacing of the entry points. Of course, if you
only needed one entry point, you could begin your code at $0500
directly without any further indirect jumps. However, in such a
case you should not use U4 to U8 because they will more than
likely cause the disk drive to crash. The code for the jump
table can be written to the 1571's RAM by either the memory-write
command, or by opening buffer #2 as a random access buffer and
using the sector-read command to get a machine code program from
a specific disk sector.
More Resets
Three general reset type commands, operating at different
degrees, are provided in 1571 DOS. Each command is issued as is,
with no additional parameters specified. The first command is a
"soft" reset. This performs the function of cancelling any
previously issued commands, except the device number change, mode
select and head select, and return the drive to its standby state
waiting for the next command. The syntax is:
"U9" (or "UI")
In 1541 mode, UI is also used to select the serial bus speed.
"UI+" goes to 1541 bus speed (for a C-64, C-16, Plus/4) while
"UI-" goes to the slightly faster 1540 bus speed (for a VIC-20
only).
A "hard" reset can be performed using the "U:" or "UJ" command.
This will cancel all previous commands, including those not
affected by the "U9" command, and restore the drive to its
initial power on state. This command will also activate the DOS
error code 73, CBM DOS V3.0 1571, message allowing the computer
to determine which type of drive is connected.
The final reset command is unique to the 1571: it actuates the
drive's interupt routine. Normally, this command will not appear
to do anything, unless the interupt vector at $02a9 of the 1571's
RAM has been changed to point to a custom routine or the job loop
parameters have been altered through memory writes. The syntax
for this command is:
"U;" (or "UK")
DOS Internals
The internal operation of the disk drive is complicated indeed.
The command interpreter takes instructions from the computer over
the serial bus, digests them into individual "jobs" and passes
the job instructions to the controller for action. In this
respect, the interpreter is much like a construction supervisor
and the controller is like the workers who actually do the
physical work.
For example, to LOAD a program, the interpreter receives the LOAD
command from the computer along with a filename. The interpreter
must then assign a buffer for the directory and tell the
controller to read the first directory sector into this buffer.
The interpreter then scans the buffer and looks for a match with
the desired filename. If none is found, then the interpreter
tells the controller to fetch the next directory sector, and so
on, until either the filename is matched or the last directory
sector has been read. If the filename has not been matched, the
interpreter returns a "file not found" error message to the
computer. If the file is found, the interpreter gets the
starting sector number from the directory entry and proceeds to
tell the controller the sequence of sectors to read. After each
sector is read, the interpreter sends the data to the computer
and determines the next sector in the chain. The process is
repeated until the interpreter decides that there are no more
sectors in the file.
The sequence of operations for a file SAVE is even more complex
because it involves reading the BAM, deciding what sectors are
free, writing then verifying the file sector by sector, updating
the BAM and writing the new BAM as well as directory back to the
disk.
The Job Queue
For most applications, the high level (relatively speaking) DOS
commands discussed in the previous sections of this document are
more than adequate. However, for highly specialized
applications, such as esoteric disk copy protection schemes, you
can also program the drive directly to do things that it was not
originally intended to do by using the "job queue". This is
essentially the lowest level that you can operate in DOS, short
of writing your own DOS code. (Since the 1571 is limited in the
amount of available RAM, writing your own extensive DOS routines
is not very practical.) It should be noted that although the job
queue seems to be straight forward enough to use, it should be
used with a good deal of caution. Its main weakness (and also
its main strength, depending on your point of view) is that no
error checking is done on the job paramters (track and sector
values) before attempting to execute a command. The controller
assumes that the command interpreter has caught any errors before
setting up the job.
The job queue is located in zero page memory of the 1571's RAM.
It is merely a series of locations (call them pigeon holes if you
like) which are used to send messages between the two parts of
the operating system: the command interpreter and the controller.
The associated memory locations for the job parameters are
summarized in Table 8.
The command interpreter takes the high level command, such as to
read data from a file, and breaks it down into a series of
discrete jobs, each of which involves only one action (such as
read, write, or verify) on one specific track/sector combination.
The appropriate parameters are passed to the controller through
the job queue. During the interupt cycle (about 100 times per
second), the controller scans the job queue memory locations. If
a value of $80 or greater is found in the queue, the controller
performs the command using the corresponding track and sector
data and data buffer locations and then places the result status
code back into the queue and continues to scan the remainder of
the queue.
For example, if memory location $00 contained a value of $80,
location $06 had a value of 1 and location $07 had a 4, then the
controller would read track 1, sector 4 into data buffer #0 which
is at $300 to $3ff. The specific command codes and result status
codes will be discussed in the next section of this document.
Note that although space has been allocated in the job queue for
six buffers, the last buffer (#5) is not actually present in RAM.
Table 8: Job Queue Memory Addresses
...............................................
Job Queue Track Sector Data Buffer
...............................................
$00 $06 $07 $0300-$03ff
$01 $08 $09 $0400-$04ff
$02 $0a $0b $0500-$05ff
$03 $0c $0d $0600-$06ff
$04 $0e $0f $0700-$07ff
$05 $10 $11 (not used)
...............................................
Commands
Table 9 summarizes the individual job queue commands. Note that
all command codes have values of $80 (decimal 128) or greater.
Table 9: Job Queue Command Summary
...............................................................
Job Code Action
(hex) (dec)
...............................................................
$80 128 read sector
$88 136 read another sector on same track
$90 144 write sector
$a0 160 verify sector
$b0 178 look for sector header
$c0 192 home to track 1
$d0 208 execute program in buffer
$e0 224 combine program in job loop
$f0 240 format disk
................................................................
After each command has executed, it will return one of the error
codes listed in Table 10. Note that all error codes have values
of less than $10 (decimal 16).
Table 10: Job Return and Error Codes
.........................................................
Return/Error Code Meaning
.........................................................
$0 or 1 no error
$2 sector header not found
$3 sync mark not found
$4 data block not found
$5 data block checksum error
$6 formatting error
$7 verify error
$8 write protect on during write
$9 header checksum error
$a (10) data block too long
$b (11) disk ID mismatch
$c (12) (not currently used)
$d (13) index hole not found
$e (14) burst mode syntax error
$f (15) drive not ready/no disk
.........................................................
As mentioned previously, the controller does not check to see if
track and sector locations contain "valid" numbers before it
tries to execute the command in the job queue. This allows you
the complete flexibility to read and write beyond the normal 1 to
35 track per side range and outside of the normal sector number
range for a given track. This is most useful for "hiding" data
on the disk for use in copy protection schemes because such data
cannot be read by most disk copiers, unless they are specifically
designed for it. Even then, the copier must know the exact
paramters that you have specified before it can find the hidden
sectors.
Programming the Job Loop
Because the job queue is scanned very rapidly, you must set up
the tracks and sector parameters (and place the data in the
buffer if doing a write operation) before putting the job code in
the job queue.