OSWORD &7F - Single Density Disk Access ======================================= OSWORD &7F passes an 8271-style control block to the floppy disk controller to access disks. Double-density DFSs also allow OSWORD &7F to access double-density disks. On extry: XY+0 drive number %pxDDDdsd XY+1..4 data address XY+5 number of parameters XY+6 command XY+7... parameters XY+n returned result No contents of the control block should be relied upon on exit other than the result byte. Some systems update the control block, some systems do not. Some DFSs, such as DFS 2.45 supplied in the Master MOS 3.50 ROM, only respond to OSWORD &7F if DFS is the current filing system and fail silently if any other filing system is selected. Drive number ============ The drive number specifies the drive to access. If bit 7 is set, then the previously-used drive is used, and the drive status check is skipped. The drive number is expressed as a binary number %pxDDDdsd. b7: p : If 1, selects the previously-used drive and density b5-b3: DDD : select the drive density: %xx0=Acorn single density %xx1=Acorn double density %0xx=Watford current density %10x=Watford single density %11x=Watford double density b2,b0: dd : physical drive number b1: s : side Single density DFSs do not have any ability to select double density disk access. Acorn DFSs select the density with b3, Watford DFSs select the density with b4 and b5. To specify a density in a manner compatible with both Acorn and Watford DFSs specify the density with both methods: %001000sd - to specify single density %001110sd - to specify double density Most DFSs do not implement physical drives numbers larger than 1 (logical drives greater than 3). Selecting the previously selected drive can only be relied upon if DFS is the currently selected filing system. A drive number of &FF should be passed to select the previously used drive. DFS 2.xx in the Master MOS 3.20 ROM incorrectly passes the density bit in b3 to the drive control register b3 instead of b5, so OSWORD &7F cannot access double density disks without patching the DFS. Commands ======== Command Parameters Meaning &40 Scan data ** &44 Scan data and deleted data multi-sector ** &4A Write data 128 bytes &4B Write data &4E Write deleted data 128 bytes &4F Write deleted data &52 Read data 128 bytes &53 Read data &56 Read data and deleted data 128 bytes &57 Read data and deleted data &5B Read IDs &5E Verify data and deleted data 128 bytes &5F Verify data and deleted data multi-sector &63 Format track &64 (EDOS) Write track &65 (EDOS) Read track &69 Seek &6C --none-- Read drive status &75 <&0D> Initialise &75 <&1n> Specify bad tracks &76 --none-- (EDOS) Force interrupt &7A Write special register &7D Read special register &E0 (1770) Read track &F0 (1770) Write track ** Not possible on a BBC as needs DMA hardware. ===Size + Count=== Bits 0 to 4 specify the number of sectors to be read or written. Specifying zero sectors is undefined and may result in unpredictable behaviour. Bits 5 to 7 specify the sector size as 128*2^size, as follows: b7 b6 b5 Sector size 0 0 0 128 bytes 0 0 1 256 bytes 0 1 0 512 bytes 0 1 1 1024 bytes 1 0 0 2048 bytes 1 0 1 4096 bytes 1 1 0 8192 bytes 1 1 1 16384 bytes Results ======= The result is returned to the byte after the last parameter. The location is addressed by XY?(7+XY?5). For command &6C this location contains the drive status; for command &7D it is the requested special register; and for command &7A the result is undefined. Values returned by the other commands are as made up as follows: * b7-b6: always zero (1770 DFS returns 11 if command unrecognised) * b5: deleted data found * b4-b3: completion type: 00=no error, 01=recoverable error, 10=unrecoverable error, 11=failure * b2-b1: completion code * b0: always zero This gives the following result values: type code Result Meaning ------------------------------------------------------- 00 00 &00 Successful completion 00 01 &02 Success, scan met equal ** 00 10 &04 Success, scan met not equal ** 00 11 &06 unused 01 00 &08 Clock error 01 01 &0A Late DMA ** 01 10 &0C ID CRC error 01 11 &0E Data CRC error 10 00 &10 Drive not ready 10 01 &12 Disk write protected 10 10 &14 Track 0 not found 10 11 &16 Write error 11 00 &18 Sector not found 11 01 &1A unused 11 10 &1C unused 11 11 &1E unused (HADFS Drive not present) &FE 8271 command unknown. **Not possible on a BBC as needs DMA hardware. The result byte will have &20 added to it if deleted data has been read. Intel documentation states that result type 01 should be retried up to a total of ten times before abandoning. In practice: * results types 01 and 10 (other than &10 - Drive not ready, and &12 - Disk write protected) should be retried up to ten times * result &10 should be retried indefinitely until some other result occurs * result &18 - Sector not found - could be followed by a seek to track zero then one additional attempt. The result byte can be preloaded with a value to return if no OSWORD &7F routine exists. For instance, preloading the result with &00 makes all such failed calls appear to succeed, preloading with &18 makes all calls appear to return 'Sector not found'. HADFS preloads the result byte with &1E to give a default result of 'Drive not present'. ==Coding== The following routine can be used to perform an OSWORD &7F call that takes three parameters, such as Write (&4B) and Read (&53). It requires X%=>15-byte control block, Y%=X%DIV256. DEFFNdisk(addr%,cmd%,drv%,trk%,sec%,num%,den%):LOCAL fs% fs%=FNfs:IF fs%<>4:*FX143,18,4 REPEAT X%?0=drv%+den%*24+32:X%!1=addr%:X%?5=3 X%?6=cmd%:X%?7=trk%:X%?8=sec%:X%?9=num%OR&20 A%=127:CALL&FFF1:A%=X%?10 UNTIL A%<>&10:IF fs%<>4:OSCLI"FX143,18,"+STR$ fs% =A% DEFFNfs:LOCAL A%,E%,Y%:=(USR&FFDA)AND&FF 8271 Commands ============= The 8271 command passed in the control block is actually a bitmap made up as follows: +---+---+---+---+---+---+---+---+ | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | +---+---+---+---+---+---+---+---+ | | | | | | | | | | +---+---+ | +---+----Size: 00 multiple scan data | | | | | 01 no transfer | | | | | 10 128 bytes | | | | | 11 multiple sectors | | | | | | | | | +------------Data: 0 ignore delete data | | | | 1 all data | | | | | | | +-----------Direction: 0 Write to FDC | | | 1 Read from FDC | | | | | +-----------------Command: 000 Scan | | 001 Read | | 010 Write | | 011 Verify | | 100 Format | | 101 Seek | | 110 Initialise | | 111 Special Registers | | | +---------------------------------- Drive +-------------------------------------- Side DFS copies the drive and side bits from the drive number passed in XY?0. Bit 3 is used to select the appropriate NMI and Tube code to transfer to or from the floppy disk controller. Obviously, some combinations result in commands that are not sensible or are ineffective. For instance, it makes no sense to combine "Read" with "no transfer". Implementation ============== Some DFSs, such as DFS 2.45 supplied in the Master MOS 3.50 ROM, only respond to OSWORD &7F if DFS is the current filing system and fail silently if any other filing system is selected. Acorn DFS --------- This is the original implementation of OSWORD &7F. It is a fairly simple interface to the Intel 8271 floppy disc controller; it passes the command and parameters to the controller, supplies the appropriate NMI service routine to fetch or store the disc data, and returns the result. Acorn 1770 DFS -------------- This emulates key commands of the 8271. Software double-stepping is available. Double density access can be made by setting bit 3 of the drive number. Unfortunately, the programmers didn't realise that the double density bit was moved on the BBC Master, so double density access is not possible without a patched filing system (http://mdfs.net/ROMs/Filing/Disk). Watford DDFS ------------ Density selectable with b4-b5 of the drive number. Opus EDOS --------- This emulates key commands of the 8271, and operates on each drive in the density that was detected at the last *CAT (single or double). Software double-stepping is enabled if *OPT 8,255 is entered and *CAT detects a 40 track disc. The Format Track command formats 256-byte sectors only in single density, or double density if 16 or more sectors are specified. The density of operation cannot be directly specified to other commands. The sector size parameter is ignored in favour of the sectors' N records.