Commit 708e0ddb authored by Neil Turton's avatar Neil Turton
Browse files

Import from cleaned 360 CD

hdr/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
s/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
**/s/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
*,ffb gitlab-language=bbcbasic linguist-language=bbcbasic linguist-detectable=true
**/c/** gitlab-language=c linguist-language=c linguist-detectable=true
**/h/** gitlab-language=c linguist-language=c linguist-detectable=true
diff -r -d ADFS::HardDisc4.$.aideen.Builds.Latest.Sources.OS_Core.FileSys.FileCore.Resources.UK.Messages RAM::RamDisc0.$.filecor290.Resources.UK.Messages
> FileTooBig:File too big
Only in RAM::RamDisc0.$.filecor290.rm: FileCore
Only in RAM::RamDisc0.$.filecor290.rm: FileCoreO
diff -r -d ADFS::HardDisc4.$.aideen.Builds.Latest.Sources.OS_Core.FileSys.FileCore.s.Errors RAM::RamDisc0.$.filecor290.s.Errors
> E1 error FileTooBig, File too big
diff -r -d ADFS::HardDisc4.$.aideen.Builds.Latest.Sources.OS_Core.FileSys.FileCore.s.FileCore20 RAM::RamDisc0.$.filecor290.s.FileCore20
< BNE %F50
> BNE %FT50
diff -r -d ADFS::HardDisc4.$.aideen.Builds.Latest.Sources.OS_Core.FileSys.FileCore.s.FileCore35 RAM::RamDisc0.$.filecor290.s.FileCore35
< [ T ; is this the cause of our problems?
> [ F ; is this the cause of our problems?
< BICEQS LR, R1, #7 ; check that drive valid
> ; BICEQS LR, R1, #7 ; check that drive valid
This document has the following sections:
1) contents of source files
2) use of workspace
3) conventions
4) debugging
1) contents of source files
FileCore GETs all the source files
Version Version, date, and highest fix number to be applied
Fixes documents and sets switches for fixes since image became stable
AsmHdr more switches
DevVersion declares development version number for test versions, incremented
with each assembly and GETs system header files
DebugOpts Declares T and F and sets the debugging options
MyMacros Macros not in Hdr:Macros
CoreHdr Exported FileCore values
Defns Definitions of constants
FileCore00 Start of module, allocates workspace, and GETs Errors
Errors declares error numbers and builds error table
FileCore05 useful subroutines
FileCore15 interfaces to low level disc op at various abstraction levels
FileCore20 routines maintaining disc <-> drive mapping
FileCore25 directory caching
FileCore30 more useful subroutines, including interfaces to rest of system
FileCore31 new map allocation
FileCore32 new map zone compaction
FileCore33 new map primitives
FileCore35 old free space map operations
FileCore40 filename and directory operations
FileCore45 OSFILE and map/directory writing to disc
TekneHelp Tokenised help from HelpText
FileCore50 module interfaces and * commands
FileCore60 OSFUN
FileCore70 open files
FileCore80 new open file write behind/read ahead/caching
2) use of workspace
main module workspace
| misc. | Dir | Directory cache : open file | free | winnie
| work | Buffer | : file buffer cache | space | defect
| space | | : | maps | lists
^0 ^ FileBufsStart ^MapSpace ^DefectSpace
The size of the directory cach, file buffer cache, and hard disc maps are
kept in CMOS RAM. The hard disc maps are claimed in separate blocks from the
RMA so that if the value in CMOS RAM is wrong (due to reformatting or
connecting a different drive) the blocks can be returned and ones of the
correct size claimed. The file buffers are held after the file is closed and
are only thrown away when needed for other files, or when the directory
cache is allowed to temporarily expand into the file buffer cache.
The miscellaneous workspace contains various byte and word variables and
records such as the disc and drive records.
3) conventions
a) The routines are mostly callee save ie registers not explicitly returning
a result are preserved. Many subroutine calls document the registers
expected for parameters and results eg.
BL FullLookUp ;(R1,R2->R0-R6,C,V)
means that R1 and R2 are parameters and that R0 to R6 are modified by the
call. Flags are listed in the result if they have significant meaning after
the call and it cannot be assumed that other flags are preserved.
b) The variable ReEntrance keeps track of the levels of nesting of calls.
This is used to detect illegal reentrance and must be modified appropriately
by all entry and exit points. Suitable macros and routines are declared in
c) errors are kept in a different format internally - see Errors
d) disc addresses are kept in three forms for different levels of
abstraction. In each case the top 3 bits indicate the device and the other
29 bits define the position on the device.
external disc address - This is the form used to communicate with the
external device drivers and when calling RetryDriveOp. The top 3 bits is
the drive number and the bottom 29 bits is an offset in bytes from the
beginning of the disc.
disc address - This is the next level up where discs are abstracted from
drives and is used when calling RetryDiscOp. The top 3 bits is the disc
number and the bottom 29 bits is an offset in bytes from the beginning of
the disc.
indirect disc address - This is the top level and is used in new map discs
to abstract the SIN (system internal number) of a file from its allocation
on the disc. On old map discs it is exactly the same as a disc address. On
new map discs the top 3 bits are still the disc number. However bits 8-23 is a file id which can be looked up in the map and bits 0-7 are 0 for a file
which does not share a map chunk or the sector offset + 1 in the map chunk
if it does.
4) Debugging
FileCore00 contains various switches which can be turned on to aid debugging.
Some of the more specialised are:
ExceptionTrap - To ensure the FIRST exception is trapped
VduTrap - To redirect debugging text in a circular fashion into the memory
reserved for RAMFS. For time critical debugging.
SpoolOff - To turn spooling off for debugging text to prevent illegal reentry
IrqDebug - To disable debugging while IrqSema set to avoid being swamped by
background scheduling debugging.
DebugSwitch - For all debugging to be conditional on the contents of a
memory location to allow debugging to be turned on and off
during a test.
The exec file to produce a Filecore 2.00 as used in RISC OS 2.00 is Make_2,00.
The object produced is called Obj.
Version specific filenames are of the following type.
Make_v,vv is the make file which produces Obj
Hdr_v,vv sets the options for the assembly
Obj_v,vv is an copy of the object that should be produced. A binary comparison
of Obj with this file is done except for test versions.
v,vv is the version number or Test for a test version
These are my general notes on ADFSBuffers support (FileCore80) as I attempt to
understand the code within (here be demons!). I intend to list every ADFSBuffers
function that I examine here along with what changes are required. I'll also list
those functions which I consider to not need updating at all. I'll also generate
some notes of general ADFSBuffers working. Hopefully this documentation should be
useful to others in the future.
Each buffer is a 1K buffer. It can however be considered
as two sub-buffers of 512 bytes or four sub-buffers of
256 bytes.
Each 'process' contains a process block which tells us what this
process is actually doing. Tacked onto the end of the process is
a scatter list - everyone likes scatter lists don't they? Luckily
for us, pair extension is disabled. That is, the scatter list never
gets extended just when the driver least expects it, as it causes
all sorts of headaches - allegedly, of course.
Process Scatter Lists
------- ------- -----
As mentioned above, the process scatter lists cannot be extended
by adding more pairs. Indeed, enough pairs must be available
in each process to satisfy the maximum number of buffers that
can be in use. Thus each process has a scatter list upto
MaxFileBuffers in length. Each scatter list entry must correspond
to either a buffer or a direct transfer. A scatter list entry
cannot cover multiple buffers as data for adjacent buffers in
a transfer will not conjoin. Does this apply for sub-buffers?
This seems to be an adjustment offset which would generally appear
to be added to any offset within a file to give the actual disc
address for that offset - thus DiscAdjust only remains valid
when working within a single fragment. It is added to the offset
into a file to give the disc address corresponding to that offset.
I'm thinking that DiscAdjust must be always sector aligned. If
this assumption breaks I'll have fun.
The next three sections list what needs modified.
Functions which will need modified:
--------- ----- ---- ---- --------
FileFrag ... SBP: done
BackGroundFileCacheOp ... SBP: done
GetBytesEntry ... SBP: done
PutBytesEntry ... SBP: done
BackGroundOps ... SBP: done
Functions which will not need modified:
--------- ----- ---- --- ---- --------
DefFileFrag (veneer to FileFrag)
remember you got me thinking about how to do big discs in FileCore the
other day? Well, here's the result:
Answer: Yes, probably feasible in a not unreasonable amount of time.
Two parts to change here:
* The map format needs adjusting to cope better with monster discs. The
limiting factor in the map is the header field which gives the
link to the first free fragment in a zone. This is currently 2
bytes big which limits the disc to being divided into 32766
pieces. On a 4G disc this will give 128K byte directories! This is
silly. There's three approaches to sorting this out: stretch the
field to 4 bytes; deal with the 2-byte first free link specially;
free links are 15 bits or LinkBits (a field in the disc record)
long, whichever is the shorter. All of these are practical and
reasonable - it just needs a day or so of analysis to choose which
is best. Instant analysis gives: new disc format - awkward; special
case at start of free lists - awkward; doesn't seem to have obvious
problems. Once the limit has been removed discs can be divided into
more parts and so are somewhat more sensible. Unfortunately, this
means monster maps too:
LinkBits Max Map Size Disc Size
15 ~64K ~512M (dirs 16K)
16 ~136K ~1G (dirs 17K)
17 ~288K ~2G (dirs 18K)
18 ~608K ~4G (dirs 19K)
19 ~1280K ~8G (dirs 20K)
Note the map size approximate values are low by about 1%.
Each halving of the directory size takes you into the next higher
map size.
* The conversion from indirect disc addresses (Object ID,offest) to
direct disc addresses (disc offset) needs to convert to sector
offsets instead. Indeed, FileCore will always deal with sector
offsets internally and will convert to these when a DiscOp is given
and from these if the low level filing system can't cope with sector
offsets. An analysis is given below of the impact of such a change.
I'd definitely do and finish the first change before the second because it
gives some benefits early (smaller directories) and has less of a global
impact throughout FileCore.
Convert FileCore to big discs:
Externally the world sees big files (up to 4GBytes) and a new low level API
where a filing system (eg SCSIFS) can request to be given sector numbers,
not byte numbers as disc addresses. On these filing systems FileCore_DiscOp
will reject non-sector aligned requests with non-sector transfer amounts.
Internally IndDisc addresses are still passed around with offsets, but get
converted to sector addresses before DiscOp is called.
bit use
0-7 sector offset within shared object (usually 0)
8-28 Object ID (21 bits)
29-31 disc number
Routines to be changed (Files with routines listed have been analysed, those
without haven't):
SBP: Those files marked with * haven't been *fully* analysed and thus
more work will be needed on determining what requires changing. Also
note that I've found routines which aren't mentioned below which I've
found need changed.
DoDefect - convert ... SBP: done
DoDefectMapOut - convert ... SBP: done
DismountDisc - convert ... SBP: done
DoVerify - convert ... SBP: done
DoBackup - convert ... SBP: done
DoMap - covnert ... SBP: done - but need to widen field?
DoCheckMap - convert ... SBP: done
GenIndDiscOp - convert to sector shifted ... SBP: done
RetryDriveOp - convert to sector shifted scheme ... SBP: done
DoCachedReadSecs - convert (yuck!) ... SBP: done
DoCachedReadSector - convert (yuck!) ... SBP: done
ReadFsMap - convert ... SBP: done
MoveData - convert to shifted quantities ... SBP: done
FindErrBlock - generate error properly ... SBP: done
NewRandomClaim - convert to shifted form ... SBP: done
DoCompMoves - convert to shifted form ... SBP: simple vsn
FindFileFragment - Add offset shifted by sector size ... SBP: done
MapDiscApp - work in sector shifted quantities ... SBP: done
MapPtrToDiscAdd - work in sector shifted quantities ... SBP: done
DiscAddToMapPtr - work in sector shifted quantities ... SBP: done
CriticalWriteFsMap - switch to shifted ... SBP: done
FileFrag ... SBP: done
BackGroundFileCacheOp ... SBP: done
GetBytesEntry ... SBP: done (but buggy)
PutBytesEntry ... SBP: done
BackGroundOps ... SBP: done
DoSwiDiscOp ... SBP: done
add DoSwiSectorDiscOp ... SBP: done
DoSwiFloppyStructure ... SBP: done
SanityCheckBadBlockList - sector shifted quantities ... SBP: done
SanityCheckEDiscRecord - alignment of transfers to
sector boundary ... SBP: done
LayoutFreeSpaceMap - sector vs byte addrs ... SBP: done
MapOutADefect - sector vs byte addrs ... SBP: done
LayoutRootDir - sector vs byte addrs ... SBP: done
DoOsFunObjectAtOffset ... SBP: done
MarkObjMappedIn ... SBP: done
Files which won't change:
SBP: Additional Comments
DoReadCachedSecs and DoCacheReadSectors are sometimes called by
FileCore (using XFileCore_DiscOp) with non-aligned disc addresses.
This behaviour will have to change with the advent of sector-based
disc addresses; all start addresses will now have to be properly
Information for file: ADFS::HardDisc4.$
Line Message
270 LDR r0, [r3,#DiscSize2]
271 STR r0, [lr,#DiscSize2]
275 LDR r0, [r3, #DiscSize]
280 LDR r1, [r3, #DiscSize2]
287 LDR r0, [r3, #DiscSize]
317 LDR r2, [r11, #SrcDiscRec + DiscSize2] ; get top 32bits of disc size
321 LDR r2, [r11, #SrcDiscRec + DiscSize] ; max
326 LDR r2, [r11, #SrcDiscRec + DiscSize] ; max
344 LDR r3, [r11, #SrcDiscRec + DiscSize]
347 LDR r5, [r11, #SrcDiscRec + DiscSize2]
351 LDR r3, [r11, #SrcDiscRec + DiscSize]
606 LDR r6, [r5, #DiscSize]
609 LDR r7, [r5,#DiscSize2]
613 LDR r6, [r5, #DiscSize]
1334 ; above loading of DiscSize.
1351 LDR LR, [R10, #ZoneHead+DiscSize]
1353 LDR LR, [R10, #ZoneHead+DiscSize2]
1368 LDRVC r2, [r10, #ZoneHead+DiscSize] ; bound above by DiscSize-1
1414 LDR R2, [R10,#ZoneHead+DiscSize]
2224 LDR LR, [R5, #DiscSize2]
2227 LDR LR, [R5, #DiscSize]
2638 LDR R0, [LR, #DiscSize2] ; get discsize2
2640 LDREQ R0, [LR, #DiscSize]
3159 LDR R2, [LR, #DiscSize2] ;
3207 LDR R1, [R10, #ZoneHead+DiscSize2] ; discsize2 field
Information for file: ADFS::HardDisc4.$
Line Message
89 DiscSize aw 4
106 DiscSize2 aw 4 ; top 32bits of the disc size. This combines with
107 ; DiscSize to give the full size of the disc. Note
229 PrevFormDiscSize aw 4 ; DiscSize in previous format operation
231 PrevFormDiscSize2 aw 4 ; 2nd part of DiscSize in previous format operation
Information for file: ADFS::HardDisc4.$
Line Message
794 LDR lr, [r5, #DiscSize]
795 STR lr, [r0, #PrevFormDiscSize]
797 LDR lr, [r5, #DiscSize2]
798 STR lr, [r0, #PrevFormDiscSize2]
873 LDR LR, [R5,#DiscSize]
880 LDR R7, [R5,#DiscSize2]
1174 LDR R11, [R5, #DiscSize]
1182 LDR R12, [R5, #DiscSize2]
1188 DREG r9, "DiscSize/sectors per cylinder into DivRem = "
1550 LDR R11, [R5, #DiscSize]
1552 DREG r9, "DiscSize/bytes per cylinder into DivRem = "
Information for file: ADFS::HardDisc4.$
Line Message
225 LDRNE lr, [r4, #PrevFormDiscSize]
226 STRNE lr, [r5, #DiscSize]
228 LDRNE lr, [r4, #PrevFormDiscSize]
229 STRNE lr, [r5, #DiscSize]
256 LDR r0, [r5, #DiscSize]
257 DREG r0, " DiscSize="
308 ; DiscSize
310 ; DiscSize2
328 LDREQ r0, [r3, #DiscSize]
329 LDREQ lr, [r5, #DiscSize]
332 LDREQ r0, [r3, #DiscSize2]
333 LDREQ lr, [r5, #DiscSize2]
748 ; as a hack to try to get floppies to mount - set DiscSize2 to 0
752 STR lr, [r5,#DiscSize2]
1505 LDR r8, [r7, #PrevFormDiscSize]
1506 STR r8, [r5, #DiscSize]
1508 LDR r8, [r7, #PrevFormDiscSize2]
1509 STR r8, [r5, #DiscSize2]
1535 ; Need the defect list for heads/sectorsize/secspertrk/density/lowsector/DiscSize
1575 ; Pick up heads/sectorsize/secspertrk/density/lowsector/DiscSize from read block
1607 LDR lr, [r4, #DiscSize]
1608 STR lr, [r5, #DiscSize]
1610 LDR lr, [r4, #DiscSize2]
1614 STR lr, [r5, #DiscSize2]
1627 STR lr, [r5, #DiscSize]
1630 STR lr, [r5, #DiscSize2]
Information for file: ADFS::HardDisc4.$
Line Message
1057 LDR LR, [R1, #DiscSize]
1102 LDR LR, [R1,#DiscSize]
1139 LDR LR, [R1, #DiscSize]
1144 LDREQ R0, [R1, #DiscSize2]
1186 LDR LR, [R1,#DiscSize]
Information for file: ADFS::HardDisc4.$
Line Message
1383 LDRNE LR, [LR, #DiscSize]
Information for file: ADFS::HardDisc4.$
Line Message
1390 LDR lr, [r5, #DiscSize2]
1392 LDREQ lr, [r5, #DiscSize]
2164 LDR lr, [r5, #DiscSize2]
2168 LDR lr, [r5, #DiscSize]
2175 LDR lr, [r5, #DiscSize]
Information for file: ADFS::HardDisc4.$
Line Message
255 LDR lr, [r0,#DiscSize2]
256 STR lr, [r8,#DiscSize2]
384 STR r2, [r4, #DefectStruc + DiscSize]
388 STR r2, [r4, #DefectStruc + DiscSize2]
633 LDR r1, [r0, #DiscSize2]
634 STR r1, [r6, #DiscSize2]
658 STR r2, [r4, #ZoneHead + DiscSize]
661 STR r2, [r4, #ZoneHead + DiscSize2]
811 LDR r0, [r5, #DiscSize]
Information for file: ADFS::HardDisc4.$
Line Message
160 ; generate both parts of DiscSize
173 STR r2, [sp, #4+DiscSize2]
174 STR r1, [sp, #4+DiscSize]
185 STR r1, [sp, #DiscSize]
383 STR r1, [sp, #DiscSize]
384 STR r2, [sp, #DiscSize2]
394 STR r1, [sp, #DiscSize]
704 LDR R2, [R4, #DiscSize]
799 LDR R0, [R4, #DiscSize]
804 LDR LR, [R4, #DiscSize2]
808 LDR R0, [R4, #DiscSize]
967 ; and the DiscSize2 field
968 LDR R1, [LR, #DiscSize2]
969 STR R1, [R0, #DiscSize2]
Information for file: ADFS::HardDisc4.$
Line Message
260 STR r0, [r5, #DiscSize]
263 STR r0, [r5, #DiscSize2]
273 LDR r0, [r5, #DiscSize2]
277 LDR r0, [r5, #DiscSize]
295 LDR r0, [r5, #DiscSize2]
299 LDR r0, [r5, #DiscSize]
812 LDR r1, [sp, #DiscSize]
814 LDR r2, [sp, #DiscSize2]
820 ORR r1, r1, r2, LSL lr ; now full DiscSize in sectors in r1
824 LDR r1, [sp, #DiscSize]
867 LDR r0, [sp, #DiscSize]
868 STR r0, [r5, #DiscSize]
870 LDR r0, [sp, #DiscSize2]
871 STR r0, [r5, #DiscSize2]
1124 ASSERT DiscSize=16
1126 ASSERT DiscSize2=36
1134 ADDEQ r4,r4,#DiscSize2-DiscSize-4
1135 ADDEQ r14,r14,#DiscSize2-DiscSize-4
1141 ADDEQ r4,r4,#DiscSize2-DiscSize-4
1142 ADDEQ r14,r14,#DiscSize2-DiscSize-4
1252 STR r0, [r5, #DiscSize]
1256 STR r0, [r5, #DiscSize2]
1261 STR r0, [r5, #DiscSize]
1453 ; If End>DiscSize then puke
1504 STR r3, [r5, #DiscSize]
1507 STR r3, [r5, #DiscSize2]
BigShare changes:
Changed GenIndDiscOp to use sharing unit.
Changed NewClaimFree
Changed MeasureFileAllocSize
Changed MeasureFileAllocSize_GotMap
Defect list handling implemented up to now uses DiscSize
and DiscSize2 to determine whether to use a single or
a twin defect list. This mechanism may fail with discs
partitioned for Risc iX or other Unix systems, so from
now on will use the new BigFlag field to determine this.
Files and routines thought to need changing (list is
incomplete and may grow).
File Routine Status
s.Commands UpdateBadBlockList Done
s.FileCore60 DoOsFunDefectList64 Done
Defect list handling
------ ---- --------
To help with the handling of defect lists, we must have a method for
dealing with old discs in a backwards-compatible manner, and properly
handling new defect lists in such a way that old software will not
break. This will be done by having a second defect list after the
original defect list, which contains defects from 512M onwards, in
sector address form. The second defect list will have its own
checksum separate from that for the first defect list. The end
marker for the second defect list is &40000000 so as not to confuse
software which only knows about the first defect list. Thus, the
defect list will look like this