8 HADFS technical

information

General

Sectors 0-1 usually contain a DFS catalogue with a DFS !Boot file embedded in the catalogue. Sector 70 contains the disk name and free space map. Sector 71-73 contains the root ($) directory. All names are padded with spaces.

Sector 0-1

Sectors 0 and 1 usually contain a DFS catalogue with a boot file to select HADFS. The first six bytes of sector zero usually contain "HADFS",&00.

0 1 2 3 4 5 6 7 8 9 A B C D E F +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | H A D F S |&00| | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

10 11 12 13 14 15 16 17 +---+---+---+---+---+---+---+---+ |Flg| Disk Structure Record | +---+---+---+---+---+---+---+---+

If Flg=&0D then &11 to &17 contain a disk structure record that describes the shape of the disk. The rest of sector 0 and 1 usually contain 6502 code to load the HADFS ROM from the disk. On a disk with multiple paritions, sectors 0 and 1 will hold information about the non-HADFS partition.

Sector 70

0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | Disk name | &00,(C)JGH,&00 | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

18 19 1A 1B 1C 1D 1E 1F HADFS disks are identified +--+--+--+--+--+--+--+--+ by this string |DskID|Date |MaxSec|Flag| +--+--+--+--+--+--+--+--+

&18-&19: DskID Disk id - created pseudo-randomly when a new disk is created &1A-&1B: Date Date of creation: &1A b7-b3: day &1A b2-b0: (year-1981)DIV16 &1B b7-b4: (year-1981)MOD15 &1B b3-b0: month &1C-&1E: MaxSec Maximum number of sectors. (Last sector number) + 1.

&1E-&1F: Flag b15=0 Small Disks - 16bit Free Space Map b14: Don't overwrite disk with *INSTALL b13: Mount this drive as URD b12: Mount this drive as LIB b11: Mount this drive as CSD b10-b9: unused b8: Don't modify sectors 0 and 1 b7-b3: unused b2: Partitioned disk b1: Split disk, eg 40*2 b0: Data disk

b15=1 Large Disks - 24bit Free Space Map b14: Don't overwrite disk with *INSTALL b13: Mount this drive as URD b12: Mount this drive as LIB b11: Mount this drive as CSD b10-b9: unused b8: Don't modify sectors 0 and 1 b7-b0: MaxSec b16-b23

Small Disk Free Space Map: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... F7 F8 F9 FA FB FC FD FE FF +--+--+--+--+--+--+--+--+--+--+--+--+- - - - -+--+--+--+--+--+--+--+--+ |Start| Len |Start| Len |Start| Len | |00 00|00| Reserved | +--+--+--+--+--+--+--+--+--+--+--+--+- - - - -+--+--+--+--+--+--+--+--+

Large Disk Free Space Map: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... F7 F8 F9 FA FB FC FD FE FF +--+--+--+--+--+--+--+--+--+--+--+--+- - - - -+--+--+--+--+--+--+--+--+ | Start | Length | Start | Length | |00 00 00| Reserved | +--+--+--+--+--+--+--+--+--+--+--+--+- - - - -+--+--+--+--+--+--+--+--+

The free space map is terminated by a Start=0. The last entry ends at &F7. With a full free space map, &F8/&F9/&FA contains a zero terminator.

Directories

There are two types of directory. Large disks always use Big Directories. Small Disks default to Small Directories, but can use Big Directories. Small Directories are 32 x 24-byte entries, Big Directories are 24 x 32-byte entries.

Small Directory layout: &000 Dir. header &0C0 Entry 8 &180 Entry 16 &240 Entry 24 &018 Entry 1 &0D8 Entry 9 &198 Entry 17 &258 Entry 25 &030 Entry 2 &0F0 Entry 10 &1B0 Entry 18 &270 Entry 26 &048 Entry 3 &108 Entry 11 &1C8 Entry 19 &288 Entry 27 &060 Entry 4 &120 Entry 12 &1E0 Entry 20 &2A0 Entry 28 &078 Entry 5 &138 Entry 13 &1F8 Entry 21 &2B8 Entry 29 &090 Entry 6 &150 Entry 14 &210 Entry 22 &2D0 Entry 30 &0A8 Entry 7 &168 Entry 15 &228 Entry 23 &2E8 Entry 31

Large Directory layout: &000 Dir. header &0C0 Entry 6 &180 Entry 12 &240 Entry 18 &020 Entry 1 &0E0 Entry 7 &1A0 Entry 13 &260 Entry 19 &040 Entry 2 &100 Entry 8 &1C0 Entry 14 &280 Entry 20 &060 Entry 3 &120 Entry 9 &1E0 Entry 15 &2A0 Entry 21 &080 Entry 4 &140 Entry 10 &200 Entry 16 &2C0 Entry 22 &0A0 Entry 5 &160 Entry 11 &220 Entry 17 &2E0 Entry 23

Directory header Small Directories: 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | Directory name |Parnt|NN|CC|Link |DskID|BB|UU|First| Aux | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Large Directories: 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | Directory name |xx xx|NN|CC| Aux |DskID|BB|UU| First |00| +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

18 19 1A 1B 1C 1D 1E 1F +--+--+--+--+--+--+--+--+ | Link |00| Parent |00| +--+--+--+--+--+--+--+--+

SmallDir LargeDir &0A-&0B &1C-&1E Parent: parent directory sector address &0C &0C NN: b0-b4: number of entries b5: reserved b6: long object names present. If long object names are present, the load and exec address fields are used to hold characters 11 to 16 of the object name and bytes &10 and &11 hold the filetype. b7: 0=small directories, 1=large directories &0D &0D CC: cycle number &0E-&0F &18-&1A Link: sector of next directory chunk, or zero &10-&11 &10-&11 DskID: disk ID &12 &12 BB: b0-b1: boot option b2-b3: reserved b4-b7: b8-b11 of user number &13 &13 UU: b0-b7 of user number &14-&15 &14-&16 First: sector of first directory chunk, or zero &16 &0E Aux: b0-b3: reserved b4-b7: b8-b11 of auxilary user number &17 &0F Aux: b0-b7 of auxilary user number

Directory entries Small directories: 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | Object name and attributes | Load Addr | Exec Addr | Len |Date |Sectr| +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Large directories: 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | Object name and attributes | Load Addr | Exec Addr | Length | Sector | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

19 1A 1B 1C 1D 1E 1F +--+--+--+--+--+--+--+ |00|MDate|MTime|CDate| +--+--+--+--+--+--+--+

&00 contains &00 if the entry is deleted. &00-&07 contain the attributes in bits 7: RWELRWEP &08 b7: 'D' attribute - entry is a directory

In small directories: &09 b7: (year-1981) bit 4 &0D b7-b6: (year-1981) b6-b5 b5: b7-b5 of Load address &14 b2-b0: b18-b16 of length b7-b3: day of object modification date &15 b3-b0: month of object modification date b7-b4: b3-b0 of (year-1981) of object modification date

In large directories: &19 unused, &00 &1A b2-b0: b7-b4 of (year-1981) of object modification date b7-b3: day of object modification date &1B b3-b0: month of object modification date b7-b4: b3-b0 of (year-1981) of object modification date &1C b4-b0: seconds/2 of object modification time b7-b5: b2-b0 of minutes of object modification time &1D b2-b0: b5-b3 of minutes of object modification time b7-b3: hours of object modification time &1E b2-b0: b6-b4 of (year-1981) of object creation date b7-b3: day of object creation date &1F b3-b0: month of object creation date b7-b4: b3-b0 of (year-1981) of object creation date

All the sector entries in Big Directories are three bytes followed by a zero byte, to leave room for future extension of sector numbers to four bytes.

Extended Directories

To be able to store more than 31 or 23 entries in a directory, a directory can be extended by stringing together two or more directory chunks, where a directory chunk is three sectors containing directory information. The parent directory's entry for the directory points to the sector of the first chunk. The directory chunks' Link field points to the sector of the next chunk, the last chunk's Link field being zero. Each chunk's First field points to the sector of the first chunk, the first chunk's First field being zero.

Parent directory: +-----------+-----+-----------+-----+---------+-----+-----------+-----+-- |Object name| |Object name| |DirName | |Object name| | +-----------+-----+-----------+-----+---------+-----+-----------+-----+-- | +-----------------------<-+------------<-+ | | v | +---------+-----+-----+ | |DirName |Link |zero | | +---------+-----+-----+ | | | +---------<-+ | | | v | +---------+-----+-----+ | |DirName |Link |First| | +---------+-----+-----+ | | | | +---------<-+ +->-----+ | | v | +---------+-----+-----+ | |DirName |zero |First| | +---------+-----+-----+ | | | +->-----+

If the directory's parent directory entry is also in an extended directory, the Parent field should point to the parent directory's first chunk, pointed to by the parent directory's First field.

Sector Addresses

HADFS uses 256-byte sectors. Sectors are addressed by a four-byte value made up as &ddssssss where dd is the drive number and ssssss is the sector on that drive. All HADFS functions use four-byte sector addresses. Small disks use 16-bit sector addresses, &000000 to &00FFFF, allowing a maximum disk size of 16M. Large Disks use 24-bit sector addresses, &000000 to &FFFFFF, allowing a maximum disk size of 4G.

Mapping to physical disk sectors

Floppy disks are addressed H:C:S, that is, the sectors count upwards on one side of the disk, then upwards on the other side. This is called sequential addressing. On a DFS formatted disk (10 sectors/track), the second side always starts at sector 800. If you format a disk with fewer than 80 tracks, then there will be a gap just before sector 800, which must be reflected by a gap in the free space map, and the Split Disk flag must be set in the disk flags.

External drives

Valid drive numbers are 0-9, A-V, giving 31 drives. Current allocation is: Drive 0 First floppy drive 1 Second floppy drive 2 Third floppy drive 3 Fourth floppy drive 4 First partition on first IDE hard disk drive 5 First partition on second IDE hard disk drive 6 Second partition on first IDE hard disk drive 7 Second partition on second IDE hard disk drive 8 Third partition on first IDE hard disk drive 9 Third partition on second IDE hard disk drive A Fourth partition on first IDE hard disk drive B Fourth partition on second IDE hard disk drive C-G unallocated I Internal ROM files J-L unallocated M GoMMC RAM disk N-Q unallocated R RAM disk S-V unallocated

Drives 0 and 1 are the two floppy drives that are accessed as drives 0/2 and 1/3 in DFS. Accessing drives numbered above 1 causes an OSWORD call for extra software to provide access to other drives. If there is no driving software for drives 2 onwards, then the error Drive x not present is given if an attempt to access it is made. The OSWORD call for the extra drives is:

A=90 (&5A) XY+0: 0 Check for these values XY+1: 6 in these two locations. XY+2: \ XY+3: \ Address XY+4: / XY+5: / XY+6: \ \ XY+7: } Start sector \ Four-byte XY+8: / / sector address XY+9: Drive number / XY+10: Number of sectors XY+11: Call type and return code

Call types: 1 write sectors 2 read sectors 3 request drive info 4 format 5 park heads (do not claim) &80 user read sectors &81 user write sectors

To provide access to extra drives, you must intercept the OSWORD routine and check for OSWORD 90. You must only claim the call if the first two bytes are &00,&06 and the drive number is the drive you are supporting, and the call type is less than 128. Calls 128 and above are translated by HADFS into either an OSWORD &7F call or another OSWORD 90 call.

Calls 1 and 2 read and write the supplied number of sectors using the address in memory and the sector start. HADFS usually reads and writes a between 8 and 64 sectors at a time, but you should be able to cope with the full range.

Call 3 should return the total number of sectors on the drive in XY+6 to XY+8 (&000000 meaning &1000000). If the number of sectors in XY+10 is not zero, the call should do a sector read, as call 2.

Call 4 reserved for formatting disks.

Call 5 is issued when a *BYE comand is used. This should not be claimed, as it should be passed on to other driving routines.

Calls &80 and &81 are translated by HADFS into the required calls to read either the floppy drives by calling OSWORD &7F or an external drive by calling OSWORD 90. They should not be claimed or recognised in any way by the driving routines.

A return code of 0 indicates that all is well and the operation was provided. A return code of 1 to 5 (ie unchanged from the call type) indicates that the drive is not present. Return codes of 6 and above are used as disk error numbers. These are: &06 Bad block (IDE error &80) &08 Clock error &0A Late DMA &0C CRC error in ID (IDE error &01) &0E Data CRC error (IDE error &40) &10 reserved &12 Drive read only &14 Track zero not found (IDE error &02) &16 Write error &18 Sector not found (IDE error &10) &1A Media change request (IDE error &08) &1C Abort (IDE error &04) &FE Disk/drive not present (IDE error &20)

Calls &80 and &81 translate an unchanged return code into: &FE Drive not present

Error &10, Drive not ready, should never be returned. The routine should retry until the drive is ready, or another error is returned. Other return codes are reported as Disk error XX.

Selection of screen memory is taken care of by the HADFS code, and so the only I/O address supplied will be &FFFFxxxx. Addresses in the language processor should be taken care of by the driving routine using the Tube communication routines installed by the Tube code at &406. If there is no Tube present, then the supplied addresses will always be in the I/O processor, ie &FFFFxxxx.

Keyboard links

When using EDOS on the BBC B and B+, the OSWORD &7F disk access routine only responds if EDOS is the currently selected filing system. If keyboard link 2 is make, then EDOS always responds to the OSWORD &7F call, so allowing HADFS to access floppy drives.

Acorn DFS 0.90 has a bug in that is responds to all OSWORD calls numbered &80 and higher. This means that when HADFS looks for a default drive after *MOUNT or Shift-Break, when it tests the GoMMC drive DFS corrupts the HADFS workspace. To avoid this, if DFS 0.90 is present HADFS disables the GoMMC driver.

Due to the way of testing for DFS 0.90 the GoMMC driver is also disabled on a BBC B if DFS is actually completely absent. To enable the GoMMC driver on a BBC B which has no DFS present set keyboard link 2.

*OPT6 and *OPT7

The first time an access to drives 0 to 7 is made, it is made through OSWORD 90. If this is claimed, then all further accesses to that drive are made through OSWORD 90 until the next *HADFS, *MOUNT, *I AM or *BYE. Otherwise, accesses to drive 0 to 7 are made with internal drivers. Drives 0 and 1 access the floppy drive through OSWORD &7F. To force accesses to drives 0 to 7 to use external drivers via OSWORD 90, *OPT7,<drive> can be used. To make drive access return to using internal drivers use *OPT6,<drive>. *OPT0 resets all the *OPT6 and *OPT7 settings.

Master CMOS configuration

On the Master series, (or the BBC B or B+ with suitable expansion) the *OPT6/7 setting is saved in HADFS's CMOS byte at ROMnumber+30. The *OPT6/7,0 setting is store in bit 7 and the *OPT6/7,7 setting in bit 0. The current setting can be shown with *STATUS HADFS. When running on a BBC B, HADFS provides a *STATUS command to display the settings set by *OPT6 and *OPT7. It also shows the current date setting.

HADFS prior to v5.65 only stores the *OPT6/7,1 setting in bit 6.

Changing default drives

After a *MOUNT with no parameter, or after startup, HADFS needs to decide what drive to use. It does this by examining each disk present and then calling three OSBYTE calls to see if there is some software that wants to change the default drive. Normally, HADFS defaults to drive 0 if not told what drive to use explicitly.

The OSBYTE calls are: A=90, X=6, Y=64 Look for default drive A=90, X=6, Y=65 Look for default library drive A=90, X=6, Y=66 Look for default user drive

When there is a file access after a *MOUNT or a startup, HADFS checks the disk flags on each drive from 31 down to 2. Then, OSBYTE 90,6,64 is called to see if there is a default drive to set the CSD to. If there is, the URD and CSD are set to this. OSBYTE 90,6,65 is then called to see if there is a default drive for the Library directory. If there is, then the directory $.Library is looked for on that drive. If there isn't, then the LIB drive is set to the CSD drive (which may have been set by OSBYTE 90,6,64), and $.Library looked for there.

If the OSBYTE call is not claimed, then the MOS sets the X register to &FF. If some software claims the OSBYTE call and sets the X register to a drive number, this will be in the range &00 to &1F for drive :0 to :V. HADFS checks bit 7 of the returned X to see if the OSBYTE call has returned a drive number.

This means that lower numbered drives have mount priority over higher number drives, and software responding to OSBYTE 90 has priority over any disks present.

The program MkIntern demonstates various OSBYTE call claiming when creating a drive in sideways RAM. It also shows how to call the Tube code for communicating with a second processor.

HADFS memory use

HADFS uses the following pages of memory: BBC Master &0E00 &0E00 HADFS information &0F00 &0F00 Channel 25 buffer/FSM buffer/used for last few bytes of LOAD &C000 Channel 25 buffer &1000 &C100 Channel 26 buffer/BBC DFS workspace &C200 Master DFS workspace &1100 &C300 \ &1200 &C400 } Current directory &1300 &C500 / &1400 &C600 Channel 27 buffer &1500 &C700 Channel 28 buffer &1600 &C800 Channel 29 buffer private w/s: HADFS information when HADFS not selected.

On the BBC channel 25 is always used for input, as its buffer is also used for other purposes, and keeping channel 25 input-only means that HADFS doesn't have to keep saving the buffer to disk. If DFS is absent on a BBC, then channel 26 becomes available.

The lowest value that PAGE can be moved to on a BBC is: &1700 Loads/Saves/up to 4 channels open &1600 Loads/Saves/up to 3 channels open &1500 Loads/Saves/up to 2 channels open &1400 Loads/Saves/only 1 read-only channel open &1000 Loads/Saves/only 1 read-only channel open - but loading to &1000 will overwrite directory buffer, and reading a directory will overwrite memory at &1000 &0E00 No access available - one load to &E00 can occur, but then workspace will be overwritten and no further access is available

Break and Reset

Most of HADFS's information is preserved over a Break or Ctrl-Break. All channels remain open and the CSD, URD and LIB remain selected. On a Ctrl-Break, any open channels are abandoned. On a Shift-Break, a *I AM
BOOT
command is issued, which abandons any open channels, mounts the default user drive and starts any auto-start sequence.