www.riscos.com Technical Support: |
|
You can add filing systems to RISC OS. You must write them as relocatable modules. There are two ways of doing so:
In both cases, the amount of work you have to do is considerably less than if you were to write a filing system from scratch, as the FileSwitch and FileCore modules already provide a core of the functions your filing system must offer. Obviously if you use FileCore as well as FileSwitch, more is already provided for you, and so you have even less work to do. The structure of FileCore is then imposed on your filing system; to the user, it will appear very similar to ADFS, leading to a consistency of design.
Obviously there is no way that FileSwitch can know how to communicate directly with the entire range of hardware that any filing system might use. Your filing system must provide these facilities, and declare the entry points to FileSwitch. When FileSwitch receives a SWI call or * Command, it does its share of the work, and uses these entry points to get the relevant filing system to do the work that is hardware dependent.
The relevance of the rest of this chapter depends on how you intend to write your own filing system:
In both cases you should also see the chapter entitled Modules, for more information on how to write a module.
When your module initialises, it must declare itself to be a filing system, so that FileSwitch knows of its existence. You must call OS_FSControl 12 to do this - see OS_FSControl 12 for details. R1 and R2 tell FileSwitch where to find a filing system information block. This in turn tells FileSwitch the locations of all the entry points to the filing system's low level routines that interface with the hardware.
This table shows the offsets from the start of the filing system information block, and the meaning of each word in the block:
Offset | Contains | ||||||
---|---|---|---|---|---|---|---|
&00 | Offset of filing system name (null terminated) | ||||||
&04 | Offset of filing system startup text (null terminated) | ||||||
&08 | Offset of routine to open files (FSEntry_Open) | ||||||
&0C | Offset of routine to get bytes from media (FSEntry_GetBytes) | ||||||
&10 | Offset of routine to put bytes to media (FSEntry_PutBytes) | ||||||
&14 | Offset of routine to control open files (FSEntry_Args) | ||||||
&18 | Offset of routine to close open files (FSEntry_Close) | ||||||
&1C | Offset of routine to do whole file operations (FSEntry_File) | ||||||
&20 | Filing system information word
&24
| Offset of routine to do various FS operations (FSEntry_Func)
| &28
| Offset of routine to do multi-byte operations (FSEntry_GBPB)
| &2C
| Extra filing system information word (optional)
| |
The offsets held in each word are from the base of the filing system module. The GBPB entry (at offset &28 from the start of the information block) is optional if the filing system supports non buffered I/O, and not required otherwise.
The block need not exist for long, as FileSwitch takes a copy of it and converts the entry points to absolute addresses. So you could set up the block as an area in a stack frame, for example.
The filing system information word (at offset &20) tells FileSwitch various things about the filing system:
Bit | Meaning if set |
---|---|
31 | Special fields are supported |
30 | Streams are interactive (ie prompting for input is appropriate) |
29 | Filing system supports null length filenames |
28 | Filing system should be called to open a file whether or not it exists |
27 | Tell the filing system when flushing by calling FSEntry_Args 255 |
26 | Filing system supports FSEntry_File 9 |
25 | Filing system supports FSEntry_Func 20 |
24 | Reserved - must be zero |
23 | Filing system supports image filing system extensions |
22 | Pass & and % in paths when appropriate |
21 | Need not store directories for this filing system |
20 | Use Open/GetBytes/Close entry points rather than File 255 |
19 | Use Open/GetBytes/Close entry points rather than File 0 |
18 | Use FSEntry_Func 9 in preference to FSEntry_File entry points |
17 | Extra filing system information word is present |
16 | Filing system is read-only |
15 - 8 | Maximum number of files that may be open (see below) |
7 - 0 | Filing system number (see below) |
Bits 16 - 23 are ignored by RISC OS 2. File systems that were written for RISC OS 2 should have these bits clear, which may cause problems: for example, RISC OS 2 read-only filing systems will incorrectly have bit 16 clear.
Bits 8 - 15 tell FileSwitch the maximum number of files that can be easily opened on the filing system (per server, if appropriate). A value of 0 means that there is no definite limiting factor - DMA failure does not count as such a factor. These bits may be used by system extension modules such as the Font Manager to decide whether a file may be left open or should be opened and closed as needed, to avoid the main application running out of file handles.
Bits 0 - 7 contain the filing system identification number. Currently allocated ones are listed in the Filing system numbers. For your own allocation, contact Acorn Computers in writing: see Appendix H: Registering names.
The extra filing system information word is present if bit 17 of the filing system information word is set. If absent, it is assumed by FileSwitch to have value zero. The meaning of the bits in the word is as follows:
Bit | Meaning if set |
---|---|
0 | Filing system supports FSEntry_Func 34 |
1 | Filing system should be called to do Cat |
2 | Filing system should be called to do Ex |
3 - 31 | Reserved - must be zero |
You should only set bits 1 and 2 if your filing system provides a non-standard format for Cat and Ex respectively.
Your filing system must have a Service Call handler. It must respond to Service_FSRedeclare (see Service_FSRedeclare) by redeclaring the filing system. For some filing systems, it may be appropriate to respond to Service_CloseFile. Disc based filing systems should also support Service_IdentifyDisc, Service_EnumerateFormats, Service_IdentifyFormat, and Service_DisplayFormatHelp.
If your filing system has associated file storage, it must provide a * Command to select itself, such as *ADFS or *Net. This must call OS_FSControl 14 to direct FileSwitch to make the named filing system current, thus:
StarFilingSystemCommand STMFD r13!, {r14} ; In a * Command so R0-R6 may be corrupted MOV r0, #FSControl_SelectFS ; 14 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, but it obviously should provide more than just a way to select itself. Look through the previous chapters in this part of the manual to see what other filing systems offer.
If the list of * Commands you want to provide closely matches those in the FileCore, you ought to investigate adding your filing system to FileCore rather than to FileSwitch; this will be less work for you.
The finalise entry of your module must call OS_FSControl 16 (for both soft and hard deaths), so that FileSwitch knows that your filing system is being removed:
MOV r0, #FSControl_RemoveFS ; 16 ADR r1, FilingSystemName SWI XOS_FSControl CMP pc, #0 ; Clears V (also clears N,Z, sets C)
For full details of OS_FSControl 16, see OS_FSControl 16.
For a description of image filing systems, and their relationship to other filing systems, see the chapter entitled DOSFS. Image filing systems are not supported by RISC OS 2.
When your module initialises, it must declare itself to be an image filing system, so that FileSwitch knows of its existence. You must call OS_FSControl 35 to do this - see OS_FSControl 35 for details. R1 and R2 tell FileSwitch where to find an image filing system information block. This in turn tells FileSwitch the locations of all the entry points to the image filing system's low level routines that interface with the hardware.
This table shows the offsets from the start of the image filing system information block, and the meaning of each word in the block:
Offset | Contains |
---|---|
&00 | Image filing system information word |
&04 | Image filing system file type |
&08 | Offset of routine to open files (ImageEntry_Open) |
&0C | Offset of routine to get bytes from media (ImageEntry_GetBytes) |
&10 | Offset of routine to put bytes to media (ImageEntry_PutBytes) |
&14 | Offset of routine to control open files (ImageEntry_Args) |
&18 | Offset of routine to close open files (ImageEntry_Close) |
&1C | Offset of routine to do whole file operations (ImageEntry_File) |
&24 | Offset of routine to do various FS operations (ImageEntry_Func) |
The offsets held in each word are from the base of the image filing system module.
The block need not exist for long, as FileSwitch takes a copy of it and converts the entry points to absolute addresses. So you could set up the block as an area in a stack frame, for example.
The image filing system file type gives the numerical file type of files which contain images understood by the image filing system.
The image filing system information word (at offset 0) tells FileSwitch various things about the image filing system:
Bit | Meaning if set |
---|---|
27 | Tell the image filing system when flushing by calling ImageEntry_Args 255 |
All other bits are reserved and should be set to zero.
Your image filing system must have a Service Call handler. It must respond to the same service calls as any other filing system; see the chapter entitled Service Call handler.
There are no * Commands that your image filing system must provide, but most should provide some. See the chapter entitled DOSFS for an example of what other image filing systems offer.
The finalise entry of your module must call OS_FSControl 36 (for both soft and hard deaths), so that FileSwitch knows that your image filing system is being removed:
MOV r0, #FSControl_DeRegisterImageFS ; 36 ADR r1, ImageFileType SWI XOS_FSControl CMP pc, #0 ; Clears V (also clears N,Z, sets C)For full details of OS_FSControl 36, see OS_FSControl 36.
The principal part of a filing system (or of an image filing system) is the set of low-level routines that control the filing system's hardware. There are certain conventions that apply to them.
Routines called by FileSwitch are always entered in SVC mode, with both IRQs and FIQs enabled. This means you do not have to change mode to access hardware devices directly, and are able to change to FIQ mode to set up FIQ registers if necessary.
R13 in supervisor mode is used as the system stack pointer. The filing system (or image filing system) may use this full descending stack. When the filing system (or image filing system) is entered you should take care not to push too much onto the stack, as it is only guaranteed to be 1024 bytes deep; however most of the time it is substantially greater. The stack base is on a 1Mbyte boundary. Hence, to determine how much stack space there is left for your use, use the following code:
MOV R0, R13, LSR #20 ; Get Mbyte value of SP SUB R0, R13, R0, LSL #20 ; Sub it from actual value
You may move the stack pointer downwards by a given amount and use that amount of memory as temporary workspace. However, interrupt processes are allowed to use the supervisor stack so you must leave enough room for these to operate. Similarly, if you call any operating system routines, you must give them enough stack space.
If a read or write operation occurs that requires a file buffer to be claimed for a file, and this memory claim fails, then FileSwitch will look to steal a file buffer from some other file. Victims are looked for in the order:
In the last two cases, FileSwitch obviously calls the filing system (or image filing system) to write out the buffer first, before giving it to the new owner. If an error occurs in writing out the buffer under RISC OS 2, the stream that owned the data in the buffer (not the stream that needed to get the buffer) is marked as having 'data lost'; any further operations will return the 'Data lost' error. FileSwitch is always capable of having one file buffered at any time, although it won't work very well under such conditions.
R12 on entry to the filing system (or image filing system) is set to the value of R3 it passed to FileSwitch when initialising by calling OS_FSControl 12 or 35. Conventionally, this is used as a pointer to your private word. In this case, module entries should contain the following:
LDR R12, [R12]
to load the actual private word into the register.
The error numbers your filing system returns should take this format:
&0001nnee
where nn is the filing system number, as passed in the information word (see the chapter entitled Filing system information word); and ee is one of the error numbers used by FileCore based filing systems (see the table on Error Token Default text), or - if none is relevant - a number that does not appear in that table.
Filing systems may support both buffered and unbuffered streams. Unbuffered streams must maintain their own sequential pointers, file extents and allocated sizes. File Switch will maintain the EOF-error-on-next-read flag for them.
Image filing system streams are always buffered; consequently they should not support unbuffered streams.
Generally FileSwitch does not make calls to filing systems (or to image filing systems) unless the access on objects is correct for the requested operation.
Note that if a file is opened for buffered output and has only write access, FileSwitch may still attempt to read from it to perform its file buffering. You must not fault this.
Filing system (or image filing system) routines do not need to preserve any registers other than R13.
If a routine wishes to return an error, it should return to FileSwitch with V set and R0 pointing to a standard format error block.
You may assume that:
All pathnames should be treated as read-only If you do need to make changes to a pathname, you must copy it to your local workspace and modify that copy.
All filing system interfaces, with the exception of FSEntry_Func 23, are always passed names in the canonical form. This canonical form is defined by the designer of a particular filing system and is fixed. Canonical form is used to ensure that dissimilar references to the same object reduce to identical strings, and thus the filing system can easily determine that two object references are to the same object. For example after:
*Mount 0 *Dir A.z
references to $.a.b.c and to ^.b.c will reduce to the same canonical form:
adfs::MyDisc.$.a.b.c
The use of canonical form also helps the filing system to run faster. Because all filing system interfaces only receive canonical names, the parsing can be fast and efficient. Remember that canonicalisation happens once for several calls to the filing system itself.
The chosen canonical form should be a subset of the acceptable name styles, and hence the canonical name should be acceptable to the canonicaliser as input. For example the input syntax for the NetFS canonicaliser is:
Net[#(name|number]:[:discname.]$|&
The output format is:
Net::name.$|&
It is also worthwhile optimising the canonicalisation code so that an already canonical name is processed very fast.
In the following descriptions a pathname will always be relative to the root directory of the image, and will never have any '^', '$', '@', '%', '\' or '&' characters in it. When a wildcarded pathname is specified, the operation should be applied to all matching leafnames; but earlier wildcarded elements in the path should use the first match. A null pathname indicates the root directory of the image.
These are the interfaces that your filing system (or image filing system) must provide. Their entry points must be declared to FileSwitch by calling OS_FSControl 12 when your filing system module is initialised, or by calling OS_FSControl 35 when your image filing system module is initialised.
R0 = reason code
R1 = pointer to filename
R3 = FileSwitch handle for the file
R6 = pointer to special field if present, otherwise 0
R0 = file information word (not the same as the filing system information word)
R1 = your filing system's handle for the file (0 if not found)
R2 = buffer size for FileSwitch to use (0 if file unbuffered, else must be a power of 2 between 64 and 1024)
R3 = file extent (buffered files only)
R4 = space currently allocated to file (buffered files only: must be a multiple of buffer size)
R1 = pointer to filename
R3 = FileSwitch handle for the file
R6 = image filing system's handle for image that contains file
R0 = image file information word (not the same as the image filing system information word)
R1 = your image filing system's handle for the file (0 if not found)
R2 = buffer size for FileSwitch to use (must be a power of 2 between 64 and 1024)
R3 = file extent
R4 = space allocated to file (must be a multiple of buffer size)
FileSwitch calls this entry point to open a file for read or write, and to create it if necessary.
On entry, R3 contains the handle that FileSwitch will use for the file if your filing system successfully opens it. This is a small integer (typically going downwards from 255), but must be treated as a 32-bit word for future compatibility. Your filing system may want to make a note of it when the file is opened, in case it needs to refer to files by their FileSwitch handles (for example, it must close all open files on a *Dismount). It is the FileSwitch handle that the user sees.
On exit, your filing system must return a 32-bit file handle that it uses internally to FileSwitch. FileSwitch will then use this file handle for any further calls to your filing system. You may use any value, apart from a handle of 0 which means that no file is open.
The value returned in R2 is the natural block size of the file; for disc oriented filing systems, this should be the same as the natural sector size. FileSwitch - when calling the filing system - will tend to use multiple of this value, aligned on a boundary which is also a multiple of this value.
If your memory allocation fails, this is not an error, and you should indicate it to FileSwitch by setting R1 to 0 on exit.
The reason code given in R0 has the following meaning:
Value | Meaning |
---|---|
0 | Open for read |
1 | Create and open for update |
2 | Open for update |
For both reason codes 0 and 2 FileSwitch will already have checked that the object exists (unless you have overridden this by setting bit 28 of the filing system information word) and, for reason code 2 only, that it is not a directory. These reason codes must not alter a file's datestamp.
If a directory is opened for reading, then bytes will not be requested from it. The use of this is for compatibility with existing programs which use this as a method of testing the existence of an object.
For reason code 1 FileSwitch will already have checked that the leafname is not wildcarded, and that the object is not an existing directory. Your filing system should return an extent of zero. If the file already exists you should return an allocated space the same as that of the file; otherwise you should return a sensible default that allows space for the file to grow. Your filing system should also give a new file a filetype of &FFD (Data), datestamp it, and give it sensible access attributes (WR/ is recommended).
The file information word returned in R0 uses the following bits:
Bit | Meaning if set |
---|---|
31 | Write permitted to this file |
30 | Read permitted from this file |
29 | Object is a directory |
28 | Unbuffered OS_GBPB supported (stream-type devices only) |
27 | Stream is interactive |
All other bits are reserved and should be set to 0.
An interactive stream is one on which prompting for input is appropriate, such as kbd:.
FileSwitch will already have checked that the object exists and that it is not a directory. You must not alter a file's datestamp.
The image file information word returned in R0 uses the following bits:
Bit | Meaning if set |
---|---|
31 | Write permitted to this file |
30 | Read permitted from this file |
R1 = file handle used by your filing system/image filing system
R2 = pointer to buffer
R3 = number of bytes to read into buffer
R4 = file offset from which to get data
--
This entry point is used by FileSwitch to request that you read a number of bytes from an open file, and place them in memory.
The file handle is guaranteed by FileSwitch not to be a directory, but not necessarily to have had read access granted at the time of the open - see the last case given below.
The memory address is not guaranteed to be of any particular alignment. You should if possible optimise your filing system's transfers to word-aligned locations in particular, as FileSwitch's and most clients do tend to be word-aligned. The speed of your transfer routine is vital to filing system performance. An optimised example (similar to that used in RISC OS) is given in the Example program.
The number of bytes to read, and the file offset from which to read data are guaranteed to be a multiple of the buffer size for this file. The file offset will be within the file's extent.
This call is made by FileSwitch for several purposes:
Note that FileSwitch holds no buffered data immediately after a file has been opened.
R1 = file handle used by your filing system
R0 = byte read, C clear
R0 = undefined, C set if attempting to read at end of file
This entry point is called by FileSwitch to get a single byte from an unbuffered file from the position given by the file's sequential pointer. The sequential pointer must be incremented by one, unless the end of the file has been reached.
The file handle is guaranteed by FileSwitch not to be a directory and to have had read access granted at the time of the open.
Your filing system must not try to keep its own EOF-error-on-next-read flag - instead it must return with C set whenever the file's sequential pointer is equal to its extent before a byte is read. It is FileSwitch's responsibility to keep the EOF-error-on-next-read flag.
If your filing system does not support unbuffered GBPB directly, then FileSwitch will call this entry the necessary number of times to complete its client's request, stopping if you return with the C flag set (EOF).
R1 = file handle used by your filing system/image filing system
R2 = pointer to buffer from which to read data
R3 = number of bytes of data to read from buffer and put to file
R4 = file offset at which to put data
--
This entry point is called by FileSwitch to request that you take a number of bytes, and place them in the file at the specified file offset.
The file handle is guaranteed by FileSwitch not to be a directory, and to have had write access granted at the time of the open.
The memory address is not guaranteed to be of any particular alignment. You should if possible optimise your filing system's transfers to word-aligned locations in particular, as FileSwitch's and most clients do tend to be word-aligned. The speed of your transfer routine is vital to filing system performance. An optimised example (similar to that used in FileSwitch) is given in the Example program.
The number of bytes to write, and the file offset at which to write data are guaranteed to be a multiple of the buffer size for this file. The final write will be within the file's extent, so it will not need extending.
This call is made by FileSwitch for several purposes:
Note that FileSwitch holds no buffered data immediately after a file has been opened.
R0 = byte to put to file (top 24 bits zero)
R1 = file handle used by your filing system
--
This entry point is called by FileSwitch to request that you put a single byte to an unbuffered file at the position given by the file's sequential file pointer. You must advance the sequential pointer by one. If the sequential pointer is equal to the file extent when this call is made, you must increase the allocated space of the file by at least one byte to accommodate the data - although it will be more efficient to increase the allocated space in larger chunks (256 bytes/1k is common).
The file handle is guaranteed by FileSwitch not to be a directory, and to have had write access granted at the time of the open.
If your filing system does not support unbuffered GBPB directly, then FileSwitch will call this entry the necessary number of times to complete its client's request.
Various calls are made by FileSwitch through these entry points to deal with controlling open files. The actions are specified by R0 as follows:
R0 = 0
R1 = file handle used by your filing system
R2 = sequential file pointer
This entry point is called by FileSwitch to read the sequential file pointer for the given file. You should only support this call if your filing system uses unbuffered files.
If your filing system does not support a pointer as the concept is meaningless (kbd: for example) then it must return a pointer of 0, and not return an error.
R0 = 1
R1 = file handle used by your filing system
R2 = new sequential file pointer
--
This entry point is called by FileSwitch to request that you alter the sequential file pointer for a given file. You should only support this call if your filing system uses unbuffered files.
If the new pointer is greater than the current file extent then:
If you cannot extend the file you should return an error as soon as possible, and in any case before you update the extent.
If your filing system does not support a pointer as the concept is meaningless (kbd: for example) then it must ignore the call, and not return an error.
R0 =2
R1 = file handle used by your filing system
R2 = file extent
This entry point is called by FileSwitch to read the extent of a given file. You should only support this call if your filing system uses unbuffered files.
If your filing system does not support file extents as the concept is meaningless (kbd: for example) then it must return an extent of 0, and not return an error.
R0 = 3
R1 = file handle used by your filing system/image filing system
R2 = new file extent
--
This entry point is called by FileSwitch to request that you change the extent of a file.
The file handle is guaranteed by FileSwitch not to be a directory, and to have had write access granted at the time of the open.
If the filing system does not support file extents as the concept is meaningless (kbd: for example) then it must ignore the call, and not return an error.
For buffered files, FileSwitch only calls this entry point to set the real file extent just prior to closing an open file. Your filing system should store the value of R2 in the file's catalogue information as its new length.
For unbuffered files, FileSwitch calls this entry point whenever requested to by its client.
If the new extent is less than the current sequential pointer (the file is shrinking and the pointer would lie outside the file), then you must set the pointer to the new extent.
If the new extent is greater than the current one then you must extend the file with zeros. If you cannot extend the file you should return an error as soon as possible, and in any case before you update the extent.
R0 = 4
R1 = file handle used by your filing system/image filing system
R2 = size allocated to file by filing system
This entry point is called by FileSwitch to read the size allocated to a given file. All filing systems must support this call.
R0 = 5
R1 = file handle used by your filing system/image filing system
R2 = -1 if (sequential pointer is equal to current extent), otherwise R2 = 0
This entry point is called by FileSwitch to determine whether the sequential pointer for a given file is at the end of the file or not. You should only support this call if your filing system uses unbuffered files.
If a filing system does not support a pointer and/or a file extent as the concept(s) are meaningless (kbd: for example) then the treatment of the C bit is dependent on that filing system. For example, kbd: gives EOF when Ctrl-D is read from the keyboard; null: always gives EOF; and vdu: never gives EOF.
R0 = 6
R1 = file handle used by your filing system/image filing system
R2 = load address of file (or 0)
R3 = execution address of file (or 0)
This entry point is called by FileSwitch to request that your filing system flushes any modified data that it is holding in buffers. You should only support this call if your filing system does its own buffering in addition to that done by FileSwitch. For example, ADFS does its own buffering when doing readahead/writebehind, and so needs to use this call.
The modified data should be flushed to its storage media.
This entry point is only called if your filing system is buffered, and you set bit 27 of your filing system information word when you initialised your filing system.
The modified data should be flushed to its image. The image should subsequently be flushed to its storage media to ensure the data's integrity.
This entry point is only called if you set bit 27 of your image filing system information word when you initialised your image filing system.
R0 = 7
R1 = file handle used by your filing system/image filing system
R2 = size of file to ensure
R2 = size of file actually ensured
This entry point is called by FileSwitch to ensure that a file is of at least the given size. Your file system should do just this, but need not ensure that any extra space is zeroed. All filing systems must support this call.
R0 = 8
R1 = file handle used by your filing system
R2 = file offset at which to write
R3 = number of zero bytes to write
--
This entry point is called by FileSwitch to request that your filing system writes a given number of zero bytes to a given offset within a file. You should only support this call if your filing system uses buffered files.
The file handle is guaranteed by FileSwitch not to be a directory, and to have had write access granted at the time of the open.
The number of bytes to write, and the file offset at which to write data are guaranteed to be a multiple of the buffer size for this file.
R0 = 9
R1 = file handle used by your filing system/image filing system
R2 = load address of file (or 0)
R3 = execution address of file (or 0)
This entry point is called by FileSwitch to read the date/time stamp for a given file. The bottom four bytes of the date/time stamp are stored in the execution address of the file. The most significant byte is stored in the least significant byte of the load address. All filing systems must support this call. If your filing system cannot stamp an open file given its handle, then it should return R2 and R3 set to zero.
R0 = 10
R1 = file handle used by your filing system/image filing system
R2 = new image stamp of image
All registers preserved
This entry point is called by FileSwitch when an image filing system has changed an image's image stamp (a unique identification number). The purpose of the call is to inform your filing system of the change, and to pass it the new image stamp. If your filing system does not support the root object being an image, then it should ignore this call. Otherwise - as for example in the case of FileCore - you should update your filing system's internal note of the image stamp, as you may need to use it to identify the disc at a later time.
This call is for information only, and should not require any further action. It is not called by RISC OS 2, which does not support image filing systems.
R1 = file handle used by your filing system/image filing system
R2 = new load address to associate with file
R3 = new execution address to associate with file
--
This entry point is called by FileSwitch to request that your filing system close an open file, and put a new date/time stamp on it. For ImageEntry_Close, you should then call OS_Args 255 on the image after updating the structure for the closed file; this ensures that all data is flushed to the disc.
If your filing system returned from the FSEntry_Args 9 (or ImageEntry_Args 9) call with R2 and R3 both zero, then they will also have that value here, and you should not try to restamp the file. Restamping takes place if the file has been modified and FSEntry_Args 9 (or ImageEntry_Args 9) returned a non-zero value in R2.
Note that *Close and *Shut (ie close all open files) are performed by FileSwitch which passes the handles, one at a time, to the relevant filing system for closing. Filing systems should not try to support this themselves.
Various calls are made by FileSwitch through these entry points to perform operations on whole files. The actions are specified by R0 as follows:
R0 = 0
R1 = pointer to filename
R2 = load address to associate with file
R3 = execution address to associate with file
R4 = pointer to start of buffer
R5 = pointer to byte after end of buffer
R6 = pointer to special field if present, otherwise 0 (FSEntry_File 0); or image filing system's handle for image that contains file (ImageEntry_File 0)
R6 = pointer to a leafname for printing *OPT 1 info
This entry point is called by FileSwitch to request that your filing system saves data from a buffer held in memory to a file. FileSwitch has already validated the buffer, and ensured that the leafname is not wildcarded. If the file currently exists and is not locked, the old file is first discarded. The new file should have the same access attributes as the one it is replacing, or some default access if the file doesn't already exist. You should return an error such as File locked if you could not save the specified file.
FileSwitch immediately copies the leafname returned in R6, so it need not have a long lifetime. You could hold it in a small static buffer, for example.
R0 = 1
R1 = pointer to wildcarded filename
R2 = new load address to associate with file
R3 = new execution address to associate with file
R5 = new attributes for file
R6 = pointer to special field if present, otherwise 0 (FSEntry_File 1); or image filing system's handle for image that contains file (ImageEntry_File 1)
--
This entry point is called by FileSwitch to request that your filing system updates the catalogue information for an object. If the object is a directory you must either write the information (FileCore-based filing systems do) or return an error. You must not return an error if the object does not exist.
R0 = 2
R1 = pointer to wildcarded filename
R2 = new load address to associate with file
R6 = pointer to special field if present, otherwise 0
--
This entry point is called by FileSwitch to request that your filing system alters the load address for a file. If the object is a directory you must either write the information (FileCore-based filing systems do) or return an error. You must not return an error if the object does not exist.
R0 = 3
R1 = pointer to wildcarded filename
R3 = execution address to associate with file
R6 = pointer to special field if present, otherwise 0
--
This entry point is called by FileSwitch to request that your filing system alters the execution address for a file. If the object is a directory you must either write the information (FileCore-based filing systems do) or return an error. You must not return an error if the object does not exist.
R0 = 4
R1 = pointer to wildcarded pathname
R5 = new attributes to associate with file
R6 = pointer to special field if present, otherwise 0
--
This entry point is called by FileSwitch to request that your filing system alters the attributes of an object. You must not return an error if the object does not exist.
R0 = 5
R1 = pointer to pathname
R6 = pointer to special field if present, otherwise 0 (FSEntry_File 5); or image filing system's handle for image that contains file (ImageEntry_File 5)
R0 = object type:
R2 = load address
R3 = execution address
R4 = file length
R5 = file attributes
R6 preserved (ImageEntry_File 5)
This entry point is called by FileSwitch to request that your filing system returns the catalogue information for an object. You should return an error if:
You should return type 0 if:
R0 = 6
R1 = pointer to filename
R6 = pointer to special field if present, otherwise 0 (FSEntry_File 6); or image filing system's handle for image that contains file (ImageEntry_File 6)
R0 = object type
R2 = load address
R3 = execution address
R4 = file length
R5 = file attributes
This entry point is called by FileSwitch to request that your filing system deletes an object. FileSwitch will already have ensured that the leafname is not wildcarded. No data need be transferred to the file. You should return an error if the object is locked against deletion, but not if the object does not exist. The results refer to the object that was deleted.
R0 = 7
R1 = pointer to filename
R2 = load address to associate with file
R3 = execution address to associate with file
R4 = start address in memory of data
R5 = end address in memory plus one
R6 = pointer to special field if present, otherwise 0 (FSEntry_File 7); or image filing system's handle for image that contains file (ImageEntry_File 7)
R6 = pointer to a filename for printing *Opt 1 info (FSEntry_File 7 only)
This entry point is called by FileSwitch to request that your filing system creates a file with a given name. R4 and R5 are used only to calculate the length of the file to be created. If the file currently exists and is not locked, the old file is first discarded. The new file should have the same access attributes as the one it is replacing, or some default access if the file doesn't already exist. You should return an error if you couldn't create the file.
R0 = 8
R1 = pointer to directory name
R2 = load address (ignored by RISC OS 2)
R3 = execute address (ignored by RISC OS 2)
R4 = number of entries (0 for default)
R6 = pointer to special field if present, otherwise 0 (FSEntry_File 8); or image filing system's handle for image that contains file (ImageEntry_File 8)
--
This entry point is called by FileSwitch to request that your filing system creates a directory. If the directory already exists then your filing system can do one of these:
If directories don't support load and execute addresses (which will only be of the directory type/datestamp form) then no error should be returned. Note that RISC OS 2 will ignore the load and execute addresses in R2 and R3.
FileSwitch will already have ensured that the leafname is not wildcarded. You should return an error if you couldn't create the directory.
R0 = 9
R1 = pointer to filename
R6 = pointer to special field if present, otherwise 0
R0 = object type
R2 = load address
R3 = execution address
R5 = file attributes
This entry point is called by FileSwitch to read the catalogue information for an object, save for the object length. It is useful for NetFS with fileservers, as the length is not stored in a directory. You must not return an error if the object does not exist.
It is only ever called by *Copy under RISC OS 2; bit 26 of your filing system information word must have been set when the filing system was initialised. Otherwise FileSwitch calls FSEntry_File 5, and the length returned in R4 is ignored.
R0 = 10
R1 = pointer to filename
R6 = pointer to special field if present, otherwise 0 (FSEntry_File 10); or image filing system's handle for image that contains file (ImageEntry_File 10)
R2 = natural block size of the file (in bytes)
This entry point is called by FileSwitch to read the natural block size for a file (see FSEntry_Open and ImageEntry_Open). It is not called by RISC OS 2.
R0 = 255
R1 = pointer to wildcarded filename
R2 = address to load file
R6 = pointer to special file if present; otherwise 0
R0 corrupted
R2 = load address
R3 = execution address
R4 = file length
R5 = file attributes
R6 = pointer to a filename for printing *OPT 1 info
This entry point is called by FileSwitch to request that your filing system loads a file.
FileSwitch will already have called FSEntry_File 5 and validated the client's load request. If FSEntry_File 5 returned with object type 0 then the user will have been returned the 'File 'xyz' not found' error; type 2 will have returned the ''xyz' is a directory' error; types 1 with corresponding load actions will have had them executed (which may recurse back down to load again), those with no read access will have returned 'Access violation', and those being partially or wholly loaded into invalid memory will have returned 'No writeable memory at this address'.
Therefore unless the filing system is accessing data stored on a multi-user server such as NetFS/FileStore, the object will still be the one whose info was read earlier.
The filename pointed to by R6 on exit should be the non-wildcarded 'leaf' name of the file. That is, if the filename given on entry was $.!b*, and the file accessed was the boot file, R6 should point to the string !Boot.
Various calls are made through these entry points to deal with assorted filing system (or image filing system) control. Many of these output information. You should do this in two stages:
This avoids problems caused by the write character process being in the middle of spooling, or by an active task swapper.
If you add a header to output (cf *Info, *Cat and *Ex on ADFS) you must follow it with a blank line. You should always try to format your output to the printable width of the current window. You can read this using XOS_ReadVduVariables to read the WindowWidth variable (&100), which copes with most eventualities. Don't cache the value, but read it before each output.
The actions are specified by R0 as given below.
R0 = 0
R1 = pointer to wildcarded directory name
R6 = pointer to special field if present, otherwise 0
--
This entry point is called by FileSwitch to set the current directory to the one specified by the directory name and context given. If the directory name is null, you should assume it to be the user root directory.
You should not also make the context current, but instead provide an independent means of doing so, such as *FS on the NetFS.
This entry point is called by RISC OS 2; otherwise it is only called to perform a *Opt 1 command when bit 23 of the filing system information word is clear.
R0 = 1
R1 = pointer to wildcarded directory name
R6 = pointer to special field if present, otherwise 0
--
This entry point is called by FileSwitch to set the current library directory to the one identified by the directory name and context given. If the directory name is null, you should assume it to be the filing system default (which is dependent on your implementation).
You should not also make the context current, but instead provide an independent means of doing so, such as *FS on the NetFS.
This entry point is only called by RISC OS 2.
R0 = 2
R1 = pointer to wildcarded directory name
R6 = pointer to special field if present, otherwise 0
--
This entry point is called by FileSwitch to catalogue the directory identified by the directory name and context given. If the directory name is null, you should assume it to be the current directory. (This corresponds to the *Cat command.)
This entry point is called by RISC OS 2; otherwise it is only called if bit 1 of the extra filing system information word is set.
R0 = 3
R1 = pointer to wildcarded directory name
R6 = pointer to special field if present, otherwise 0
--
This entry point is called by FileSwitch to print information on all the objects in the directory identified by the directory name and context given. If the directory name is null, you should assume it to be the current directory. (This corresponds to the *Ex command.)
This entry point is called by RISC OS 2; otherwise it is only called if bit2 of the extra filing system information word is set.
R0 = 4
R1 = pointer to wildcarded directory name
R6 = pointer to special field if present, otherwise 0
--
This entry point is called by FileSwitch to catalogue the specified subdirectory relative to the current library directory. If the directory name is null, you should assume it to be the current library directory. (This corresponds to the *LCat command.)
This entry point is called by RISC OS 2; otherwise it is only called if bit 1 of the extra filing system information word is set.
R0 = 5
R1 = pointer to wildcarded directory name
R6 = pointer to special field if present, otherwise 0
--
This entry point is called by FileSwitch to print information on all the objects in the specified subdirectory relative to the current library directory. If the directory name is null, you should assume it to be the current library directory. (This corresponds to the *LEx command.)
This entry point is called by RISC OS 2; otherwise it is only called if bit 2 of the extra filing system information word is set.
R0 = 6
R1 = pointer to wildcarded pathname
R6 = pointer to special field if present, otherwise 0.
--
This entry point is called by FileSwitch to print information on all the objects matching the wildcarded pathname and context given, in the same format as for FSEntry_Func 3. (This corresponds to the *Info command.)
This entry point is called by RISC OS 2; otherwise it is only called if bit 2 of the extra filing system information word is set.
R0 = 7
R1 = new option (or 0)
R2 = new parameter
R6 = 0 (cannot specify a context)
--
This entry point is called by FileSwitch to set filing system options.
An option of 0 means reset all filing system options to their default values. An option of 1 is never passed to you, as FileSwitch maintains these settings. An option of 4 is used to set the boot file action. You may use other option numbers for your own purposes; please contact Acorn for an allocation.
(This corresponds to the *Opt command.)
You should return an error for bad combinations of options and parameters.
R0 = 8
R1 = pointer to pathname of object to be renamed
R2 = pointer to new pathname for object
R6 = pointer to first special field if present, otherwise 0 (FSEntry_Func 8); or image filing system's handle for image that contains file (ImageEntry_Func 8)
R7 = pointer to second special field if present, else 0 (FSEntry_Func 8 only)
R1 = 0 if rename performed (0 otherwise)
This entry point is called by FileSwitch to attempt to rename an object. If the rename is not 'simple' - ie just changing the file's catalogue entry - R1 should be returned with a value other than zero. (For example, the files may be on different images.) In such cases, FileSwitch will return a 'Bad rename' error.
R0 = 9
R1 = pointer to wildcarded pathname
R2 = pointer to access string (null, space or control-character terminated)
R6 = pointer to special field if present, otherwise 0.
--
This entry point is called by FileSwitch to give the requested access to all objects matching the wildcarded name given. (This corresponds to the *Access command.)
You should ignore inappropriate owner access bits, and try to store public access bits.
This entry point is called by RISC OS 2; otherwise it is only called if bit 18 of the filing system information word is set.
R0 = 10
--
This entry point is called by FileSwitch to request that your filing system performs its boot action.
For example, ADFS examines the boot option - as set by *Opt 4 - of the disc in the configured drive and acts accordingly (so, if boot option 2 is set, it will *Run &.!Boot); whereas NetFS attempts to logon as the boot user to the configured file server.
This call may not return if it runs an application.
R0 = 11
R2 = pointer to buffer in which to put data
R6 = 0 (cannot specify a context)
--
This entry point is called by FileSwitch to obtain the name of the disc that the CSD is on in the temporary filing system, and its boot option. This data should be returned in the area of memory pointed to by R2, in the following format:
<name length byte><disc name><boot option byte>
If there is no CSD, this call should return the string 'Unset' for the disc name, and the boot action should be set to zero.
The buffer pointed to by R2 will not have been validated with OS_ValidateAddress, because FileSwitch doesn't know how big the buffer has to be. It is the filing system's responsibility to validate any buffer that it uses, and to return an error if the memory required is not valid. Under RISC OS 2 it should use the error text 'No writable memory at this address'; under later versions it should instead look up the token BadWrt.
The buffer pointed to by R2 will not have been validated and so you should be prepared for faulting when you write to the memory. You must not put an interlock on when you are doing so.
R0 = 12
R2 = pointer to buffer in which to put data
R6 = 0 (cannot specify a context)
--
This entry point is called by FileSwitch to obtain the name of the CSD on the temporary filing system, and privilege status in relation to that directory. This data should be returned in the area of memory pointed to by R2, in the following format:
<zero byte><name length byte><current directory name><privilege byte>
If there is no CSD, this call should return the string 'Unset' for the directory name.
The privilege byte is &00 if you have 'owner' status (ie you can create and delete objects in the directory) or &FF if you have 'public' status (ie are prevented from creating and deleting objects in the directory). On FileCore-based filing systems, you always have owner status.
The buffer pointed to by R2 will not have been validated with OS_ValidateAddress, because FileSwitch doesn't know how big the buffer has to be. It is the filing system's responsibility to validate any buffer that it uses, and to return the error 'No writable memory at this address' if the memory required is not valid.
R0 = 13
R2 = pointer to buffer in which to put data
R6 = 0 (cannot specify a context)
--
This entry point is called by FileSwitch to obtain the name of the library directory on the temporary filing system, and privilege status in relation to that directory. This data should be returned in the area of memory pointed to by R2, in the following format:
<zero byte><name length byte><library directory name><privilege byte>
If no library is selected, this call should return the string 'Unset' for the library directory name.
The buffer pointed to by R2 will not have been validated with OS_ValidateAddress, because FileSwitch doesn't know how big the buffer has to be. It is the filing system's responsibility to validate any buffer that it uses, and to return the error 'No writable memory at this address' if the memory required is not valid.
This entry point is only called by RISC OS 2.
R0 = 14
R1 = pointer to wildcarded directory name
R2 = pointer to buffer in which to put data
R3 = number of object names to read
R4 = offset of first item to read in directory (0 for start of directory)
R5 = length of buffer
R6 = pointer to special field if present, otherwise 0 (FSEntry_Func 14); or image filing system's handle for image that contains file (ImageEntry_Func 14)
R3 = number of names read
R4 = offset of next item to read in directory (-1 if end)
This entry point is called by FileSwitch to read the leaf names of entries in a directory into an area of memory pointed to by R2. If the directory name is null, then for filing systems the currently-selected directory should be read; for image filing systems the root directory should be read. The names are returned in the buffer as a list of null terminated strings. You must not overflow the end of the buffer, and you must only count names that you have completely inserted.
The length of buffer that FileSwitch will have validated depends on the call that was made to it:
Unfortunately there is no way you can tell which was used. RISC OS programmers are encouraged to use the latter.
You should return an error if the object being catalogued is not found or is a file. The following are, however, all valid return values:
R0 = 15
R1 = pointer to wildcarded directory name
R2 = pointer to buffer in which to put data
R3 = number of object names to read
R4 = offset of first item to read in directory (0 for start of directory)
R5 = length of buffer
R6 = pointer to special field if present, otherwise 0 (FSEntry_Func 15); or image filing system's handle for image that contains file (ImageEntry_Func 15)
R3 = number of records read
R4 = offset of next item to read in directory (-1 if end)
This entry point is called by FileSwitch to read the leaf names of entries (and their file information) in the given directory into a buffer pointed to by R2. If the directory name is null, then the currently-selected directory should be read. The names and information are returned in records, with the following format:
Offset | Contents |
---|---|
&00 | Load address |
&04 | Execution address |
&08 | Length |
&0C | Attributes |
&10 | Object type |
&14 | Object name |
FileSwitch will have validated the buffer. You must not overflow the end of the buffer, and you must only count names that you have completely inserted. You should assume that the buffer is word-aligned, and your records should be so too. You may find this code fragment useful to do so:
ADD r2, r2, #p2-1 ; p2 is a power-of-two, in this case 4 BIC r2, r2, #p2-1
You should return an error if the object being catalogued is not found or is a file.
R0 = 16
--
This entry point is called by FileSwitch to request that your filing system go into as dormant a state as possible. For example, it should place hard drives in their transit positions, etc. All files will have been closed by FileSwitch before this call is issued.
R0 = 17
R6 = 0 (cannot specify a context)
--
This entry point is called by FileSwitch to print out a filing system banner that shows which filing system is selected. FileSwitch calls it if it receives a reset service call and the text offset value (in the filing system information block) is -1. This is to allow filing systems to print a message that may vary, such as Acorn Econet or Acorn Econet no clock.
You should print the string using XOS_... SWIs, and if there is an error return with V set and R0 pointing to an error block. This is not likely to happen.
This entry point is never called by FileSwitch.
R0 = 19
R1 = pointer to wildcarded directory name
R2 = pointer to buffer in which to put data
R3 = number of object names to read
R4 = offset of first item to read in directory
R5 = length of buffer
R6 = pointer to special field if present, otherwise 0
R3 = number of records read
R4 = offset of next item to read in directory (-1 if end)
This entry point is called by FileSwitch to read the names of entries (and their file information) in the given directory into a buffer pointed to by R2. If the directory name is null, then the currently-selected directory should be read. The names and information are returned in records, with the following format:
Each record is word-aligned.
R0 = 20
R1 = pointer to pathname (may be wildcarded under RISC OS 2 only)
R6 = pointer to special field if present, otherwise 0
--
This entry point is called by FileSwitch to request that your filing system outputs full information on the given object (or, under RISC OS 2, on all the objects matching the wildcarded pathname). The format must be the same as for the *FileInfo command.
It is only called by FileSwitch if bit 25 of the filing system information word was set when the filing system was initialised. Otherwise FileSwitch will use calls to FSEntry_Func 6 to implement *FileInfo.
R0 = 21
R1 = FileSwitch handle to the file
R2 = buffer size for file if known, otherwise 0
R1 = image filing system's handle for image
This entry point is called by FileSwitch to notify your image filing system that FileSwitch would like it to handle a new image. This entry gives the image filing system a chance to set up internal structures so that data could be cached or buffered from the image. All future requests FileSwitch makes of the image filing system will quote the returned image filing system's handle for the image when appropriate.
The image should be flagged internally as 'stamp image on next update', and when it is updated its unique identification number should be updated. Whenever this number is updated the host filing system should be informed of its new value using OS_Args 8 - this is important, because otherwise the host filing system will lose track of which disc is which.
The buffer size (if given) should be treated as a hint to the sector size.
R0 = 22
R1 = image filing system's handle for image
--
This entry point is called by FileSwitch to notify your image filing system that an image is about to be closed. All files will have been closed for you before this call is made. You should save any buffered data for this image before returning, and discard any cached data.
This entry point is not called by RISC OS 2.
R0 = 23
R1 = pointer to special field if present, otherwise 0
R2 = pointer to disc name if present, otherwise 0
R3 = pointer to buffer to hold canonical special field, or 0 to return required length
R4 = pointer to buffer to hold canonical disc name, or 0 to return required length
R5 = length of buffer to hold canonical special field
R6 = length of buffer to hold canonical disc name
R1 = pointer to canonical special field if present, otherwise 0
R2 = pointer to canonical disc name if present, otherwise 0
R3 = bytes overflow from special field buffer (ie required length if R3 = 0 on entry)
R4 = bytes overflow from special field buffer (ie required length if R4 = 0 on entry)
R5, R6 preserved
This entry point is called by FileSwitch to convert the given special field and disc name to canonical (unique) forms. If no buffers are passed to hold the results, this call instead returns their required lengths, which gives FileSwitch a means of finding out this information.
FileSwitch uses this call to convert user-specified special field and disc names into a canonical (unique) form. Typically this call is used in two stages: the first to find out how much space is required in the buffers, and the second to do the conversion. For example, if a user specifies a file as NetFS#Arf:&.thing.whatsit, FileSwitch uses this call as follows:
R1 = pointer to the string 'Arf'
R2 = 0
R3 = 0
R4 = 0
R5 = any value (since R3 = 0)
R6 = any value (since R4 = 0)
NetFS returns these values:
R1 = any non-zero value
R2 = any non-zero value
R3 = required length of buffer to hold canonical special field (excluding any terminating null)
R4 = required length of buffer to hold canonical disc name (excluding any terminating null)
R5, R6 preserved
FileSwitch now allocates memory for two buffers of the lengths specified by NetFS in the R3 and R4 return values, then call NetFS again as follows:
R1 = pointer to the string 'Arf'
R2 = 0
R3 = pointer to a buffer of length R5 bytes
R4 = pointer to a buffer of length R6 bytes
R5 = length of buffer pointed to by R3
R6 = length of buffer pointed to by R4
NetFS now fills in the buffers: (R3,R5) with the special field, and (R4,R6) with the disc name. It returns:
R1 = R3 on entry (and the buffer is filled with '49.254')
R2 = R4 on entry (and the buffer is filled in with 'Arf')
R3, R4 = 0 (no overflows over the end of the buffers)
R5, R6 preserved
This entry point is not called by RISC OS 2, and is only otherwise called if bit 23 of the filing system information word is set.
R1 = pointer to directory pathname
R2 = pointer to buffer to hold resolved name, or 0 if none
R3 = pointer to wildcarded object name
R5 = length of buffer
R6 = pointer to special field if present, otherwise 0
R1 preserved
R2 = -1 if not found, else preserved
R3 preserved
R4 = -1 if FileSwitch should resolve this wildcard itself, else bytes overflow from buffer
R5 preserved
This entry point is called by FileSwitch to find which object in the given directory matches the name given. If the filing system can not do a more efficient job than FileSwitch would if it were to use FSEntry_Func 14 and then to find which was the first match, then the filing system should just return with R4 = -1.
This entry point is not called by RISC OS 2, and is only otherwise called if bit 23 of the filing system information word is set.
R0 = 25
R1 = pointer to name of image (FSEntry_Func 25 only)
R2 = pointer to buffer
R5 = length of buffer
R6 = pointer to special field if present, otherwise 0 (FSEntry_Func 25); or image filing system's handle for image (ImageEntry_Func 25)
R0 - R6 preserved
This entry point is called by FileSwitch to request that your filing system fills the given buffer with the byte offsets to the start of any defects in the specified image. The list must be terminated by the value &20000000.
It is an error if the specified image is not the root object in an image (eg it is an error to map out a defect from adfs::HardDisc4.$.fred, but not an error to map it out from adfs::HardDisc4.$).
This entry point is not called by RISC OS 2.
R0 = 26
R1 = pointer to name of image (FSEntry_Func 26 only)
R2 = byte offset to start of defect
R6 = pointer to special field if present, otherwise 0 (FSEntry_Func 26); or image filing system's handle for image (ImageEntry_Func 26)
R0 - R2, R6 preserved
This entry point is called by FileSwitch to request that your filing system maps out the given defect from the specified image.
It is an error if the specified image is not the root object in an image (eg it is an error to map out a defect from adfs::HardDisc4.$.fred, but not an error to map it out from adfs::HardDisc4.$). If the defect cannot be mapped out because it is not free, then you should return an error.
This entry point is not called by RISC OS 2.
R0 = 27
R1 = pointer to pathname of any object on image (FSEntry_Func 27 only)
R6 = pointer to special field if present, otherwise 0 (FSEntry_Func 27); or image filing system's handle for image (ImageEntry_Func 27)
R0, R1, R6 preserved
R2 = boot option (as in *Opt 4,n)
This entry point is called by FileSwitch to read the boot option (ie the value n in *Opt 4,n) of the image that holds the object specified by R1 (FSEntry_Func 27), or that is specified by the handle in R6 (ImageEntry_Func 27).
This entry point is not called by RISC OS 2.
R0 = 28
R1 = pointer to pathname of any object on image (FSEntry_Func 28 only)
R2 = new boot option
R6 = pointer to special field if present, otherwise 0 (FSEntry_Func 28); or image filing system's handle for image (ImageEntry_Func 28)
R0 - R2, R6 preserved
This entry point is called by FileSwitch to request that your filing system writes the boot option (ie the value n in *Opt 4,n) of the image that holds the object specified by R1 (FSEntry_Func 28), or that is specified by the handle in R6 (ImageEntry_Func 28).
R0 = 29
R1 = pointer to pathname of any object on image (FSEntry_Func 29 only)
R2 = pointer to buffer for map (pre-filled with 0s)
R5 = size of buffer
R6 = pointer to special field if present, otherwise 0 (FSEntry_Func 29); or image filing system's handle for image (ImageEntry_Func 29)
R0 - R2, R5, R6 preserved
This entry point is called by FileSwitch to read the used space map for the image that holds the object specified by R1 (FSEntry_Func 29), or that is specified by the handle in R6 (ImageEntry_Func 29). It is used by the *Backup command to decide which sectors to copy.
Your filing system should fill the given buffer with 0 bits for unused blocks, and 1 bits for used blocks. The buffer must be filled to its limit, or to the image's limit, whichever is less. The 'perfect' size of the buffer can be calculated from the image's size and its block size (as returned from FSEntry_Open or ImageEntry_Open: see FSEntry_Open and ImageEntry_Open). The correspondence of the buffer to the file is 1 bit to 1 block. The least significant bit (bit 0) in a byte comes before the most significant bit.
This entry point is not called by RISC OS 2.
R0 = 30
R1 = pointer to pathname of any object on image (FSEntry_Func 30 only)
R6 = pointer to special field if present, otherwise 0 (FSEntry_Func 30); or image filing system's handle for image (ImageEntry_Func 30)
R0 = free space
R1 = biggest object creatable
R2 = disc size
This entry point is called by FileSwitch to read the free space for the image that holds the object specified by R1 (FSEntry_Func 30), or that is specified by the handle in R6 (ImageEntry_Func 30).
R0 = 31
R1 = pointer to pathname of any object on image (FSEntry_Func 31 only)
R2 = pointer to new name of image
R6 = pointer to special field if present, otherwise 0 (FSEntry_Func 31); or image filing system's handle for image (ImageEntry_Func 31)
Registers preserved
This entry point is called by FileSwitch to request that your filing system name the image that holds the object specified by R1 (FSEntry_Func 31), or that is specified by the handle in R6 (ImageEntry_Func 31).
This refers to the image's name (eg a disc name), rather than the name of the file containing that image.
This entry point is not called by RISC OS 2.
R0 = 32
R1 = pointer to pathname of any object on image (FSEntry_Func 32 only)
R2 = reason code
R6 = pointer to special field if present, otherwise 0 (FSEntry_Func 32); or image filing system's handle for image (ImageEntry_Func 32)
Registers preserved
This entry point is called by FileSwitch to request that your filing system stamp the image that holds the object specified by R1 (FSEntry_Func 32), or that is specified by the handle in R6 (ImageEntry_Func 32). It is used for FileCore to communicate with an image filing system for the control and management of the disc Id of a given image. Valid values for R2 on entry are:
Value | Meaning |
---|---|
0 | stamp image on next update |
1 | stamp image now |
To stamp an image the image's unique identification number should be updated to a different value. This value is used to distinguish between different images with the same name, and to determine when a given image has been updated. It should be filled in the disc record disc id field when the disc is originally identified. The kind of uses expected for these calls are:
and, for ImageEntry_Func 32 only, the following two uses:
R0 = 33
R1 = pointer to pathname of any object on image (FSEntry_Func 33 only)
R2 = byte offset into image
R3 = pointer to buffer to receive object name (if object found)
R4 = length of buffer
R6 = pointer to special field if present, otherwise 0 (FSEntry_Func 33); or image filing system's handle for image (ImageEntry_Func 33)
R2 = kind of object found at offset:
This entry point is called by FileSwitch to find the usage of the given offset within the image that holds the object specified by R1 (FSEntry_Func 33), or that is specified by the handle in R6 (ImageEntry_Func 33). If the offset is free, a defect or outside the image then you should return with R2 = 0. If the offset is used, but has no object name which corresponds to it (for example the free space map, FAT tables, boot block and the such), then return with R2 = 1. If the given offset is associated with only one object (such that deleting that object would definitely free the given offset), then you should return with R2 = 2. If the offset is associated with several objects (files/directories), but cannot be said to be associated with one only (for example, the disc may have one large section allocated which is used by several files within one directory), then return with R2 = 3.
You may corrupt the buffer during the search and, if you find an object (ie R2 = 2 or 3), you should return its pathname in the buffer. The pathname should not have a '$' prefix, but the first path element should have a '.' prefix, eg:
.a.b.c.d
rather than:
a.b.c.d
R1 = pointer to null-terminated directory name
R2 = changed directory (0 CSD_ 1 PSD_ 2 URD_ 3 Lib)
R6 = pointer to special field if present, otherwise 0
R1, R2, R6 preserved
This entry point is provided so that filing systems can optimise their handling of directory caches. It is called when FileSwitch has successfully changed a directory, as indicated by R2.There is no reason for a filing system to have these directories stored, but even if it does it should not change its record of the directory; instead it should use this information to help it decide which directories to cache, and which not to.
This entry point is used to implement multiple get byte and put byte operations on unbuffered files. It is only ever called if you set bit 28 of the file information word on return from FSEntry_Open, and you need not otherwise provide it. FileSwitch will instead use multiple calls to FSEntry_PutBytes and FSEntry_GetBytes to implement these operations.
R0 = 1 or 2
R1 = file handle used by your filing system
R2 = pointer to buffer
R3 = number of bytes to put to file
If R0 = 1
R0, R1 preserved
R2 = address of byte after the last one transferred from buffer
R3 = number of bytes not transferred
R4 = initial file pointer + number of bytes transferred
This entry point is called by FileSwitch to request that your filing system transfer data from memory to the file at either the specified file pointer (R0 = 1), or the current one (R0 = 2). If the specified pointer is beyond the end of the file, then you must fill the file with zeros between the current file extent and the specified pointer before the bytes are transferred.
The file handle is guaranteed by FileSwitch not to be a directory, and to have had write access granted at the time of the open.
R0 = 3 or 4
R1 = file handle used by your filing system
R2 = pointer to buffer
R3 = number of bytes to get from file
If R0 = 3
R0, R1 preserved
R2 = address of byte after the last one transferred to buffer
R3 = number of bytes not transferred
R4 = initial file pointer + number of bytes transferred
This entry point is called by FileSwitch to request that your filing system transfer data from a file to memory, either from the specified file pointer (R0 = 3), or from the current one (R0 = 4).
If the specified pointer is greater than or equal to the current file extent then you must not update the sequential file pointer, nor must you return an error.
The file handle is guaranteed by FileSwitch not to be a directory and to have had read access granted at the time of the open.
Your filing system must not try to keep its own EOF-error-on-next-read flag - instead it is FileSwitch's responsibility to keep the EOF-error-on-next-read flag. Unlike FSEntry_GetBytes, FileSwitch will set the C bit before it returns to its caller if your filing system returns a non-zero value in R3 - so your filing system need not handle this either.
This code fragment is an optimised routine for moving blocks of memory. It could be further enhanced to take advantage of the higher speed of memory access given by the MEMC chip if LDM and STM instructions are quad-word aligned. You should find this useful when writing your own filing systems, as efficient transfer code is crucial to the performance of a filing system.
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; MoveBytes(source, dest, size in bytes) - fast data copier from RCM ; ========= ; SKS Reordered registers and order of copying to suit FileSwitch ; **Not yet optimised to do transfers to make most of 1N,3S feature of MEMC** ; extern void MoveBytes(void *source, void *destination, size_t count); ; In: r1 = src^ (byte address) ; r2 = dst^ (byte address) ; r3 = count (byte count - never zero!) ; Out: r0-r3, lr corrupt. Flags preserved mbsrc1 RN 0 mbsrcptr RN 1 mbdstptr RN 2 mbcnt RN 3 mbsrc2 RN 14 ; Note deviancy, so care in LDM/STM mbsrc3 RN 4 mbsrc4 RN 5 mbsrc5 RN 6 mbsrc6 RN 7 mbsrc7 RN 8 mbsrc8 RN 9 mbsrc9 RN 10 mbshftL RN 11 ; These two go at end to save a word mbshftR RN 12 ; and an extra Pull lr! sp RN 13 lr RN 14 pc RN 15 MoveBytes ROUT STMDB sp!, {lr} TST mbdstptr, #3 BNE MovByt100 ; [dst^ not word aligned] MovByt20 ; dst^ now word aligned. ; branched back to from below TST mbsrcptr, #3 BNE MovByt200 ; [src^ not word aligned] ; src^ & dst^ are now both word aligned ; count is a byte value (may not be a whole number of words) ; Quick sort out of what we've got left to do SUBS mbcnt, mbcnt, #4*4 ; Four whole words to do (or more) ? BLT MovByt40 ; [no] SUBS mbcnt, mbcnt, #8*4-4*4 ; Eight whole words to do (or more) ? BLT MovByt30 ; [no] STMDB sp!, {mbsrc3-mbsrc8} ; Push some more registers MovByt25 LDMIA mbsrcptr!, {mbsrc1, mbsrc3-mbsrc8, mbsrc2} ; NB. Order! STMIA mbdstptr!, {mbsrc1, mbsrc3-mbsrc8, mbsrc2} SUBS mbcnt, mbcnt, #8*4 BGE MovByt25 ; [do another 8 words] CMP mbcnt, #-8*4 ; Quick test rather than chaining down LDMEQDB sp!, {mbsrc3-mbsrc8, pc}^ ; [finished] LDMDB sp!, {mbsrc3-mbsrc8} MovByt30 ADDS mbcnt, mbcnt, #8*4-4*4 ; Four whole words to do ? BLT MovByt40 STMDB sp!, {mbsrc3-mbsrc4} ; Push some more registers LDMIA mbsrcptr!, {mbsrc1, mbsrc3-mbsrc4, mbsrc2} ; NB. Order! STMIA mbdstptr!, {mbsrc1, mbsrc3-mbsrc4, mbsrc2} LDMEQDB sp!, {mbsrc3-mbsrc4, pc}^ ; [finished] LDMDB sp!, {mbsrc3-mbsrc4} SUB mbcnt, mbcnt, #4*4 MovByt40 ADDS mbcnt, mbcnt, #4*4-2*4 ; Two whole words to do ? BLT MovByt50 LDMIA mbsrcptr!, {mbsrc1, mbsrc2} STMIA mbdstptr!, {mbsrc1, mbsrc2} LDMEQDB sp!, {pc}^ ; [finished] SUB mbcnt, mbcnt, #2*4 MovByt50 ADDS mbcnt, mbcnt, #2*4-1*4 ; One whole word to do ? BLT MovByt60 LDR mbsrc1, [mbsrcptr], #4 STR mbsrc1, [mbdstptr], #4 LDMEQDB sp!, {pc}^ ; [finished] SUB mbcnt, mbcnt, #1*4 MovByt60 ADDS mbcnt, mbcnt, #1*4-0*4 ; No more to do ? LDMEQDB sp!, {pc}^ ; [finished] LDR mbsrc1, [mbsrcptr] ; Store remaining 1, 2 or 3 bytes MovByt70 STRB mbsrc1, [mbdstptr], #1 MOV mbsrc1, mbsrc1, LSR #8 SUBS mbcnt, mbcnt, #1 BGT MovByt70 LDMDB sp!, {pc}^ ; [finished] ; Initial dest^ not word aligned. Loop doing bytes (1,2 or 3) until it is MovByt100 LDRB mbsrc1, [mbsrcptr], #1 STRB mbsrc1, [mbdstptr], #1 SUBS mbcnt, mbcnt, #1 LDMEQDB sp!, {pc}^ ; [finished after 1..3 bytes] TST mbdstptr, #3 BNE MovByt100 B MovByt20 ; Back to mainline code MovByt200 ; dst^ now word aligned, but src^ isn't. just lr stacked here STMDB sp!, {mbshftL, mbshftR} ; Need more registers this section AND mbshftR, mbsrcptr, #3 ; Offset BIC mbsrcptr, mbsrcptr, #3 ; Align src^ MOV mbshftR, mbshftR, LSL #3 ; rshft = 0, 8, 16 or 24 only RSB mbshftL, mbshftR, #32 ; lshft = 32, 24, 16 or 8 only LDR mbsrc1, [mbsrcptr], #4 MOV mbsrc1, mbsrc1, LSR mbshftR ; Always have mbsrc1 prepared ; Quick sort out of what we've got left to do SUBS mbcnt, mbcnt, #4*4 ; Four whole words to do (or more) ? BLT MovByt240 ; [no] SUBS mbcnt, mbcnt, #8*4-4*4 ; Eight whole words to do (or more) ? BLT MovByt230 ; [no] STMDB sp!, {mbsrc3-mbsrc9} ; Push some more registers MovByt225 LDMIA mbsrcptr!, {mbsrc3-mbsrc9, mbsrc2} ; NB. Order! ORR mbsrc1, mbsrc1, mbsrc3, LSL mbshftL MOV mbsrc3, mbsrc3, LSR mbshftR ORR mbsrc3, mbsrc3, mbsrc4, LSL mbshftL MOV mbsrc4, mbsrc4, LSR mbshftR ORR mbsrc4, mbsrc4, mbsrc5, LSL mbshftL MOV mbsrc5, mbsrc5, LSR mbshftR ORR mbsrc5, mbsrc5, mbsrc6, LSL mbshftL MOV mbsrc6, mbsrc6, LSR mbshftR ORR mbsrc6, mbsrc6, mbsrc7, LSL mbshftL MOV mbsrc7, mbsrc7, LSR mbshftR ORR mbsrc7, mbsrc7, mbsrc8, LSL mbshftL MOV mbsrc8, mbsrc8, LSR mbshftR ORR mbsrc8, mbsrc8, mbsrc9, LSL mbshftL MOV mbsrc9, mbsrc9, LSR mbshftR ORR mbsrc9, mbsrc9, mbsrc2, LSL mbshftL STMIA mbdstptr!, {mbsrc1, mbsrc3-mbsrc9} MOV mbsrc1, mbsrc2, LSR mbshftR ; Keep mbsrc1 prepared SUBS mbcnt, mbcnt, #8*4 BGE MovByt225 ; [do another 8 words] CMP mbcnt, #-8*4 ; Quick test rather than chaining down LDMEQDB sp!, {mbsrc3-mbsrc9, mbshftL, mbshftR, pc}^ ; [finished] LDMDB sp!, {mbsrc3-mbsrc9} MovByt230 ADDS mbcnt, mbcnt, #8*4-4*4 ; Four whole words to do ? BLT MovByt240 STMDB sp!, {mbsrc3-mbsrc5} ; Push some more registers LDMIA mbsrcptr!, {mbsrc3-mbsrc5, mbsrc2} ; NB. Order! ORR mbsrc1, mbsrc1, mbsrc3, LSL mbshftL MOV mbsrc3, mbsrc3, LSR mbshftR ORR mbsrc3, mbsrc3, mbsrc4, LSL mbshftL MOV mbsrc4, mbsrc4, LSR mbshftR ORR mbsrc4, mbsrc4, mbsrc5, LSL mbshftL MOV mbsrc5, mbsrc5, LSR mbshftR ORR mbsrc5, mbsrc5, mbsrc2, LSL mbshftL STMIA mbdstptr!, {mbsrc1, mbsrc3-mbsrc5} LDMEQDB sp!, {mbsrc3-mbsrc5, mbshftL, mbshftR, pc}^ ; [finished] LDMDB sp!, {mbsrc3-mbsrc5} SUB mbcnt, mbcnt, #4*4 MOV mbsrc1, mbsrc2, LSR mbshftR ; Keep mbsrc1 prepared MovByt240 ADDS mbcnt, mbcnt, #2*4 ; Two whole words to do ? BLT MovByt250 STMDB sp!, {mbsrc3} ; Push another register LDMIA mbsrcptr!, {mbsrc3, mbsrc2} ; NB. Order! ORR mbsrc1, mbsrc1, mbsrc3, LSL mbshftL MOV mbsrc3, mbsrc3, LSR mbshftR ORR mbsrc3, mbsrc3, mbsrc2, LSL mbshftL STMIA mbdstptr!, {mbsrc1, mbsrc3} LDMEQDB sp!, {mbsrc3, mbshftL, mbshftR, pc}^ ; [finished] LDMDB sp!, {mbsrc3} SUB mbcnt, mbcnt, #2*4 MOV mbsrc1, mbsrc2, LSR mbshftR ; Keep mbsrc1 prepared MovByt250 ADDS mbcnt, mbcnt, #2*4-1*4 ; One whole word to do ? BLT MovByt260 LDR mbsrc2, [mbsrcptr], #4 ORR mbsrc1, mbsrc1, mbsrc2, LSL mbshftL STR mbsrc1, [mbdstptr], #4 LDMEQDB sp!, {mbshftL, mbshftR, pc}^ ; [finished] SUB mbcnt, mbcnt, #1*4 MOV mbsrc1, mbsrc2, LSR mbshftR ; Keep mbsrc1 prepared MovByt260 ADDS mbcnt, mbcnt, #1*4-0*4 LDMEQDB sp!, {mbshftL, mbshftR, pc}^ ; [finished] LDR mbsrc2, [mbsrcptr] ; Store remaining 1, 2 or 3 bytes ORR mbsrc1, mbsrc1, mbsrc2, LSL mbshftL MovByt270 STRB mbsrc1, [mbdstptr], #1 MOV mbsrc1, mbsrc1, LSR #8 SUBS mbcnt, mbcnt, #1 BGT MovByt270 LDMDB sp!, {mbshftL, mbshftR, pc}^ ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ END