The Acorn DFS Osword commands - by - Gordon Horsington ---------------------------------------------------------- Module 2. The DFS Osword commands (part 2) ------------------------------------------ +----------------------------------------------------------+ | All the DFS modules in this series use programs which | | experiment with the format and contents of discs. These | | experiments may have disasterous effects if you use any | | of the programs on discs which store programs or data | | which you cannot afford to lose. You should first try | | out the programs using discs that have either been | | duplicated or, better still, have not been used at all. | +----------------------------------------------------------+ ---------- Osword &7F ---------- Osword &7F executes the 8271 disc controller commands. If the disc interface uses a 1770 disc controller then Osword &7F emulates the 8271 command set using the 1770. The complete command set executed by Osword &7F is shown in figure 1. Osword &7F commands from &69 to &7D were covered in module 1. In this module I will explain how to use the Osword &7F command numbers &4A to &63. +---------+--------+------+-------------------------------------------+ | Command | Param- | 1770 | Action | | number | eters | | | +---------+--------+------+-------------------------------------------+ | &4A | 2 | Yes | Write data 128 bytes | | &4B | 3 | Yes | Write data multi-sector | | &4E | 2 | Yes | Write deleted data 128 bytes | | &4F | 3 | Yes | Write deleted data multi-sector | | &52 | 2 | Yes | Read data 128 bytes | | &53 | 3 | Yes | Read data multi-sector | | &56 | 2 | Yes | Read data and deleted data 128 bytes | | &57 | 3 | Yes | Read data and deleted data multi-sector | | &5B | 3 | Yes | Read sector ids | | &5E | 2 | Yes | Verify data and deleted data 128 bytes | | &5F | 3 | Yes | Verify data and deleted data multi-sector | | &63 | 5 | Yes | Format track | | &69 | 1 | Yes | Seek | +---------+--------+------+-------------------------------------------+ | &6C | 0 | Part | Read drive status | | &75 | 4 | Part | Initialise 8271 | | &75 | 4 | Part | Load bad tracks | | &7A | 2 | Part | Write special register | | &7D | 1 | Part | Read special register | +---------+--------+------+-------------------------------------------+ Figure 1. The Osword &7F commands --------------------------------- -------------------------- Osword &7F Read Sector IDs -------------------------- Before using this command you should ensure that the appropriate track register contains the current physical track number or use the Osword &7F Seek command to seek track 0. Osword &7F Read Sector IDs uses the appropriate track register as a base from which to seek a specified physical track. It then reads the required number of sector IDs and stores them in the buffer area specified in the parameter block. Sector IDs are transfered into the buffer area in physical sector order. The command returns four bytes For each sector ID that it reads. byte 0 = logical track number byte 1 = head number byte 2 = logical sector number byte 3 = data size code (0=128, 1=256, ... 4=2048) The following parameter block is used by Osword &7F read sector IDs: Parameter block &00 = drive number (&00-&03 or &FF) Parameter block &01 - &04 = buffer address for sector IDs Parameter block &05 = &03 (3 command parameters) Parameter block &06 = &5B (read sector IDs command) Parameter block &07 = physical track number Parameter block &08 = &00 Parameter block &09 = number of IDs to be read Parameter block &0A = result byte One of many possible uses for this command is to check if a disc has been formatted. If Osword &7F Read Sector IDs fails to find at least one sector on track zero the most probable reason is that the disc has not been formatted and this will be reported as error number &18, sector not found (see figure 2). The program NOTFORM uses this idea to see if a disc in the current drive has been formatted. +--------+----------------------------+ | Result | Interpretation | +--------+----------------------------+ | &02 | Scan met equal ** | | &04 | Scan met not equal ** | | &08 | Clock error | | &0A | Late DMA ** | | &0C | Sector ID CRC error | | &0E | Data CRC error | | &10 | Drive not ready | | &12 | Disc write protected | | &14 | Physical track 0 not found | | &16 | Write fault | | &18 | Sector not found | +--------+----------------------------+ | Errors marked ** should not occur | +-------------------------------------+ Figure 2. The error codes returned in the result byte ----------------------------------------------------- 10 REM: NOTFORM 20 osword=&FFF1 30 DIM mcode &100 40 FOR pass = 0 TO 2 STEP 2 50 P%=mcode 60 [ OPT pass 70 LDA #&7F 80 LDX #block MOD 256 90 LDY #block DIV 256 100 JSR osword 110 RTS 120 .block 130 EQUB &FF \ current drive 140 EQUD buffer \ buffer address 150 EQUB &03 \ 3 parameters 160 EQUB &5B \ read sector IDs 170 EQUB &00 \ track 0 180 EQUB &00 190 EQUB &01 \ read 1 sector 200 .result 210 EQUB &00 \ result byte 220 .buffer 230 EQUD &00 240 ] 250 NEXT 260 CALL mcode 270 IF ?result=&18 PRINT"Disc not formatted" ELSE PRINT"Disc formatted" The Osword &7F Read Sector IDs command was used in the program IDSDUMP used in module 0. After working through this module you might like to go back to module 0 and look again at the example programs. ----------------------- Osword &7F Format Track ----------------------- The Osword &7F Format Track command uses a sector table stored in the buffer specified in the parameter block. This table contains four bytes for every ID field on the track. For each sector to be on the disc the following bytes must be stored in the buffer: byte 0 = logical track number (&00-&FF) byte 1 = head number (use &00) byte 2 = logical sector number (&00-&FF) byte 3 = data size code (0=128, 1=256, ... 4=2048) The following parameter block is used with the Osbyte &7F Format Track command: Parameter block &00 = drive number (&00-&03 or &FF) Parameter block &01 - &04 = buffer address for sector IDs Parameter block &05 = &05 (5 command parameters) Parameter block &06 = &63 (format track command) Parameter block &07 = physical track number Parameter block &08 = gap 3 size (see figure 2) Parameter block &09 = sector size/number of sectors Parameter block &0A = gap 5 size (always use &00) Parameter block &0B = gap 1 size (always use &10) Parameter block &0C = result byte The gap 3 size can be taken from figure 3 (all numbers in figure 3 are in decimal). The most significant 3 bits of the number stored in parameter block &09 contain the sector size code (column 2 of figure 3). The least significant 5 bits contain the number of sectors per track. To calculate the number to be stored in parameter block &09 multiply the size code by 32 and add the number of sectors. For example, if you want to format a track with five sectors of 512 bytes then parameter block &09 will contain 2*32+5 = 69 = &45. +-------------+-----------+--------+------+------+------+------+------+ | No. Sectors | Size code | Length | Gap1 | Gap2 | Gap3 | Gap4 | Gap5 | +-------------+-----------+--------+------+------+------+------+------+ | 18 | 0 | 128 | 16 | 11 | 11 | 24 | 0 | | 10 | 1 | 256 | 16 | 11 | 21 | 30 | 0 | | 5 | 2 | 512 | 16 | 11 | 74 | 88 | 0 | | 2 | 3 | 1024 | 16 | 11 | 255 | 740 | 0 | | 1 | 4 | 2048 | 16 | 11 | 0 | 1028 | 0 | +-------------+-----------+--------+------+------+------+------+------+ Figure 3. The relationship between sector size code, length and gap size. ------------------------------------------------------------------------- The Osword &7F Format Track command uses the appropriate track register as a base from which to seek the specified physical track. It then uses the sector IDs stored in the buffer to create the ID fields for each sector. It calculates and writes the ID field CRC bytes, creates the correct gap sizes, fills the data fields with bytes of &E5, and calculates and writes the data field CRC bytes. The program FORM10 can be used to format physical track &27 of the disc in the current drive with 10 sectors of 256 bytes. This program will destroy all the data stored on track &27 - you have been warned! The buffer used in the program FORM10 stores 4 bytes for each sector. Taking physical sector &00 in line 240 as an example, The bytes &27, &00, &00 and &01 are stored (the order of the bytes is reversed with the EQUD command). These four bytes represent the logical track number, the head number, the logical sector number and the data size code. You can alter the logical track and sector numbers and use the IDSDUMP program from module 0 to see the effect this has on the format of the disc. If you alter the logical track number you will be unable to *BACKUP the disc. 10 REM: FORM10 20 DIM mcode &100 30 osword=&FFF1 40 FORpass=0 TO 2 STEP 2 50 P%=mcode 60 [ OPT pass 70 LDA #&7F 80 LDX #block MOD 256 90 LDY #block DIV 256 100 JSR osword 110 RTS 120 .block 130 EQUB &FF \ current drive 140 EQUD buffer \ address of sector table 150 EQUB &05 \ 5 parameters 160 EQUB &63 \ format track command 170 EQUB &27 \ physical track &27 180 EQUB 21 \ gap 3 (from figure 2) 190 EQUB &2A \ 10 sectors of 256 bytes 200 EQUB &00 \ gap 5 (always &00) 210 EQUB &10 \ gap 1 (always &10) 220 EQUB 0 \ result byte 230 .buffer 240 EQUD &01000027 250 EQUD &01010027 260 EQUD &01020027 270 EQUD &01030027 280 EQUD &01040027 290 EQUD &01050027 300 EQUD &01060027 310 EQUD &01070027 320 EQUD &01080027 330 EQUD &01090027 340 ] 350 NEXT 360 CALL mcode There is more to formatting a disc than just formatting all the tracks. It is also necessary to create an empty catalogue on track 0 of the disc. Formatting discs will be covered in more detail in module 3. ---------------------------------------------------- Osword &7F Verify Data and Deleted Data multi-sector ---------------------------------------------------- Osword &7F Verify Data and Deleted Data multi-sector uses the appropriate track register as a base from which to seek the track and sector specified in the parameter block. It attempts to verify the sector and returns &00 in the result byte if it is successful. It returns &20 in the result byte if deleted data have been successfully verified. If more than one sector is specified this procedure repeats until either all the sectors have been verified or an error occurs. The following parameter block is used with the Osbyte &7F Verify Data and Deleted Data multi-sector command: Parameter block &00 = drive number (&00-&03 or &FF) Parameter block &01 - &04 = buffer address (not used) Parameter block &05 = &03 (3 command parameters) Parameter block &06 = &5F (verify multi-sector command) Parameter block &07 = logical track number Parameter block &08 = logical sector number Parameter block &09 = sector size/number of sectors Parameter block &0A = result byte The most significant 3 bits of the number stored in parameter block &09 contain the sector size code (column 2 of figure 3). The least significant 5 bits contain the number of sectors per track. To calculate the number to be stored in parameter block &09 multiply the size code by 32 and add the number of sectors. For example, if you want to verify a track with ten sectors of 256 bytes then parameter block &09 will contain 1*32+10 = 42 = &2A. If you want to verify discs that use different physical and logical track numbers it is necessary to use the Osword &7F Seek command to find the appropriate track, Osword &7F Read Sector IDs to read the logical track and sector number, and Osword &7F Write Special Register to write the logical track number into the appropriate track register before using Osword &7F Verify Data and Deleted Data multi-sector. After verifying the sector(s) it is then necessary to use Osword &7F Write Special Register to write the physical track number back into the appropriate track register. This procedure was used in the program VERIFY in module 0. The following code could be used to verify track &27 of the disc formatted with the program FORM10 LDA #&7F LDX #block MOD 256 LDY #block DIV 256 JSR &FFF1 RTS .block EQUB &FF \ current drive EQUD &00 \ buffer address (not used) EQUB &03 \ 3 parameters EQUB &5F \ verify command EQUB &27 \ logical track &27 EQUB &00 \ start with logical sector &00 EQUB &2A \ 10 sectors of 256 bytes EQUB &00 \ result byte ------------------------------------------------- Osword &7F Verify Data and Deleted Data 128 bytes ------------------------------------------------- If you need to verify just one sector of 128 bytes you can use the Osword &7F Verify Data and Deleted Data 128 bytes command. This command uses the following parameter block. Parameter block &00 = drive number (&00-&03 or &FF) Parameter block &01 - &04 = buffer address (not used) Parameter block &05 = &02 (2 command parameters) Parameter block &06 = &5E (verify 128 bytes command) Parameter block &07 = logical track number Parameter block &08 = logical sector number Parameter block &09 = result byte Although using this command saves you the trouble of calculating the sector size/number of sectors parameter, I cannot recommend using it when the multi-sector command is so much more versitile. ---------------------------------- Osword &7F Write Data multi-sector ---------------------------------- Osword &7F Write Data multi-sector uses the appropriate track register as a base from which to seek the track and sector specified in the parameter block. If it cannot find the track and sector it returns the sector not found error (&18) in the result byte. If it finds the required track and sector it writes a data mark at the start of the data field and copies the first sector of data from the buffer to the specified sector. If more than one sector is specified this procedure repeats until either all the sectors have been written or an error occurs. The following parameter block is used with the Osword &7F Write Data multi-sector command. Parameter block &00 = drive number (&00-&03 or &FF) Parameter block &01 - &04 = buffer address Parameter block &05 = &03 (3 command parameters) Parameter block &06 = &4B (write data multi-sector command) Parameter block &07 = logical track number Parameter block &08 = logical sector number Parameter block &09 = sector size/number of sectors Parameter block &0A = result byte The most significant 3 bits of the number stored in parameter block &09 contain the sector size code (column 2 of figure 3). The least significant 5 bits contain the number of sectors per track. To calculate the number to be stored in parameter block &09 multiply the size code by 32 and add the number of sectors. For example, if you want to verify a track with ten sectors of 256 bytes then parameter block &09 will contain 1*32+10 = 42 = &2A. The program WRITE10 can be used to demonstrate this command. This program will destroy all the data stored on track &01 of the disc it uses - you have been warned! WRITE10 uses an normally formatted DFS disc and stores 2.5k of data on track &01. The buffer starts at PAGE (line 240) and so the program could be used to store a small BASIC program on a disc. The data are stored without an entry in the DFS catalogue and cannot be read using any of the DFS star commands. If you use the DFS commands to store any other data on the disk, the data stored with WRITE10 could be overwritten. The data can be read from the disc using the Osword &7F Read Data and Deleted Data command which is explained later in this module. 10 REM: WRITE10 20 mcode = &0A00 30 osword=&FFF1 40 page = PAGE 50 FORpass=0 TO 2 STEP 2 60 P%=mcode 70 [ OPT pass 80 LDA #&7F 90 LDX #block MOD 256 100 LDY #block DIV 256 110 JSR osword 120 LDA result 130 BEQ ok 140 BRK 150 BRK 160 EQUS "Write error" 170 .ok 180 BRK 190 EQUS "Write sucessful" 200 BRK 210 BRK 220 .block 230 EQUB &FF \ current drive 240 EQUD page \ start at PAGE 250 EQUB &03 \ 3 parameters 260 EQUB &4B \ write data multi-sector 270 EQUB &01 \ logical track 1 280 EQUB &00 \ start logical sector 0 290 EQUB &2A \ 10 sectors of 256 bytes 300 .result 310 EQUB &00 \ result byte 320 ] 330 NEXT 340 PRINT''"Type: CALL &";~mcode;" to save 10 sectors"' ------------------------------- Osword &7F Write Data 128 bytes ------------------------------- If you need to write just one sector of 128 bytes you can use the Osword &7F Write Data 128 bytes command. This command uses the following parameter block. Parameter block &00 = drive number (&00-&03 or &FF) Parameter block &01 - &04 = buffer address Parameter block &05 = &02 (2 command parameters) Parameter block &06 = &4A (write data 128 bytes command) Parameter block &07 = logical track number Parameter block &08 = logical sector number Parameter block &09 = result byte Although using this command saves you the trouble of calculating the sector size/number of sectors parameter, I cannot recommend using it when the multi-sector command is so much more versitile. ------------------------------------------ Osword &7F Write Deleted Data multi-sector ------------------------------------------ Osword &7F Write Deleted Data multi-sector uses the appropriate track register as a base from which to seek the track and sector specified in the parameter block. If it cannot find the track and sector it returns the sector not found error (&18) in the result byte. If it finds the required track and sector it writes a deleted data mark at the start of the data field and copies the first sector of data from the buffer to the specified sector. If more than one sector is specified this procedure repeats until either all the sectors have been written or an error occurs. The following parameter block is used with the Osword &7F Write Deleted Data multi-sector command. Parameter block &00 = drive number (&00-&03 or &FF) Parameter block &01 - &04 = buffer address Parameter block &05 = &03 (3 command parameters) Parameter block &06 = &4F (write deleted data multi-sector command) Parameter block &07 = logical track number Parameter block &08 = logical sector number Parameter block &09 = sector size/number of sectors Parameter block &0A = result byte The most significant 3 bits of the number stored in parameter block &09 contain the sector size code (column 2 of figure 3). The least significant 5 bits contain the number of sectors per track. To calculate the number to be stored in parameter block &09 multiply the size code by 32 and add the number of sectors. For example, if you want to verify a track with ten sectors of 256 bytes then parameter block &09 will contain 1*32+10 = 42 = &2A. The program WRITE10 can be modified to demonstrate this command. Alter line 260 from EQUB &4B to EQUB &4F. Using deleted data will effectivly disable the *BACKUP command. Don't forget that this program will destroy all the data stored on track &01 of the disc it uses - you have been warned! --------------------------------------- Osword &7F Write Deleted Data 128 bytes --------------------------------------- If you need to write just one sector of 128 bytes of deleted data you can use the Osword &7F Write Deleted Data 128 bytes command. This command uses the following parameter block. Parameter block &00 = drive number (&00-&03 or &FF) Parameter block &01 - &04 = buffer address (not used) Parameter block &05 = &02 (2 command parameters) Parameter block &06 = &4F (write deleted data 128 bytes command) Parameter block &07 = logical track number Parameter block &08 = logical sector number Parameter block &09 = result byte Although using this command saves you the trouble of calculating the sector size/number of sectors parameter, I cannot recommend using it when the multi-sector command is so much more versitile. -------------------------------------------------- Osword &7F Read Data and Deleted Data multi-sector -------------------------------------------------- Osword &7F Read Data and Deleted Data multi-sector uses the appropriate track register as a base from which to seek the track and sector specified in the parameter block. If it cannot find the track and sector it returns the sector not found error (&18) in the result byte. If it finds the required track and sector it copies the first sector of data into the buffer specified in the parameter block. If more than one sector is specified this procedure repeats until either all the sectors have been read or an error occurs. The following parameter block is used with the Osword &7F Write Deleted Data multi-sector command. Parameter block &00 = drive number (&00-&03 or &FF) Parameter block &01 - &04 = buffer address Parameter block &05 = &03 (3 command parameters) Parameter block &06 = &57 (read data and deleted data multi-sector) Parameter block &07 = logical track number Parameter block &08 = logical sector number Parameter block &09 = sector size/number of sectors Parameter block &0A = result byte The most significant 3 bits of the number stored in parameter block &09 contain the sector size code (column 2 of figure 3). The least significant 5 bits contain the number of sectors per track. To calculate the number to be stored in parameter block &09 multiply the size code by 32 and add the number of sectors. For example, if you want to verify a track with ten sectors of 256 bytes then parameter block &09 will contain 1*32+10 = 42 = &2A. The program READ10 can be used to demonstrate this command. This program reads the data written onto a disc by the program WRITE10, which was used to illustrate the Osword &7F Write Data multi-sector command. READ10 uses an normally formatted DFS disc and reads 2.5k of data from track &01. The buffer starts at PAGE (line 240) and so the program could be used to read a small BASIC program from a disc. The programs WRITE10, with the Osword &7F write deleted data command, and READ10 could be used to create a copy-protected disc. I will return to copy-protection in later modules of this series. 10 REM: READ10 20 mcode = &0A00 30 osword=&FFF1 40 page = PAGE 50 FORpass=0 TO 2 STEP 2 60 P%=mcode 70 [ OPT pass 80 LDA #&7F 90 LDX #block MOD 256 100 LDY #block DIV 256 110 JSR osword 120 LDA result 130 BEQ ok 140 BRK 150 BRK 160 EQUS "Read error" 170 .ok 180 BRK 190 EQUS "Read sucessful" 200 BRK 210 BRK 220 .block 230 EQUB &FF \ current drive 240 EQUD page \ start at PAGE 250 EQUB &03 \ 3 parameters 260 EQUB &57 \ read data and deleted data 270 EQUB &01 \ logical track 1 280 EQUB &00 \ start logical sector 0 290 EQUB &2A \ 10 sectors of 256 bytes 300 .result 310 EQUB &00 \ result byte 320 ] 330 NEXT 340 PRINT''"Type: CALL &";~mcode;" to read 10 sectors"' ----------------------------------------------- Osword &7F Read Data and Deleted Data 128 bytes ----------------------------------------------- If you need to read just one sector of 128 bytes you can use the Osword &7F Read Data and Deleted Data 128 bytes command. This command uses the following parameter block. Parameter block &00 = drive number (&00-&03 or &FF) Parameter block &01 - &04 = buffer address (not used) Parameter block &05 = &02 (2 command parameters) Parameter block &06 = &56 (read data and deleted data 128 bytes) Parameter block &07 = logical track number Parameter block &08 = logical sector number Parameter block &09 = result byte Although using this command saves you the trouble of calculating the sector size/number of sectors parameter, I can not recommend using it when the multi-sector command is so much more versitile. --------------------------------- Osword &7F Read Data multi-sector --------------------------------- If you need to read data which is not marked as deleted data then you can use the Osword &7F Read Data multi-sector command. This command uses the following parameter block. Parameter block &00 = drive number (&00-&03 or &FF) Parameter block &01 - &04 = buffer address (not used) Parameter block &05 = &02 (2 command parameters) Parameter block &06 = &53 (read data multi sector command) Parameter block &07 = logical track number Parameter block &08 = logical sector number Parameter block &09 = sector size/number of sectors Parameter block &0A = result byte This command can be used in exactly the same way as the Osword &7F Read Data and Deleted Data command but it cannot read deleted data. There is no need to use this command when the Osword &7F Read Data and Deleted Data command is more versitile. ------------------------------ Osword &7F Read Data 128 bytes ------------------------------ If you need to read just one sector of 128 bytes of data which is not marked as deleted data then you can use the Osword &7F Read Data 128 bytes command. This command uses the following parameter block. Parameter block &00 = drive number (&00-&03 or &FF) Parameter block &01 - &04 = buffer address (not used) Parameter block &05 = &02 (2 command parameters) Parameter block &06 = &52 (read data 128 bytes command) Parameter block &07 = logical track number Parameter block &08 = logical sector number Parameter block &09 = result byte Although using this command saves you the trouble of calculating the sector size/number of sectors parameter, I can not recommend using it when the multi-sector command is so much more versitile.