www.riscos.com Technical Support: |
|
FileCore does not know how to communicate directly with the hardware that your filing system uses. Your module must provide these facilities, and declare the entry points to FileCore.
This chapter describes how to add a filing system to FileCore. You should also see the chapter entitled Modules for more information on how to write a module.
When your module initialises, it must inform FileCore of its existence. You must call FileCore_Create to do this. R0 tells FileCore where to find a descriptor block. This in turn tells FileCore the locations of all the entry points to your module's low level routines that interface with the hardware:
This table shows the offsets from the start of the descriptor block, and the meaning of each word in the block:
Offset | Contains |
---|---|
0 | Bit flags |
3 | Filing system number (see the chapter entitled FileSwitch) |
4 | Offset of filing system title from module base |
8 | Offset of boot text from module base |
12 | Offset of low-level disc op entry from module base |
16 | Offset of low-level miscellaneous entry from module base |
The flag bits in the descriptor block have the following meanings:
Bit | Meaning when set |
---|---|
0 | Hard discs need FIQ |
1 | Floppy discs need FIQ |
2 | Reserved - must be zero (was supports background operations under RISC OS 2). |
3 | Use only scratch space when a temporary buffer is needed |
4 | Hard discs support mount like floppies do (ie they fill in sector size, heads, sectors per track and density) |
5 | Hard discs support poll change (ie the poll change call works for hard discs and returns a sensible value; also locking them gives a sensible result) |
6 | Floppy discs support power-eject |
7 | Hard discs support power-eject |
RISC OS 2 only uses bits 0 - 3; it ignores other bits.
Wherever possible, you should make hard discs support mount like floppies do, and hence set bit 4. If you do not do so, FileCore may have trouble mounting discs that use an alien format, as it then has no way of determining their geometry, and so has to make some assumptions that may be invalid.
FileCore_Create starts a new instantiation of FileCore, and, on return to your module, R0 points to the workspace that has been reserved for that new instantiation of FileCore. You must store this pointer in your module's workspace for future calls to FileCore; it is this value that tells FileCore which filing system you are (as well as enabling it to find its workspace!).
Unlike filing systems that are added under FileSwitch, the boot text offset cannot be -1 to call a routine.
The table below shows areas which may be used for temporary buffers when bit 3 of the flag word is not set:
Scratch space | Spare screen area | Wimp free pool | RMA heap | System heap | Application area | Directory cache | |
---|---|---|---|---|---|---|---|
FSEntry_Func 8 | |||||||
FSEntry_Close | |||||||
FSEntry_Args 7 | |||||||
AllocCompact | |||||||
Compact | |||||||
*Backup X X | |||||||
*Backup X Y | |||||||
*Backup X X q | |||||||
*Backup X Y q | |||||||
*Compact |
where AllocCompact is the auto-compact triggered when allocating space for a file, and Compact is a normal auto-compact.
Your filing system should provide a * Command to select itself, such as *ADFS or *Net. This must call OS_FSControl 14 to inform FileSwitch that the module has been selected, thus:
StarFilingSystemCommand STMFD r13!, {r14} MOV r0, #FSControl_SelectFS ADR r1, FilingSystemName SWI XOS_FSControl LDMFD r13!, {pc}
For full details of OS_FSControl 14, see OS_FSControl 14.
There are no other * Commands that your filing system must provide. For many FileCore-based systems the range it provides will be enough, and your module need add no more.
SWI calls in a FileCore module are usually implemented by simply:
For example, here is how a module might implement a DiscOp SWI:
STMFD r13!, {r8, r14} ; R12 points to module workspace LDR r8, [r12, #offset] ; R8 <- pointer to FileCore private word SWI XFileCore_DiscOp LDMFD r13!, {r8, pc}
Usually DiscOp, Drives, FreeSpace and DescribeDisc are implemented like this. Of course you can add any extra SWI calls that are necessary.
The finalise entry of your module must remove its instantiation of FileCore. For full details of how to do so, see the chapter entitled Finalisation Code.
Your module has to return errors through FileCore as follows:
The V flag must be set, and R0 is used to indicate the error:
bits 0 - 20 are the disc byte address / 256
bits 21 - 23 are the drive number
bits 24 - 29 are the disc error number
bits 0 - 7 are an error number (see list below)
bits 8 - 29 are clear
In the latter two cases FileCore will generate a suitable error block.
The error numbers that may be returned are:
The next section describes the interfaces to FileCore that your module must provide.
Your module must provide two interfaces to FileCore: one for DiscOps, and one for other miscellaneous functions.
The entry for DiscOps does much of the work for a DiscOp SWI. It is passed the same values as FileCore_DiscOp (see FileCore_DiscOp), except:
These are the reason codes that may be passed in R1:
Value | Meaning | Uses | Updates |
---|---|---|---|
0 | Verify | R2, R4 | R2, R4 |
1 | Read sectors | R2, R3, R4 | R2, R3, R4 |
2 | Write sectors | R2, R3, R4 | R2, R3, R4 |
3 | Floppy disc: read track | R2, R3 | |
Hard disc: read Id | R2, R3 | ||
4 | Write track | R2, R3 | |
5 | Seek (used only to park) | R2 | |
6 | Restore | R2 | |
7 | Floppy disc: step in | ||
8 | Floppy disc: step out | ||
15 | Hard disc: specify | R2 |
The reason codes you must support are 0, 1, 2, 5 and 6. You must complete the entire operation requested, or give an error if you are unable to do so.
Your routine must preserve R1 - R13 inclusive, except where noted otherwise above, ie:
You must also preserve the N, Z and C flags.
If there is no error then R0 must be zero on exit and the V flag clear. If there is an error then V must be set and R0 must be one of the following:
Value | Meaning |
---|---|
R0 < &100 | internal FileCore error number |
Bit 30 set, bit 31 clear | pointer to error block |
Bit 30 clear, bit 31 set | disc error bits:
|
For a list of internal FileCore error numbers, see the chapter entitled Disc errors.
If bit 8 of R1 is set, then transfer may be wholly or partially in the background. This is an optional extension to improve performance. To reduce rotational latency the protocol also provides for transfers of indeterminate length.
R3 points to a list of address/length word pairs, specifying an exact number of sectors. The length given in R4 is treated as the length of the foreground part of the transfer. R5 is a pointer to the disc record.
Your module should return to the caller when the foreground part is complete, leaving a background process scheduled by interrupts from the controller. This process should terminate when it finds an address/length pair with a zero length field.
The foreground process can add pairs to the list at any time. To get the maximum decoupling between the processes your module should update the list after each sector. This updating must be atomic (use the STMIA instruction). Your module must be able to retry in the background.
The list is extended as below:
Offset | Contents |
---|---|
-8 | Process error |
-4 | Process status |
0 | 1st address |
4 | 1st length |
8 | 2nd address |
12 | 2nd length |
16 | 3rd address |
20 | 3rd length |
etc | |
n | Loop back marker -n (where n is a multiple of 8) |
n+4 | Length of zero |
Process error is set by the caller to 0; on an error your module should set this to describe the error in the format described above.
The bits in process status are:
Bit | Meaning when set |
---|---|
31 | process active |
30 | process can be extended |
0 - 29 | pointer to block giving position of any error |
Bits 31 and 30 are set by the caller and cleared by your module. Your module must have IRQs disabled from updating the final pair in the list to clearing the active bit.
A negative address of -n indicates that your module has reached the end of the table, and should get the next address/length pair from the start of the scatter list n bytes earlier.
Your module may be called with the scatter pointer (R3) not pointing to the first (address/length) pair. So, to find the addresses of Process error and Process status, you must search for the end of list. From this you may then calculate the start of the scatter block.
The entry for MiscOps does much of the work for a MiscOp SWI. It is passed the same values as FileCore_MiscOp (see FileCore_MiscOp) - save for one reason code, noted below, which can be passed extra parameters.
These are the reason codes that may be passed in R0:
Value | Meaning |
---|---|
0 | Mount |
1 | Poll changed |
2 | Lock drive |
3 | Unlock drive |
4 | Poll period |
5 | Eject disc |
The reason codes you must support are 0, 2 and 3; for floppy drives, you must also support reason codes 1 and 4.
Your routine must preserve registers, and the N, Z and C flags - except where specifically stated otherwise.
When this entry point is called, R12 is a pointer to your FileCore module's private word.
You may only return an error from reason code 0 (Mount). This must be done in the same way as for the DiscOp entry; see the chapter entitled Returning errors.
For drives with disc sensing, reason code 1 (Poll changed) must always return changed in the spun-down state. If the drive is spun-up, you must return maybe changed if the drive has been permanently spun-up since the last 'Poll changed'; other wise you must return changed:
'Poll changed' returns for drives with disc sensing
Under RISC OS 2, the values returned from MiscOp 1 (Poll changed) in bits 4, 5, and 8 - 10 of R3 are ignored by FileCore.
Reason codes 2 and 3 (Lock/Unlock drive) must always perform that action. You must not try to track the state of the drive locking; FileCore counts lock/unlock calls itself, and only calls your module when it should actually lock or unlock the drive.
Reason code 5 (Eject disc) will never be called if bits 6 and 7 of the descriptor block are clear, since this indicates that no drives support power-ejection. Otherwise it may get called in a variety of situations: for example, after dismounting all discs as part of shutting down all filing systems.
Reason code 5 is also called whenever FileCore issues an UpCall 1 (medium not present), or an UpCall 2 (medium not known). In this case, the top bit of the drive number is set, indicating that a disc should be ejected from the drive considered to be most appropriate. The values passed to the UpCall in R4 (the iteration count) and in R5 (the minimum timeout period) are also passed on in the same registers to the MiscOp entry point. The filing system may treat these as appropriate; for example, it may choose to eject only on iteration 0 for an auto-insert detect drive, as doing further ejects may make it hard to get a new disc into the drive.
For more details of OS_UpCall 1 and 2, see OS_UpCall 1 and 2.