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.