Some notes on MiscOp
====================

Documentation in this area has previously left a lot to be desired, so after
an extended period of software archaeology, I have written up my findings.
Be aware that since this is the result of reverse engineering, it is
possible that I have missed some subtleties of the way the stack hangs
together, but in the absence of the original authors, it will have to do.


Miscellaneous
-------------

Despite what the PRM says, all MiscOp SWIs (except MiscOp 6) corrupt R1 on
exit. While techincally a FileCore bug, this is so long-standing that the
correct approach is probably to document it as such. Low-level MiscOp
handlers, however, remain required to preserve R1.

If you are calling a MiscOp 4 SWI, you must provide a valid drive number in
R1 (a pointer to a disc name, as stated in the PRM, will not be accepted). If
you are implementing the low-level routine for MiscOp4, then you cannot rely
upon the value of R1 because it depends upon how it was triggered - it may be
a drive number, or it may be a corrupt value.

In addition to the special value -1 that may be returned in R5 from MiscOp 4
(to specify an indefinite timeout), the special value 0 may be returned to
indicate that the filing system does not support swapping discs at all. (This
is used, for example, by RAMFS.) In this case, R6 is unused.

The low-level MiscOp 5 routine should also accept a special value in R1 of
&80000000, which it should interpret as the "preferred drive". This is the
drive which will be ejected if the system requires a disc which is not
already in one of the drives. In this case, R4 and R5 have meanings as in
OS_UpCall 1 and 2, which may be utilised by a heuristic in the driver to
avoid ejecting too frequently. This type of MiscOp 5 behaviour cannot be
triggered using the MiscOp SWI interface.

Flag bit 0 of MiscOp 7 has nothing to do with the lock status set by
MiscOp 2 and MiscOp 3. Instead, it complements SWI ADFS_LockIDE (and
equivalents for any other filing systems - not that any others have been
defined to date).

RISC OS 5 added a new flag, bit 1, to MiscOp 7, to indicate that the drive
should be hidden by the icon bar filer. This complements UpCall_DriveAdded
and UpCall_DriveRemoved, because it allows the state of the drives to be
enumerated if the filer starts after the filing system.

Not MiscOp-related, but I wanted to note it anyway: the Ursula FileCore spec
doesn't state a maximum value for idlen. There is a limit, of 21 bits,
enforced by the format of internal disc addresses. The maximum map size
possible with idlen=21 is (21+1)*2^21 bits, or 5.5 MiB. Supporting more than
8 drives will mandate moving the drive bits out of internal disc addresses.
This would also facilitate increasing idlen to 24 bits, which would enable
maps of up to (24+1)*2^24 bits, or 50 MiB, although this would currently
mean allocating significantly more logical address space to the map dynamic
areas.

Note that the limit is 21 because internal disc addresses (used to address
the root directory from the disc record, and in the directory structure)
allocate 3 bits to the drive number and 8 bits to the sharing offset. Unlike
the FreeLink in the map block header, the fragment id is able to use all
available bits. Non-long-filename directories only allocate 3 bytes to the
internal disc address, though they don't need to specify a drive number, so
the limit for such discs is 16.

Amazingly, although the PRM mentions briefly (in a table) that it keeps
two copies of new maps, it doesn't say where. The second copy is stored at
the very next sector after the end of the first copy. The second copy is of
exactly the same format as the first, so for example it includes another
copy of the disc record.

We can deduce why the offset &C00 was chosen for the boot block. It derives
from the way maps and root directories are laid out, and assumes that the
sector size for hard discs (which are the only discs that need a boot block
even if the disc is a single-zone disc) is 512 bytes. When long filenames
were introduced in RISC OS 4, the fact the root directory is now placed in
its own disc object allows us the flexibility to move it out of the way of
the boot block, but the map still restricts the sector size to 1 KB for
single-zone hard discs.

The details: old map discs put the map (fixed at 512 bytes) at address 0,
then padding to the next sector boundary, then the root directory (1280
bytes for L-format, 2048 bytes for D-format). New map discs with more than
one zone don't use the start of the disc, but if they have one zone, then
the disc starts with two copies of the map, each of which is one sector
long, by definition, for a one-zone disc, or 1K total. This was always
immediately followed by the 2K root directory, at least before long
filenames. This left the 3K address (&C00) as the first available address
for the boot block. Even if you move the root dorectory out of the way,
the largest each map block (and therefore sector) can be is 1K, otherwise
the second copy overlaps the boot block. Even if we adapt FileCore to allow
the copies to be separated, we can't go above 2K map blocks / sectors, or
else even the first map block overlaps the boot block.

Perhaps the simplest way to address this is to change formatting tools so
that an upper limit is placed on the LFAU (via the log2bpmb field in the
disc record) to ensure that, aside from drives that support "floppy-style"
mounting (identifiable from the drive number and the descriptor flag bits
available from FileCore_MiscOp 6) that if the disc has a sector size of
2K or more (1K or more if long filenames are not used), that the disc can
only be allocated 2 or more zones.

There remains a sector size limit imposed by the FreeLink fragment in the
map block header. Because this is in the form of a fragment block (albeit
often shorter than the remaining fragment blocks in the map block), one of
the bits is used as a terminator. The remaining 15 bits must be able to
represent any number up to the number of allocation bits in a map block.
This limits map blocks, and therefore sectors, to 32768/8 = 4K.

A similar issue is raised by the zone_spare field in the disc record. This
is a 16-bit field, so to retain the ability to mark any amount of the map
block as spare would impose an 8K limit on sector sizes (however, it is
rare in practice for zone_spare to reserve much more than 32 non-allocation
bits between map blocks, so this is unlikely to be a problem in practice).


Re-entrancy
-----------

The PRM says nothing about re-entrancy requirements for low-level MiscOps.
By contrast, DiscOps already have implied re-entrancy depending upon
whether the operation is partially or wholly in the foreground (not
re-entrant), or whether it's wholly in the background (re-entrant). This can
be important for some filing systems, so here are the requirements imposed
by FileCore on MiscOps.

MiscOp 0 (Mount), MiscOp 4 (Poll period) and MiscOp 5 (Eject) are not
called re-entrantly by FileCore (so callers of FileCore_MiscOp must assume
they are not re-entrant).

MiscOp 1 (Poll changed), MiscOp 2 (Lock drive) and MiscOp 3 (Unlock drive)
are called re-entrantly by FileCore, at least for filing systems that
support buffering.

MiscOp 6 is not called at the low level entry.

MiscOp 7 (Drive status) is already documented as being re-entrant.


Boot blocks
-----------

The use of boot blocks is intimately connected with MiscOp 0, so it is
worth some discussion.

The PRM neglects to mention some features of the hardware-dependent
information section of the boot block:

* FileCore assumes that *all* FileCore filing systems use offset &1BC-&1BF
  to hold the parking disc address. It seeks to this address when any disc
  with a boot block is dismounted. The word is required to have bits 29-31
  clear. If the disc is less than 2^29 bytes in size, then it is interpreted
  as a byte address, otherwise it is interpreted as a sector address. This
  will obviously break when we support discs of 2^29 or more sectors, and
  it makes little sense, when partitions are supported, for each partition
  to have its own parking address. In either of these cases, I suggest we
  drop the configurability and have FileCore seek to the last sector on the
  physical disc instead - after all, HForm always defaults to using the
  final cylinder, and I doubt many users change this from the default.

* ADFS uses offsets &1BA and &1BB as flags. If &1BA is non-zero, then ADFS
  uses LBA addressing in its ATA commands rather than CHS addressing. If
  bit 0 of &1BB is set, then ADFS issues ATA command "INITIALIZE DEVICE
  PARAMETERS" on the first ATA command following drive mounting. This
  command was part of the ATA command set before ATA-6, and sets the
  mapping between CHS and LBA addressing; it is only needed if the drive's
  controller has to be configured to convert between the addressing mode
  used on the ATA bus and the one it uses internally. Since modern hard
  discs no longer use fixed numbers of sectors per track across the whole
  disc, the CHS scheme is obsolete, explaining why the command was withdrawn
  in ATA-6. It is undefined what will happen for new drives what will happen
  if they receive the command, so it is probably best not to set the flag
  for them. Current versions of ADFS read these flags during its MiscOp 0
  handler, which it assumes is loading the boot block. Clearly, this is
  predicated upon there being a FileCore partition at the physical start of
  the disc, and will need some work to support alternative partitioning
  schemes.

It is worth discussing partition schemes, since this is a regular feature
request, and would impact upon boot blocks and the disc mounting process.

The boot block has two distinct functions - describing the physical disc
shape (sector size, heads, cylinders, LBA flag etc), and describing the
logical structure of the disc (location of the map, root directory etc).
The distinction between these becomes more important when we consider
partitioning.

There are three obvious partitioning schemes worth considering: FileCore
partitioning (originally developed to support RISC iX partitions), MBR
(originating with DOS, and still in widespread use) and GPT (defined by
the EFI standard, and used by many Windows, Mac OS X and Linux operating
systems since approximately 2007).

FileCore partitioning
Pros:
* first partition on a disc is fully compatible with old FileCore
* unlimited number of FileCore-formatted partitions
* fully compatible with CHS addressed drives
Cons:
* not supported by any other operating systems (except RISC iX)
* only the last partition can be non-FileCore format
* partitions can only start and end on cylinder boundaries
* partition size is limited to 65535 cylinders = approx 502 GiB
  assuming 512-byte sectors, 63 (max) sectors/track, 255 (max) heads

MBR partitioning
Pros:
* can be overlaid on the first track of a FileCore partition, leaving the
  boot block at &C00, so the first partition is compatible with old FileCore
  (except for old-map or single-zone new-map discs, where the MBR partition
  table clashes with the FileCore free space map)
* compatible with most other operating systems
* partitions can start and end at any sector
Cons:
* limited to 4 partitions
* partition size is limited to 2 TiB

GPT partitioning
Pros:
* supports 128 partitions
* supports partitions up to 8 ZiB (9.4 x 10^21 bytes), although in practice
  the FileCore disc size limit of 16 EiB (16 million terabytes, or
  1.8 x 10^19 bytes) would apply first
* partitions can start and end at any sector
Cons:
* incompatible with old FileCore (cannot place boot block at &C00)
* incompatible with 32-bit Windows, and any version of Windows, Mac OS X
  or Linux prior to approx 2007
* cannot support CHS addressed drives (because you can't fit partition
  table and boot block into first track)


MiscOp 0
--------

This entry is called, and must be handled, in two very distinct ways,
depending on whether the drive uses floppy or fixed disc style mounting:

Drive   FileCore_Create descriptor block flags   Mount style
        bit 4             bit 11
0-3     don't care        0                      Floppy
0-3     don't care        1                      Fixed
4-7     0                 don't care             Fixed
4-7     1                 don't care             Floppy

Floppy-style mounting

The only parameter you can rely on in the disc record referenced by R5 on
entry is density. This is preserved from the previous mount on this drive,
so is a good first choice when trying to read the disc geometry.

You must at least partially update the disc record on exit. This disc
record is what gets passed around modules via Service_IdentifyDisc, so
the minimum set of parameters that must be correct is:
  log2secsize
  secspertrack
  heads
  density
  lowsector

These values should, by preference, be determined by probing the hardware.
For example, the ADFS floppy drivers determine them by reading a track's
worth of sector IDs (which are held between the sectors on the physical
disc).

Ideally you should *not* read these from the disc's boot block, if it has
one (which it may not, for non-FileCore or single-zone discs), so that
manipulation of boot blocks is kept within FileCore. If you can't read the
physical disc parameters, you should be using hard disc style mounting
instead. For some reason, this option has never existed before now, but
I have just added it to FileCore, signalled by bit 11 of the descriptor
block flags. Bit 1 returned by FileCore_Features indicates that this
facility is available, if you want to ensure that this request will be
honoured.

Note the PRM is wrong in the description of FileCore_MiscOp 0: you do not
need to set up the root directory parameter in the disc record. FileCore
does this itself - during identification of new map discs, it is read from
the disc record in the boot block or the map. After identification, FileCore
zeros it (for non-FileCore discs), sets it to a known value depending on the
disc geometry (for old map FileCore discs) or updates it from the map copy
of the disc record (for new map FileCore discs).

The ADFS floppy driver does set root, and also (not even required by the
PRM) disc_size and disc_size_2. These are not needed either - during
Service_IdentifyDisc, FileCore derives the disc size from the old map, or
reads it from the disc record in the boot block or map, for new-map discs.
This is just as well, because the values (for both root and disc_size) set
up by ADFS are actually only correct for old map discs. This appears to be a
legacy from RISC OS 2, where the PRM stated that both were required, but
only for old map discs.

It is worth documenting the filetypes that FileCore uses in
Service_IdentifyDisc. They are:
  &FCE = FileType_FileCoreFloppyDisc - disc image without a boot block
  &FCD = FileType_FileCoreHardDisc   - disc image with a boot block

This means that, unless you're using a non-standard format, a quad-density
(1.6 MB, F or F+ format) floppy disc is assigned the hard disc filetype,
because it has two zones and hence needs a boot block.

FileCore will only attempt to identify a disc as a FileCore image without
a boot block if it comes from drives 0-3. This made sense historically
because in the absence of a boot block, the disc geometry can only be
determined from a floppy-style mount, and the geometry is an important
input to the identification process. This might be worth revisiting in
light of the fact that FileCore permits any drive can be mounted either way,
and that when more than 8 drives are supported, there is no longer a way for
the identification code to determine which drive the disc is in.

In addition to reading the physical geometry, a floppy-style low-level
MiscOp 0 handler must also be prepared to read a block of data, as
specified in R2-R4, unless R4 is zero. This should be treated somewhat like
a DiscOp 1 call with Escape conditions ignored, but with the following
notes:

* The caller does not know the sector size on entry, so the disc address is
  measured in bytes, even for filing systems which otherwise work in
  sector-based disc addresses.

* For compatibility with hard disc style mounting, where the filing system
  does not yet have the disc record it would need to calculate CHS addresses
  for the operation, the transfer must be from the first track of the disc
  (within the first track, the CHS and LBA addresses are identical).
  Surveying the disc formats in HForm suggests that a suitable limit to
  ensure this is 38 x 512-byte sectors, or 17K.

Currently FileCore never requests this, but a caller of SWI FileCore_MiscOp
0 might do so. However, it is highly likely that FileCore would start to
use this facility in the event that partition support was added, because
the partition table is just the sort of thing it would want to read from
the first 17K of a disc. Also note that any data block specified by the SWI
is already overridden by FileCore in hard disc mount case. Consequently,
specifying a data block to read via the SWI interface is deprecated.

Hard-disc style mounting

In this case, R5 still points at a disc record, but the filing system is
neither required nor expected to modify it. Once the filing system returns,
FileCore fills in the following fields in the disc record, prior to issuing
Service_IdentifyDisc:
  log2secsize
  secspertrack
  heads
  density
  lowsector
  disc_size
  disc_size_2

With the exception of the disc_size fields, these are the same fields used
in the floppy-style mount case - but as discussed above, clients of the
service call cannot rely upon the disc_size fields being set correctly.

What FileCore uses to fill in those fields in the disc record is the boot
block, which it requests from the filing system via R2-R4 on entry to
MiscOp 0. As discussed above, this is only suitable for reads within the
first 17K of a disc. Regrettably, some filing systems (most notably ADFS's
hard disc driver) has taken the statement in the PRMs that this block will
"typically" load the boot block as fact. What ADFS does is validate the
boot block, then cache the parking cylinder and LBA and drive init flags
from its hardware-dependent information section if it is valid, or return a
"Bad drive" error otherwise. This has several drawbacks:

* It prevents ADFS from supporting non-FileCore format hard discs.

* It doesn't make any sense for a partitioned disc, because the values
  ADFS caches are relative to the physical disc, not to any one partition.

* It is incompatible with some partitioning schemes (such as GPT) because
  the location of the boot block(s), if any, cannot be determined until
  the partition table has been read. To support partitioning, the first
  thing FileCore would have to look for would be the partition table, not
  the boot block.

To deal with this, I am defining here a scheme by which FileCore and the
filing system can resolve this dilemma.

The filing system sets bit 12 of the descriptor block flags. This indicates
that the filing system will only interpret the data read during MiscOp 0
as a boot block if it is read starting from disc address &C00, and that it
expects to be called back via MiscOp 8 once FileCore has read and validated
the partition table and the boot block for the first partition. The MiscOp 8
entry is described in more detail later.

In the event that a filing system so enabled is used with an older FileCore,
the MiscOp 0 entry will always be called to read from &C00 and so the
filing system can continue to post-process the boot block as it does at
present - indeed, if it needs the hardware-dependent parameters, it must do
so, because it will not be called with MiscOp 8.


MiscOp 1
--------

The PRM is very unhelpful when it comes to guidance on implementing
MiscOp 1. The one cryptic example it gives bears no resemblance to any
hardware drivers in any of Acorn's filing systems.

Those hardware drivers are:
* ADFS floppy discs on machines with a 1772 floppy disc controller
  (Archimedes-branded machines and the A3000)
* ADFS floppy discs on machines with a floppy disc controller from the 765-
  compatible family:
    82C710 (A5000)
    82C711 (A4, A3010, A3020, A4000)
    37C665 (Risc PC, A7000(+))
    M1535+ (Iyonix PC)
* ST506 hard disc interface (A440, A4x0/1)
* IDE hard disc interface (A5000, A4, A3020, A4000, Risc PC, A7000(+),
  Iyonix PC)
* SCSI (hard and floppy drives treated only subtly differently)
* RAM discs

The drivers that make the most complicated use of the MiscOp 1 interface, by
a long way, are the two ADFS floppy drivers.

The sequence number passed in and out of MiscOp 1 in R2 is primarily a tool
for the use of the filing system. FileCore will usually pass in the value
which it received back the last time it called the low-level entry in the
filing system. (There is a notable exception in that it does not update its
record of the last sequence number when calling MiscOp 1 from the
background, for obvious race condition reasons.) FileCore doesn't do
anything else with the sequence number.

It is also worth remembering that this interface can also be utilised by
external programs through the <filingsystem>_MiscOp SWIs, and they will each
have their own idea of what the most recent sequence number was.

The results flags fall into two categories. Contrary to what the PRM says,
FileCore doesn't actually care about any of bits 4-10 of the results flags
(with the sole exception that some versions of FileCore require that bit 3
"empty" is zero if bit 6 "empty works" is zero - but that was always true of
all Acorn's filing systems). Nevertheless, these bits are visible to
external callers of FileCore_MiscOp 1, so it should be documented what they
mean so that future filing systems can be consistent where possible.

Bit 5 "40 track" is not set by any drivers. Bits 9 "density sensing works"
and 8 "disc in drive is high density" are only set by the ADFS 765 floppy
driver, but their values are inaccurate and so cannot be relied upon.

Bit 10 "ready works" is only set by the ADFS 765 floppy driver and the SCSI
floppy driver. Bit 4 "ready", for the ADFS 765 floppy driver, means that the
drive is spun up and receiving index pulses, and is the currently selected
drive on the floppy cable. For SCSI floppies, bit 4 is simply the logical
inverse of bit 3 "empty".

Bits 6 "empty works" and 7 "changed works" are both always set on all
drivers except the two ADFS floppy drivers. For those, they vary depending
upon which floppy disc controller you have, which floppy drives are fitted,
and also at run time (in the case where a floppy disc is inserted when ADFS
initialises). The requirement in the PRM that once they are set, that they
remain so, is adhered to.

The reasons for this are to do with the way floppy discs are detected on
1772 and 765 machines.

With the 1772, a signal is asserted when the drive is empty, and remains so
until the driver pokes the controller to deassert it. If the drive is still
empty when the driver attempts the poke, then the line remains asserted.
Thus the driver can distinguish between empty drive and disc changed.

With the 765, a bit in a status register is set when a new disc is inserted
into the drive. An empty drive can only be detected by attempting to spin up
the drive, then waiting to see if you time out waiting for the index pulses
that would be generated by a rotating disc. This explains the fact that on
765 machines, repeated attempts to mount a drive when there is no disc
present will spin up the drive each time, when this was not the case on
earlier machines.

On top of this, both drivers attempt to cope with the fact that some floppy
disc drives do not generate disc present signals. There are code paths in
each whereby they signal "maybe changed" to FileCore. However, there is no
way for the drivers to tell which type of drive is fitted, so if a floppy
disc is inserted when ADFS initialises, then until the disc is ejected (1772
case) or a second disc is inserted (765 case), the drivers will operate in
"maybe changed" mode, even for drives that do support disc detection.

Correspondingly, the 1772 driver waits until the first time it detects a
disc removed, then sets bits 6 and 7 of the results flags. The 765 driver
always sets bit 6 (detecting an empty drive using index pulse timeouts
always works) but doesn't set bit 7 unless or until the controller reports
that a new disc has been inserted.

By contrast, bits 0-3 of the results flags - "not changed", "maybe changed",
"changed" and "empty" - are very important to FileCore's operation. The two
ADFS floppy drivers take different but equally valid approaches to the
relationship between these bits and the sequence number.

The 1772 driver, in "change doesn't work" mode, increments its internal copy
of the sequence number each time the motor is turned off. In "change works"
mode, it increments it whenever it polls the disc detect line, whether it is
diagnosed as drive empty or disc changed. Then in MiscOp 1, it constructs
the flags depending upon whether the caller's sequence number matches the
driver's one, along with whether the drive is empty and whether it has ever
been determined to be empty.

The 765 driver, by contrast, caches the caller's sequence number and doesn't
change it between MiscOp 1 calls. It records state changes using the flags
directly. The sequence number wouldn't be needed in this scenario, except
for the case where the caller can get out of sync, for example if an
external program is calling SWI FileCore_MiscOp. To cater for this, the
driver increments its sequence number before returning "changed" or "maybe
changed" to any caller. On entry to a subsequent MiscOp 1, the filing system
checks to see whether the caller's quoted sequence number matches what it
has cached, and if there is a mismatch then it means the caller has missed
at least one "changed" or "maybe changed" and this can be reported
immediately (and without incrementing the sequence number any further).

Note that the sequence number increments if you repeatedly poll an empty
drive with the 1772 driver, but not the 765 drive. This shouldn't really
matter because the sequence number should really be viewed as private data
of the driver. Perhaps more significantly, the 765 driver never reports
"empty" if the sequence number didn't match on entry, unlike the 1772
driver, which will do if the drive is indeed empty. Also, with the 1772
driver, if there haven't been any DiscOps since a MiscOp 1 reported "empty",
and then a disc is inserted, then the sequence number doesn't get
incremented so you get a "not changed" flag on the next MiscOp 1 without the
intervening "changed" that you would see from the 765 driver.

SCSIFS has a simple implementation to support removable media for floppies,
and hot-pluggability for both floppy and hard drives. However, it does not
modify its behaviour based upon the sequence number, merely basing its
"empty", "changed" or "not changed" responses upon state collected either
synchronous to the routine or since the last time it was called. This makes
it non-re-entrant and unsuitable for use by callers other than FileCore.
This needs to be fixed sometime, certainly if it is extended to support
background transfers.

ADFS hard disc drivers and RAMFS simply always set the "not changed" result
flag.


What FileCore does with MiscOp 1 results
----------------------------------------

FileCore maintains knowledge of 8 disc records as well as 8 drives, and
cross-references them. In addition, each drive can be in one of 6 states:

1) Unknown + Uncertain
2) Empty
3) Empty + Uncertain
4) Full + Uncertain (no disc record associated with drive)
5) Has-disc-record (disc record known good)
6) Has-disc-record + Uncertain (disc record needs confirming before use)

Each drive state transition can occur in the following circumstances,
respectively:

1) Module initialisation, *Dismount, *Bye, or disc and drive are unlinked
   (for example because the entry in the disc record array is reallocated).
2) Secondary filing system returns Empty from its MiscOp 1 routine.
3) We were in Empty state, and the secondary filing system returns
   MaybeChanged from its MiscOp 1 routine.
4) Secondary filing system returns Changed from its MiscOp 1 routine.
   Alternatively, we were in Empty or Empty + Uncertain state, and the
   secondary filing system returns NotChanged from its MiscOp 1 routine.
5) A disc record has been read from the drive (FileCore routines
   DetermineDiscType or MountDiscOnDrive).
6) We were in Has-disc-record state, and the filing system returns
   MaybeChanged from its MiscOp 1 routine. This can also happen following a
   disc format

The advantage of having a "Has-disc-record + Uncertain" state is that where
there is more than one removable drive on a filing system, FileCore can make
a good first guess at which drive to examine to locate a disc with any given
disc name, even if the drives don't indicate when the disc is changed - most
of the time, the user won't have moved it to a different drive.

It is worth noting that FileCore behaves identically in "Unknown +
Uncertain" state to how it behaves in "Full + Uncertain" state, so for all
intents and purposes they might as well be the same state.

The "Empty + Uncertain" state is a bit of an oddity, in that the only driver
that can currently get FileCore into that state is ADFS's 765 floppy driver,
used with floppy drives that have a non-functional disc-changed line. It
does follow different code paths from the "Empty" state though, so the two
states shouldn't simply be merged with it without a careful code audit and
some suitable test hardware.

It is questionable how much FileCore really needs to remember about discs
that have been removed from drives, at least since the changes in RISC OS
3.00 where FileSwitch took over maintenance of the CSD, PSD, Library and
URD. Note that the "Changing discs" section of the RISC OS 3 PRM actually
describes the responsibilities FileCore had under RISC OS 2, and has not
been updated since!


Summary requirements for MiscOp 1 handlers
------------------------------------------

R2 on exit is your private handle identifying the present time.

By calling your handler, the caller indicates it wants to know about whether
any changes have happened since the time identified by R2 on entry, or since
module initialisation if R2 is 0.

Beyond this requirement, the format of R2 is private to the filing system.

If the media is non-removable, you would normally always set result flag 0
"not changed". For this purpose, hot-pluggable drives do not count as non
removable, because as far as FileCore is concerned, the drive does not come
and go (this is merely an illusion of the icon bar filers).

If you really can't tell if media have been changed, then measure whether a
short timeout (analogous to a floppy disc spin down time) has elapsed
between DiscOps, and set result flag 1 "maybe changed" if this has happened
once or more, otherwise result flag 0 "not changed". Drive empty conditions
in this case would typically be detected via errors returned from DiscOp
instead, when the operation times out; otherwise FileCore would already know
that the drive was empty and would generate the error itself without needing
to call DiscOp. Just as with the ADFS floppy drivers, if you later determine
that you can detect media changes after all, you should switch to the rules
below.

If there have definitely been no changes to the drive, result flag 0 "not
changed" or 3 "empty" must be set, depending on whether the drive is empty
or not.

If there has been exactly one definite change to the drive, then:
* if the drive is now empty, set result flag 3 "empty"
* if the drive was empty but is no longer, you can set flag 2
  "changed" (preferred option) or flag 0 "not changed"
* if the media has changed but no poll occurred while the drive was empty,
  you must set flag 2 "changed"

If there have been more than one definite changes to the drive, then:
* preferably set flag 3 "empty" if the drive is empty - though in
  particular, you may choose to omit this if empty sensing this is a slow
  operation (otherwise multiple clients all monitoring a drive could cause
  several of these slow operations)
* failing that, set result flag 2 "changed"


MiscOp 8
--------

  Informs the filing system of the first boot block on a disc

On entry
  R0 = 8
  R1 = drive
  R2 = pointer to copy of the boot block in memory, or 0
  R3 = disc size in bytes (from partition table), low word
  R4 = disc size in bytes (from partition table), high word
  R8 = pointer to FileCore instance private word (not for low-level entry)

On exit
  All registers preserved

Re-entrancy
  SWI and low-level routine are not re-entrant

Use
  This call gives the filing system the opportunity to inspect the boot
  block for the first partition on a disc, typically so that it can extract
  values from the hardware-dependent information section.

  It is only called for drives that use hard-disc style mounting. It is
  called after FileCore has identified and decoded the partition table (if
  any) and located and loaded what would be the boot block from the first
  partition, or the boot block for the whole disc if it is not partitioned.
  If this vaidates as a FileCore boot block, then R2 contains a pointer to
  a copy of the boot block.

  Otherwise, R2 contains 0, and the filing system should assume some
  sensible defaults. For example, ADFS will use a parking cylinder at the
  end of the disc (calculated from R3 and R4), with the LBA flag set and
  the drive initialisation flag cleared. The implication is that any drive
  that needs the LBA flag clear, or the drive initialisation flag set,
  will still require that the first partition is FileCore-formatted. This
  does not apply to modern drives (ATA-6 or later), so is not a great
  burden.



Ben Avison, 2012-04-01

