Commits (78)
  • Jeffrey Lee's avatar
    Merge Kernel-5_86 · 78511925
    Jeffrey Lee authored
      hdr/EtherDevice: Merge in Kernel-5_86 to keep branch up-to-date with MAIN
    Version 5.86, Tagged as 'Kernel-5_86-4_129_2_1'
  • Jeffrey Lee's avatar
    Initial SMP changes · 9944afaf
    Jeffrey Lee authored
      This commit lays some of the groundwork for SMP support within the HAL, kernel, and OS.
      Makefile, hdr/HALDevice, hdr/DBellDevice - Add definitions for a doorbell HAL device, to allow CPU cores to signal each other via interrupts
      hdr/HALEntries - Repurpose HAL_Matrix and HAL_Touchscreen entry points for new SMP-related entry points. Add a couple of IRQ-related definitions.
      hdr/KernelWS - Boost MaxInterrupts to 256
      hdr/Options - Add new SMP build switch to control whether the kernel is built in SMP-friendly mode or not. SMP-friendly kernels should still run on single-core machines, but may behave slightly differently.
      s/ARMops - Make as many ARMops SMP-safe as possible, relying on hardware support for broadcasting of cache/TLB maintenance operations
      s/ExtraSWIs - Make SMP-friendly full OS_SynchroniseCodeAreas only sync application space and the RMA (full-cache IMB not really possible with SMP)
      s/NewIRQs - Update IRQ despatcher comments to (hopefully) reflect reality
      Docs/SMP/HAL, Docs/SMP/IRQ - Add documentation covering the new HAL calls and IRQ behaviour
      Tested on Raspberry Pi 2, 3, OMAP4, iMX6
    Version 5.86, Tagged as 'Kernel-5_86-4_129_2_2'
  • Jeffrey Lee's avatar
    Add OS_Memory 19, which is intended to replace the OS_Memory 0 "make... · b47fdbb1
    Jeffrey Lee authored
    Add OS_Memory 19, which is intended to replace the OS_Memory 0 "make uncacheable" feature, when used for DMA
      Making pages uncacheable to allow them to be used with DMA can be troublesome for a number of reasons:
      * Many processors ignore cache hits for non-cacheable pages, so to avoid breaking any IRQ handlers the page table manipulation + cache maintenance must be performed with IRQs disabled, impacting the IRQ latency of the system
      * Some processors don't support LDREX/STREX to non-cacheable pages
      * In SMP setups it may be necessary to temporarily park the other cores somewhere safe, or perform some other explicit synchronisation to make sure they all have consistent views of the cache/TLB
      The above issues are most likely to cause problems when the page is shared by multiple programs; a DMA operation which targets one part of a page could impact the programs which are using the other parts.
      To combat these problems, OS_Memory 19 is being introduced, which allows DMA cache coherency/address translation to be performed without altering the attributes of the pages.
      Files changed:
      - hdr/OSMem - Add definitions for OS_Memory 19
      - s/MemInfo - Add OS_Memory 19 implementation
      Tested on Raspberry Pi 3, iMx6
    Version 5.86, Tagged as 'Kernel-5_86-4_129_2_3'
  • Jeffrey Lee's avatar
    Merge in latest changes from main branch · aa71a49c
    Jeffrey Lee authored
    Version 5.88, Tagged as 'Kernel-5_88-4_129_2_4'
  • Jeffrey Lee's avatar
    Fix global OS_SynchroniseCodeAreas. ARMop tweaks. · e6c4e3c2
    Jeffrey Lee authored
      s/ExtraSWIs - Fix global OS_SynchroniseCodeAreas using the wrong appspace size; would have resulted in appspace only being partially synced if some pages were mapped out due to lazy swapping
      s/ARMops, s/ExtraSWIs, s/MemMap2 - Simplify code by making DCache_LineLen / ICache_LineLen store the actual line length values on ARMv7+ instead of the log2 values. Optimise SMP I-cache invalidation by allowing it to do a global invalidate. Ensure all ARMv7+ range checks use LO instead of NE, to avoid any problems with mismatched I/D line lengths (can't be sure the op range was rounded to the larger of the two)
      Tested on iMX6
    Version 5.88, Tagged as 'Kernel-5_88-4_129_2_5'
  • Jeffrey Lee's avatar
    Merge latest changes from main branch · 2cc5ebc7
    Jeffrey Lee authored
    Version 5.89, Tagged as 'Kernel-5_89-4_129_2_6'
  • Jeffrey Lee's avatar
    Merge in latest changes from main branch · 521ac671
    Jeffrey Lee authored
    Version 5.97, Tagged as 'Kernel-5_97-4_129_2_7'
  • Robert Sprowson's avatar
    Back to odd numbered development · 38d3d82a
    Robert Sprowson authored
    Version 6.02. Tagged as 'Kernel-6_02'
  • Ben Avison's avatar
    Increase number of vectors supported by the kernel to 96. · b05cb85a
    Ben Avison authored
    Version 6.03. Tagged as 'Kernel-6_03'
  • Jeffrey Lee's avatar
    Disable error block validity checks · 3c60aa69
    Jeffrey Lee authored
      The error block checks introduced in Kernel-5_35-4_79_2_313 are generating a few too many false positives and edge cases, so take the safe option of just disabling them rather than trying to tweak the rules further. Error pointers will still be checked, but the content of the error blocks will not.
      hdr/Options - Add CheckErrorBlocks switch so we can easily turn the code back on again in the future if necessary
      s/Kernel - Switch out all the code relating to error number checks, except for the dummy load of the first word of the error block, since that's still useful as a pointer validity check
      hdr/KernelWS - Revise SWIDespatch_Size definition so it's easier for it to cope with the various factors which may affect the despatcher size
      Tested on PandaBoard
      Relevant discussion:
    Version 6.04. Tagged as 'Kernel-6_04'
  • John Ballance's avatar
    Added HALDeviceID_RTC_PCF8523 · e23d83e6
    John Ballance authored
    Version 6.05. Tagged as 'Kernel-6_05'
  • Jeffrey Lee's avatar
    Merge in latest changes from main branch · 558118ac
    Jeffrey Lee authored
    Version 6.05, Tagged as 'Kernel-6_05-4_129_2_8'
  • Jeffrey Lee's avatar
    Update mode variable definitions · 7e7901c8
    Jeffrey Lee authored
      - Introduce mode variable 13, for specifying the minimum number of screen banks that are guaranteed to be available. Eventually the kernel will make use of this during mode vetting & selection, to give programs a simple and reliable way of selecting banked screen modes. Currently however it's only supported by VideoOverlay and the corresponding GraphicsV overlay APIs.
      - Extend the mode flags to allow display rotation & flipping to be specified. This is used to indicate that the framebuffer accessed by the CPU is not in the same orientation as what the user is seeing. Again, currently this is only supported by VideoOverlay and the corresponding GraphicsV overlay APIs.
      Tested on OMAP3, OMAP4
    Version 6.06. Tagged as 'Kernel-6_06'
  • ROOL's avatar
    Various kernel cleanups · bcbd3602
    ROOL authored
      NewReset.s: Remove warning about soft reset, this is not supported any longer
      MsgCode.s: Reload LR after potentially changing mode
      PMF/osinit.s: Delete vestiges of soft reset support
      Submission from Timothy Baldwin.
    Version 6.07. Tagged as 'Kernel-6_07'
  • ROOL's avatar
    Simplify initial AplSpace claim · 526764e1
    ROOL authored
      As the application slot is now a normal dynamic area, there's no need to manipulate the CAM directly. Convert FudgeSomeAppSpace into a OS_ChangeDynamicArea SWI followed by memset().
      ChangeDyn.s: Offset by 32k to account for the -32k that dynamic area -1 has.
      NewReset.s: Delete FudgeSomeAppSpace and replace as above.
      Submission from Timothy Baldwin.
    Version 6.08. Tagged as 'Kernel-6_08'
  • Jeffrey Lee's avatar
    Merge latest changes from HEAD · 5eecd7d5
    Jeffrey Lee authored
    Version 6.08, Tagged as 'Kernel-6_08-4_129_2_9'
  • Jeffrey Lee's avatar
    Allow SMP build switch to be overridden by components file · fa39779f
    Jeffrey Lee authored
      hdr/Options - The setting of the SMP switch can now be controlled by specifying the correct ASFLAGS, e.g. ASFLAGS="-PD \"SMP SETL {FALSE}\""
    Version 6.08, Tagged as 'Kernel-6_08-4_129_2_10'
  • Jeffrey Lee's avatar
    Merge SMP branch to trunk · 2736fc5f
    Jeffrey Lee authored
      Since the current SMP changes are fairly minor, and the trunk is seeing most development, from a maintenance perspective it makes sense to merge the changes to trunk. This will also make sure they get some wider testing ready for when the next round of SMP development takes place.
      - Docs/SMP - New docs folder describing SMP-related changes to the HAL and interrupt handling. Some of the IRQ changes can also be taken advantage of by single-core devices, since it introduces a way to describe which interrupt sources can be routed to IRQ & FIQ
      - Makefile, hdr/DBellDevice, hdr/HALDevice - New HAL device for an inter-processor software-generated interrupt source ("doorbell")
      - hdr/HALEntries - Reuse the unused matrix keyboard & touchscreen HAL entry points for the new IRQ handling & SMP-related HAL calls
      - hdr/KernelWS - Bump up MaxInterrupts
      - hdr/OSMem, s/MemInfo - Introduce OS_Memory 19, to allow for DMA to/from cacheable memory without actually altering the cacheability of the pages (which can be even more tricky in SMP systems than it is in uniprocessor systems)
      - hdr/Options - Introduce SMP build switch. Currently this controls whether the ARMops will operate in "SMP-friendly" mode or not (when running on MP processors)
      - s/ARMops, s/MemMap2 - Introduce the ARMv7MP ARMop implementation. Simplify DCache_LineLen / ICache_LineLen handling for WB_CR7_Lx so that it's the plain value rather than log2(n)-2
      - s/ExtraSWIs - If ARMops are in SMP-friendly mode, global OS_SynchroniseCodeAreas now only syncs application space and the RMA. This is because there is no trivial MP-safe global IMB operation available. This will also make global OS_SynchroniseCodeAreas significantly slower, but the documentation has always warned against performing a global IMB for just that reason, so code that suffers performance penalties should really try and switch to a ranged IMB.
      - s/NewIRQs - Update some comments regarding IRQ handler entry/exit conditions
    Version 6.09. Tagged as 'Kernel-6_09'
  • Jeffrey Lee's avatar
    Fix OS_Memory 0 "make temporarily uncacheable" not reporting errors · c5569c81
    Jeffrey Lee authored
      s/MemInfo - The wrapper around OS_Memory 0 introduced in Kernel-5_35-4_79_2_311 was preserving the wrong PSR field on exit, causing any error generated by the core code to be lost.
      Tested on Iyonix
      Fixes *screensave saving mostly white pixels (address translation for "external" VRAM should have failed and caused ADFS to fall back to a bounce buffer)
      Is also likely to be the cause of (address translation should have failed for soft ROM)
    Version 6.10. Tagged as 'Kernel-6_10'
  • Jeffrey Lee's avatar
    Evict ECFIndex and PalIndex from VDU workspace · bcc668c7
    Jeffrey Lee authored
      ECFIndex and PalIndex claim to be mode variables, but it's impossible for extension modes to specify their values.
      Since they're easy to calculate from the ModeFlags and Log2BPP values, drop them from the mode workspace (+ table of builtin modes) and calculate them on the fly instead.
      File changes:
      - hdr/KernelWS - Drop ECFIndex & PalIndex from workspace
      - s/vdu/vdumodes - Adjust workspace definition, drop ECFIndex & PalIndex values from VWSTAB
      - s/vdu/vdudriver - Remove now-redundant copy loop from ModeChangeSub. Remove code from GenerateModeSelectorVars that sets up the ECFIndex & PalIndex values on the stack
      - s/vdu/vdugrafl - Adjust copy loop in SwitchOutputToSprite/Mask
      - s/vdu/vdupalette, s/vdu/vdupalxx - Add GetPalIndex routine to generate PalIndex on the fly. Drop the obsolete 16bpp palette/gamma table and shuffle the other entries to simplify GetPalIndex a bit.
      - s/vdu/vduplot - Add GetECFIndex routine to generate ECFIndex on the fly. Also, fix things so that mode 0 isn't the only rectangular-pixel mode which uses the special rectangular-pixel ECF patterns (index 0 vs. index 4). Fiddle with ExportedHLine a bit to avoid an out-of-range ADR.
      - s/NewReset - Fix UAL warning for MOV R0, AppSpaceStart. Adjust memset to not assume 512KB is the correct amount
      Tested on Raspberry Pi 3
    Version 6.11. Tagged as 'Kernel-6_11'
  • Jeffrey Lee's avatar
    Fix OS_Hardware 3 to be re-entrant · 6f9f922b
    Jeffrey Lee authored
      s/HAL - OS_Hardware 3 (remove HAL device) will now re-scan the device list for the device following the Service_Hardware call, so that the device list won't become corrupt if the service call triggers addition/removal of devices.
      Tested on iMX6
      *HDMIOff now correctly removes the HDMI audio device and SoundDMA's software mixer device (SoundDMA removes mixer in response to the HDMI audio device vanishing, but re-entrancy bug meant that the HDMI device was left on the list)
      Note that this only covers re-entrancy via Service_Hardware. OS_Hardware 2/3/4/5 are not re-entrant from other locations (e.g. IRQ handlers or memory allocation service calls).
    Version 6.12. Tagged as 'Kernel-6_12'
  • Jeffrey Lee's avatar
    Improve detection of invalid/unsupported screen modes · 6eb6c11e
    Jeffrey Lee authored
      s/vdu/vdudriver - When using mode selector blocks, don't allow the system to switch into double-vertical, double-pixel, or BBC-gap modes which are in colour depths unsupported by the kernel
      Tested on BB-xM
    Version 6.13. Tagged as 'Kernel-6_13'
  • Ben Avison's avatar
    Nightly beta builds leapfrog RISC OS 5.26 · 2f8a46ed
    Ben Avison authored
  • Jeffrey Lee's avatar
    Attempt to tidy up substitute screen mode selection logic · d87c22a4
    Jeffrey Lee authored
      Over the years the OS's substitute screen mode selection logic has grown to be a tangled mess, and the logic it does implement isn't always very useful. Additionally, the kernel is structured in such a way that it can be hard for modules to override it.
      This set of changes aims to fix the many of the problems, by doing the following:
      - Moving all substitute mode selection logic out of the core VDU driver code and into a Service_ModeTranslation handler. This means you now only have one place in the kernel to look instead of several, and modules can override the behaviour by claiming/blocking the service call as appropriate.
      - Moving handling of the built-in VIDC lists out of the core VDU driver code and into a Service_ModeExtension handler. This means programs can now inspect these VIDC lists by issuing the right service call (although you are essentially limited to lists which the GraphicsV driver is OK with)
      - Moving *TV interlace & offset adjustment logic into the Service_ModeExtension handler, since they're legacy things which can be handled more cleanly for MDF/EDID (and the old code was poking memory the kernel didn't own)
      - Adding a Service_EnumerateScreenModes implementation, so that if you end up in the desktop with ScreenModes non-functional, the display manager at least has something useful to show you
      - Enhancing the handling of the built-in numbered modes so that they are now available in any colour depth; the Service_ModeExtension handler (and related handlers) treat the builtin VIDC lists as a set of mode timings, not a discrete set of modes
      - Substitute mode selection logic is a complete re-write. Instead of trying a handful of numbered fallback modes, it now tries:
        - Same mode but at higher colour depths
        - Same mode but at lower colour depths
        - Alternate resolutions (half-width mode with no double-pixel if original request was for double-pixel, and default resolution for monitor type)
      - Combined with the logic to allow the builtin VIDC lists to be used at any colour depth, this means that the kernel should now be able to find substitute modes for machines which lack support for <=8bpp modes (e.g. OMAP5)
      - Additionally the mode substitution code will attempt to retain as many properties of the originally requested mode as possible (eigen values, gap mode type, etc.)
      Other improvements:
      - The kernel now actually vets the builtin VIDC lists instead of assuming that they'll work (which also means they'll have the correct ExtraBytes value, where applicable)
      - The kernel now uses GraphicsV 19 (VetMode2) to vet the mode during the mode switch process, using the result to detect where the framebuffer will be placed. This allows for GraphicsV drivers to switch between DA 2 and external framestores on a per-mode basis.
      - The kernel now supports mode selectors which specify LineLength values which are larger than necessary; this will get translated to a suitable ExtraBytes control list item (+ combined with whatever padding the driver indicates is necessary via the VetMode2 result)
      File changes:
      - hdr/KernelWS - Reserve space for a VIDC list, since the Service_ModeExtension implementation typically can't use the built-in list as-is
      - s/Arthur3 - Issue Service_ModeFileChanged when the configured monitor type is changed, so that DisplayManager + friends are aware that the set of available modes has changed
      - s/GetAll - Fiddle with GETs a bit
      - s/MemMap2 - Extra LTORG
      - s/NewIRQs - Small routine to install/uninstall false VSync routine (previously from PushModeInfo, which wasn't really the appropriate place for it)
      - s/Utility - Hook up the extra service call handlers
      - s/vdu/legacymodes - New file containing the new service call implementations, and some related code
      - s/vdu/vdudecl - Move mode workspace definition here, from vdumodes
      - s/vdu/vdudriver - Remove assorted bits of mode substitution code. Plug in new bits for calling GraphicsV 19 during mode set, and deal with ExtraBytes/LineLength during PushModeInfo
      - s/vdu/vdumodes - Move some workspace definitions to s/vdu/vdudecl. Tweak how the builtin VIDC lists are stored.
      - s/vdu/vduswis - Rip out more mode substitution code. Issue Service_ModeFileChanged when monitor type is changed by OS_ScreenMode.
      Tested on Raspberry Pi 3, Iyonix, IGEPv5
    Version 6.14. Tagged as 'Kernel-6_14'
  • Jeffrey Lee's avatar
    Fix dodgy ranged ICache cleans when using ARMv7MP ARMops · b3c64d93
    Jeffrey Lee authored
      s/ARMops - If the ICacheInvalidate macro was told to pull a2, it would pull it before invoking ICache_InvalidateRange, causing the end address of the range to be lost. Avoid this by only pulling the registers after the ranged call.
      Also optimise MMU_ChangingEntry to go straight to ICache_InvalidateRange instead of doing a redundant range size check.
      Tested on OMAP5
      Potentially fixes lockup/long stall seen when using PhotoDesk, reported by Willi Theiss
    Version 6.15. Tagged as 'Kernel-6_15'
  • Jeffrey Lee's avatar
    Fix FindOKMode not recovering properly from unsupported VIDC lists · 6f366d87
    Jeffrey Lee authored
      s/vdu/vduswis - Fix 18 year old register corruption bug in FindOKMode which would prevent it from falling back to Service_ModeTranslation if Service_ModeExtension returned a VIDC list but the VIDC list was rejected by the GraphicsV driver
      s/vdu/vdudriver - Also, change a couple of error cases in ModeChangeSub so that they use the "Screen mode not available" error instead of the incorrect "Not enough screen memory" error.
      Tested on Raspberry Pi 3
      Fixes issue reported on forums where if AnyMode is loaded, numbered modes in unsupported colour depths weren't being replaced with substitutes (although note that there are still some AnyMode-related issues to resolve)
    Version 6.16. Tagged as 'Kernel-6_16'
  • Jeffrey Lee's avatar
    Service_ModeExtension tweak + docs update · 1b15fced
    Jeffrey Lee authored
      s/vdu/legacymodes - Make the Service_ModeExtension implementation automatically use ExtraBytes to request that the row length is a multiple of a word (since things fail with non-word aligned rows)
      hdr/VIDCList - Un-deprecate SyncPol bits 2 & 3 and improve the comments to indicate the difference between SyncPol interlace and control list interlace
      Tested on BB-xM
    Version 6.17. Tagged as 'Kernel-6_17'
  • Jeffrey Lee's avatar
    Palette/gamma optimisations · 831e1d94
    Jeffrey Lee authored
      - Fix conditional code sequence in PV_BulkWrite which meant that the greyscale palette flag was being recalculated when the border or pointer colour was changed.
      - Change PV_1stFlashState / PV_2ndFlashState to act as NOPs in true colour modes, which helps to avoid regular redundant gamma table updates (due to the flashing colour logic in the VSync handler).
      Tested on Raspberry Pi 3
    Version 6.18. Tagged as 'Kernel-6_18'
  • Jeffrey Lee's avatar
    Don't pointlessly doubly-map external framestores · e604b89c
    Jeffrey Lee authored
      s/vdu/vdudriver - When mapping external framestores, only double-map them if the driver supports hardware scrolling. Avoids wasting IO address space, and reduces IO space fragmentation if the framestore address changes
      Tested on Raspberry Pi 3
    Version 6.19. Tagged as 'Kernel-6_19'
  • Ben Avison's avatar
    Set BEN bit in SCTLR · fc49beaf
    Ben Avison authored
    Without this, some CPUs (including Cortex-A72) take the undefined instruction
    trap when encountering any CP15-encoded barrier instructions.
    Requires RiscOS/Sources/Programmer/HdrSrc!1
    Version 6.20. Tagged as 'Kernel-6_20'
  • Robert Sprowson's avatar
    Move former ControlList_Interlaced item into SyncPol flags · b3b95b4b
    Robert Sprowson authored
    ControlList_Interlaced is taken to have meant "output interlaced sync on H/V" and "configure DMA to show alternate lines in the framestore on alternate fields", therefore SyncPol flags mean:
     00 = 'normal' progressive scan
     01 = interlaced sync, but both fields show the same image
     10 = (invalid)
     11 = interlaced sync, fields use alternate lines from the image
    Version 6.21. Tagged as 'Kernel-6_21'
  • Ben Avison's avatar
    Support permanent mapping of IO above 4GB using supersections · 9024d1f6
    Ben Avison authored
    This is facilitated by two extended calls. From the HAL:
    * RISCOS_MapInIO64 allows the physical address to be specified as 64-bit
    From the OS:
    * OS_Memory 21 acts like OS_Memory 13, but takes a 64-bit physical address
    There is no need to extend RISCOS_LogToPhys, instead we change its return
    type to uint64_t. Any existing HALs will only read the a1 register, thereby
    narrowing the result to 32 bits, which is fine because all existing HALs
    only expected a 32-bit physical address space anyway.
    Internally, RISCOS_MapInIO has been rewritten to detect and use supersections
    for IO regions that end above 4GB. Areas that straddle the 4GB boundary should
    also work, although if you then search for a sub-area that doesn't, it won't
    find a match and will instead map it in again using vanilla sections - this is
    enough of an edge case that I don't think we need to worry about it too much.
    The rewrite also conveniently fixes a bug in the old code: if the area being
    mapped in went all the way up to physical address 0xFFFFFFFF (inclusive) then
    only the first megabyte of the area was actually mapped in due to a loop
    termination issue.
    Requires RiscOS/Sources/Programmer/HdrSrc!2
  • Ben Avison's avatar
    Support temporary mapping of IO above 4GB using supersections · 96913c1f
    Ben Avison authored
    Add a new reason code, OS_Memory 22, equivalent to OS_Memory 14, but
    accepting a 64-bit physical address in r1/r2. Current ARM architectures can
    only express 40-bit or 32-bit physical addresses in their page tables
    (depending on whether they feature the LPAE extension or not) so unlike
    OS_Memory 14, OS_Memory 22 can return an error if an invalid physical
    address has been supplied. OS_Memory 15 should still be used to release a
    temporary mapping, whether you claimed it using OS_Memory 14 or OS_Memory 22.
    The logical memory map has had to change to accommodate supersection mapping
    of the physical access window, which needs to be 16MB wide and aligned to a
    16MB boundary. This results in there being 16MB less logical address space
    available for dynamic areas on all platforms (sorry) and there is now a 1MB
    hole spare in the system address range (above IO).
    The internal function RISCOS_AccessPhysicalAddress has been changed to
    accept a 64-bit physical address. This function has been a candidate for
    adding to the kernel entry points from the HAL for a long time - enough that
    it features in the original HAL documentation - but has not been so added
    (at least not yet) so there are no API compatibility issues there.
    Requires RiscOS/Sources/Programmer/HdrSrc!2
  • Ben Avison's avatar
    Support supersection-mapped memory in OS_Memory 24 · bd294cf9
    Ben Avison authored
    To achieve this:
    * DecodeL1Entry and DecodeL2Entry return 64-bit physical addresses in
      r0 and r1, with additional return values shuffled up to r2 and r3
    * DecodeL1Entry now returns the section size, so callers can distinguish
      section- from supersection-mapped memory
    * PhysAddrToPageNo now accepts a 64-bit address (though since the physical
      RAM table is currently still all 32-bit, it will report any top-word-set
      addresses as being not in RAM)
    Version 6.22. Tagged as 'Kernel-6_22'
  • Jeffrey Lee's avatar
    Fix a couple of RISCOS_MapInIO bugs · 0ee90f05
    Jeffrey Lee authored
    - s/HAL - Fix ADD v. SUB muddle that could prevent addresses from being rounded down correctly. Fix incorrect logical address being returned to caller on pre-ARMv6 machines due to PageTableSync corrupting a1.
    - s/NewReset - Initialising the CMOS RAM cache while in the middle of setting up the processor vectors feels a bit silly. Move the code to just afterwards so that it feels a bit safer, and so that early crashes are easier to debug (processor vectors in stable state)
    Tested on Iyonix.
    Fixes ROM softload failure reported on forums:
    Version 6.23. Tagged as 'Kernel-6_23'
  • Jeffrey Lee's avatar
    Allow runtime adjustment of AplWorkMaxSize · 0aeea07f
    Jeffrey Lee authored
    This adds a new OS_DynamicArea reason code, 26, for adjusting
    AplWorkMaxSize at runtime. This allows compatibility tools such as
    Aemulor to adjust the limit without resorting to patching the kernel.
    Any adjustment made to the value will affect the upper limit of
    application space, and the lower limit of dynamic area placement.
    Attempting to adjust beyond the compile-time upper/default limit, or
    such that it will interfere with existing dynamic areas / wimpslots,
    will result in an error.
    Relevant forum thread:
    Tested on BB-xM, desktop active & inactive
    Version 6.24. Tagged as 'Kernel-6_24'
  • Timothy E Baldwin's avatar
    Remove duplicated documents · 484c275e
    Timothy E Baldwin authored
    Between RISC OS 3.6 and 3.7 the directory was renamed from
    Doc to Docs and was duplicated during CVS import.
    Fix by deleting Doc. Identical files remain in Docs.
    Version 6.24. Not tagged
  • Timothy E Baldwin's avatar
    Adjust exception error messages to show correct address. · ba236131
    Timothy E Baldwin authored
      Add offset parameter to DumpyTheRegisters in R4
      Shuffle internal register use up one
      Set R4 to offset before calling.
      Arbitrary offset of 0 for unreachable address exception handler.
      Tested in RPCEmu.
  • Timothy E Baldwin's avatar
    Adjust undefined instruction error message to show correct address on Thumb. · e9ce9bb1
    Timothy E Baldwin authored
    Version 6.25. Tagged as 'Kernel-6_25'
  • Jeffrey Lee's avatar
    Fix heap testbed · 071a9656
    Jeffrey Lee authored
    Kernel-5_44 tweaked the heap manager to try and avoid creating small
    free blocks. Adjust HeapTest's block size checks so that it allows for
    this behaviour.
    Tested briefly
  • Jeffrey Lee's avatar
    Add support for HeapReason_GetSkewAligned · b954559e
    Jeffrey Lee authored
    Similar to HeapReason_GetAligned, GetSkewAligned is used for allocating
    aligned blocks (with optional boundary limit). However instead of using
    the logical address of the user portion of the block for the alignment
    calculation, it uses an arbitrary offset specified in R5. This makes
    it useful for clients such as the PCI module, which care about the
    physical alignment of blocks rather than logical alignment.
    Tested with heaptest
  • Jeffrey Lee's avatar
    Add cross-check support to heaptest · 88ae7e18
    Jeffrey Lee authored
    Version 6.26. Tagged as 'Kernel-6_26'
  • Timothy E Baldwin's avatar
    Add RISC OS Limited OS_ReadSysInfo 6 items · 250b8ca6
    Timothy E Baldwin authored
    This makes SVLK and NVECTORS available.
    Version 6.27. Tagged as 'Kernel-6_27'
  • Timothy E Baldwin's avatar
    Remove some obsolete definitions for clarity · a52c5049
    Timothy E Baldwin authored
     * MinAplWork isn't used.
     * SuperMode isn't used and is less well known than "SWI OS_EnterOS".
     * MEMCADR is now only a magic value returned by OS_UpdateMEMC,
       so it is clearer to include it literally with comment.
    Added a comment to explain the baffling combination of
    the MEMC1 control register's address with it's value.
    Version 6.27. Not tagged
  • Jeffrey Lee's avatar
    Allow reservation of memory pages · 1f84ad9f
    Jeffrey Lee authored
    This change adds a new OS_Memory reason code, 23, for reserving memory
    without actually assigning it to a dynamic area. Other dynamic areas can
    still use the memory, but only the code that reserved it will be allowed
    to claim exclusive use over it (i.e. PageFlags_Unavailable).
    This is useful for systems such as the PCI heap, where physically
    contiguous memory is required, but the memory isn't needed all of the
    time. By reserving the pages, it allows other regular DAs to make use of
    the memory when the PCI heap is small. But when the PCI heap needs to
    grow, it guarantees that (if there's enough free memory in the system)
    the previously reserved pages can be allocated to the PCI heap.
    * Reservations are handled on an honour system; there's no checking that
    the program that reserved the memory is the one attempting to map it in.
    * For regular NeedsSpecificPages DAs, reserved pages can only be used if
    the special "RESV" R0 return value is used.
    * For PMP DAs, reserved pages can only be made Unavailable if the entry
    in the page block also specifies the Reserved page flag. The actual
    state of the Reserved flag can't be modified via PMP DA ops, the flag is
    only used to indicate the caller's permission/intent to make the page
    * If a PMP DA tries to make a Reserved page Unavailable without
    specifying the Reserved flag, the kernel will try to swap it out for a
    replacement page taken from the free pool (preserving the contents and
    generating Service_PagesUnsafe / Service_PagesSafe, as if another DA
    had claimed the page)
    Version 6.28. Tagged as 'Kernel-6_28'
  • Robert Sprowson's avatar
    Add GENET to the list of HAL devices · a5db413c
    Robert Sprowson authored
    Version 6.28. Not tagged
  • Jeffrey Lee's avatar
    Add OS_DynamicArea 27+28, for supporting lots of RAM · 9224a6ca
    Jeffrey Lee authored
    OS_DynamicArea 27 is the same as OS_DynamicArea 5 ("return free
    memory"), except the result is measured in pages instead of bytes,
    allowing it to behave sensibly on machines with many gigabytes of RAM.
    Similarly, OS_DynamicArea 28 is the same as OS_DynamicArea 7 (internal
    DA enumeration call used by TaskManager), except the returned size
    values are measured in pages instead of bytes. A flags word has also
    been added to allow for more expansion in the future.
    Hdr:OSMem now also contains some more definitions which external code
    will find useful.
    Version 6.29. Tagged as 'Kernel-6_29'
  • Timothy E Baldwin's avatar
    Permit special field in paths passed to OS_CLI · 2ec9e04e
    Timothy E Baldwin authored
    OS_CLI permits commands to be prefixed with a temporary filing
    system, for example "ADFS:Format"
    It also passes commands unrecognised to FileSwitch to be executed,
    so "ADFS::HardDisc4.$.!Boot" first sets the temporary filing to
    ADFS then executes ":HardDisc4.$.!Boot".
    This does not work if the path contains a special field,
    currently this results in an error as the special filed
    would be lost.
    Unfortunately many programs, including the RISC OS source
    fail because of this.
    Instead if a filing system prefix with special field
    is found switch to the Temporary filing system and
    treat the whole command as a path to execute. For example
    passing "IXFS#W:$.HardDisc4.!Boot" sets the temporary filing
    system to "IXFS" then executes "IXFS#W:$.HardDisc4.!Boot".
    Version 6.30. Tagged as 'Kernel-6_30'
  • Jeffrey Lee's avatar
    Fix OS_DynamicArea 21 handling of MaxCamEntry · 5f7b9b37
    Jeffrey Lee authored
    OS_DynamicArea 21 was treating MaxCamEntry as if it was the exclusive
    upper bound, when really it's the inclusive bound. The consequence of
    this was that PMPs were unable to explicitly claim the highest-numbered
    RAM page in the system.
    Version 6.31. Tagged as 'Kernel-6_31'
  • Timothy E Baldwin's avatar
    Fix *Dump on (apparently) empty files. · b4b52fa1
    Timothy E Baldwin authored
    Special case for empty files was crashing, fix by removing
    which also supports files which report a size of zero but
    actually contain data such as Unix device nodes and
    Linux procfs.
    Error where start outside file adjusted to permit a start
    exactly at the end of a file to permit (apparently) empty
    files with no output. Doing likewise for non-empty files
    is consistent.
    Also fix closing file in case of error reading GS format
    from CMOS.
    Version 6.32. Tagged as 'Kernel-6_32'
  • Jeffrey Lee's avatar
    Use correct access permissions during ROM decompression · aae64cb2
    Jeffrey Lee authored
    If HAL+OS are contiguous, the combined image is initially mapped as
    OSAP_None in order to allow for decompression. Fix the discontiguous
    case to use the same permissions
  • Jeffrey Lee's avatar
    PMP LogOp_MapOut fixes · a4ab6171
    Jeffrey Lee authored
    * Fix caching of page table entry flags (was never updating R9, so the
    flags would be recalculated for every page)
    * Fix use of flag in bottom bit of R6; if the flag was set, the
    early-exit case for having made all the cacheable pages uncacheable will
    never be hit, forcing it to loop through the full page list instead
  • Jeffrey Lee's avatar
    Fix stack imbalance in DA release · 3a26f20e
    Jeffrey Lee authored
    In OS_DynamicArea 2, a stack imbalance would occur if an error is
    encountered while releasing the physical pages of a PMP (R1-R8 pushed,
    but only R1-R7 pulled). Fix it, but also don't bother storing R1, since
    it's never modified.
  • Jeffrey Lee's avatar
    Fixes for zero-size PMPs · 0830af41
    Jeffrey Lee authored
    OS_DynamicArea 21, 22 & 25 were using the value of the PMP page list
    pointer (DANode_PMP) to determine whether the dynamic area is a PMP or
    not. However, PMPs which have had their max physical size set to zero
    will don't have the page list allocated, which will cause the test to
    fail. Normally this won't matter (those calls can't do anything useful
    when used on PMPs with zero max size), except for the edge case of where
    the SWI has been given a zero-length page list as input. By checking the
    value of DANode_PMP, this would result in the calls incorrectly
    returning an error.
    Fix this by having the code check the DA flags instead. Also, add a
    check to OS_DynamicArea 23 (PMP resize), otherwise non-PMP DAs could end
    up having page lists allocated for them.
  • Jeffrey Lee's avatar
    OS_Byte 19 fixes · 830bc852
    Jeffrey Lee authored
    * Don't wait for VSync if we're in IRQ context, since (a) IRQ handlers
    shouldn't take lots of time, and (b) it may hang the system. Fixes
    * Extend the DPMSUtils-inherited "don't wait for VSync if HSync output
    is off" fix to also deal with the case where VSync output is off, since
    it's reasonable to assume that turning off VSync output could also
    prevent the CPU from receiving the associated interrupts.
  • Jeffrey Lee's avatar
    Be more forgiving of GraphicsV init failures · e4a8bac2
    Jeffrey Lee authored
    * Update OS_ScreenMode 11's handling of drivers which fail to
    initialise. If there was no previous driver, then instead of trying to
    restore that nonexistant driver, stick with the new one. This is mainly
    to help with the case where the kernel's built in modes aren't accepted
    by the driver, and valid modes only become available once an MDF is
    loaded (this can happen with early OMAP3 chip revisions, which have very
    tight sync & porch limits, causing 90% of the kernel's modes to be
    rejected). If the kernel was to revert to the "no driver" state, then
    loading the MDF would still leave you with no video output.
    * Since we can now end up in a state where a driver is selected but
    hasn't been programmed yet, update OS_Byte 19 to detect this (via the
    magic ScreenBlankDPMSState value of 255) and avoid waiting for VSync
    * Update RemovePages & InsertRemovePagesExit (screen DA handlers) to
    avoid infinite loops if the screen DA gets shrunk to zero size (was seen
    while attempting to complete the !Boot sequence while no driver was
    Version 6.33. Tagged as 'Kernel-6_33'
  • Robert Sprowson's avatar
    Assign a USB flag · 56230247
    Robert Sprowson authored
    The XHCIDriver module adds 64k to get the register address. In an attempt to phase this out (so the registers are the true base address), assign a flag so that loading a suitable XHCIDriver on an old HAL still works.
    Version 6.33. Not tagged
  • Jeffrey Lee's avatar
    Fix phantom DA PostGrow errors · 8c2cae4a
    Jeffrey Lee authored
    Dynamic area PostGrow handlers aren't able to return errors, so the V
    flag is likely undefined. Fix AreaGrow so that it ignores any V-set
    condition returned by the call (especially since the CallPostGrow rapper
    will have clobbered any error pointer).
    Fixes issue reported on forums:
    Version 6.34. Tagged as 'Kernel-6_34'
  • ROOL's avatar
    Record various numbers used in other strands of RISC OS and compatible systems · 81b079e8
    ROOL authored
      * various low-numbered dynamic areas used by RISC OS 6 and Pyromaniac
      * OS_ReadSysInfo 8 host platform classes for VirtualRPC, A9Home, Pyromaniac
      * OS_Byte 0,<not 0> MosVer values for various systems since the BBC micro
      * OS_Byte 129,0,255 (BASIC INKEY -256) values for various RISC OS systems
      Discovered that these weren't really recorded anywhere during recent
      allocation request. Some information gleaned from
    Version 6.34. Not tagged
  • Robert Sprowson's avatar
    Fix abort after translating error · 7439cb45
    Robert Sprowson authored
    Reporting invalid parameters to OS_Pointer and OS_ConvertDateAndTime could wander off to bad places due to corrupt LR and/or stack imbalance.
  • Robert Sprowson's avatar
    Add aligned RMA claim subreason · fd81a66c
    Robert Sprowson authored
    => R0=24
       R3=size in bytes
       R4=alignment in bytes (must be a power of 2)
    <= R2=base of request
       or error
    Tested with a handful of valid and invalid alignments, and with one grossly larger than the free RMA to trigger an RMA extend to occur.
    Version 6.35. Tagged as 'Kernel-6_35'
  • Robert Sprowson's avatar
    Fix for bad error pointer *Dump'ing with a given start offset · 96988ed4
    Robert Sprowson authored
    Trying to dump a file larger than 2GB starting from an offset below 2GB would fail because the compare checking whether PTR#han > EXT#han accidentally set V which was taken as an error (but with R0 not really being an error block).
  • Robert Sprowson's avatar
    Add OS_Module 22 · 0e0d10cc
    Robert Sprowson authored
    Very much like OS_Module 12, but returns the pointer to the PW rather than its contents (or NULL if the module died during init).
  • Robert Sprowson's avatar
    Special case extension of aligned RMA claims · 949b03ad
    Robert Sprowson authored
    During ModHandReason_ClaimAligned care is taken to start on a multiple of 32 and end on a multiple of 32 + 16 (such that the next block in the heap would be at +20 same as plain ModHandReason_Claim would do). However, during a ModHandReason_ExtendBlock there's a possibility that those criteria can't be retained, due to having to move to a larger gap elsewhere, leaving the end at an inconvenient +36.
    Similar allocation functions in other OS' don't guarantee to return an extended block with the same alignment, so take the position that for extends we always allocate a fresh block, copy the contents, and free the original. Shrinks are left in place.
    Tested with a random allocator which juggles 16 aligned allocations 50,000 times.
    Version 6.36. Tagged as 'Kernel-6_36'
  • Jeffrey Lee's avatar
    Add scroll mouse support · 66b2aac7
    Jeffrey Lee authored
    * Listen out for PointerV 9, which (RISC OS 5) mouse drivers use to
    indicate scroll wheel updates + extra button status
    * Changes in the state of the extra buttons are treated the same as
    changes to normal mouse buttons: signalled via Event_Mouse, and stored
    in the mouse buffer (for reading via OS_Mouse).
    * Changes in the scroll wheel(s) are signalled via Event_Expansion,4. If
    the event vector call is unclaimed, the kernel's wheel position
    accumulators will be updated
    * Wheel position accumulators can be read via OS_Pointer 2
    * Wheel position accumulators implement "wrap to zero" logic on overflow
    This matches RISCOS Ltd's implementation
    except that:
    * The kernel currently doesn't call PointerV 4, so PointerV 9 is the
    only way drivers can report wheel + extra button status
    * Extra mouse buttons don't generate KeyV transitions
    * Our implementation is in the kernel, not an OSPointer module
    Version 6.37. Tagged as 'Kernel-6_37'
  • ROOL's avatar
    Resync with allocations database · b5d0e2dc
    ROOL authored
    Edits to the RISCOS header file should really have gone through the
    allocations system. Fortunately, no harm was done in this case, but a
    minor syntactical change is required in order to bring it in line with
    the automatic redaction scripts used when exporting the header from the
    allocations database.
    Version 6.37. Not tagged
  • Ben Avison's avatar
    Mirror OS_AMBControl changes from Pyromaniac · 2991e2df
    Ben Avison authored
    * Create new header file defining symbolic name for OS_AMBControl
      reason codes and flags
    * Implement OS_AMBControl 9 (used to determine required size of buffer
      passed to OS_AMBControl 8 - potential thread safety issue not addressed)
    * Return allocated error numbers in various failure cases
    Version 6.38. Tagged as 'Kernel-6_38'
  • Jeffrey Lee's avatar
    Fix OS_Byte 166 for high ZeroPage, make read-only · 0595a541
    Jeffrey Lee authored
    Despite never being properly documented in the RISC OS PRMs, there's
    evidence that Acorn were recommending that third-parties used OS_Byte
    166 for locating the OS_Byte variables well into the mid-1990's:
    Currently OS builds which use zero page relocation will only return the
    low 16 bits of the address from OS_Byte 166, most likely breaking any
    third-party software which is trying to use it. Attempt to restore
    compatibility by having OS_Byte 166 add the missing high address bits
    into the "next location" value returned in R2, and fix OS_Byte 167 in a
    similar manner (adding into R1).
    Additionally, make the values read-only, because the kernel is littered
    with code that uses hard-coded OsbyteVars addresses and so is unlikely
    to do anything sensible if someone was to modify the OsbyteVars address
    that's stored in workspace.
    Version 6.39. Tagged as 'Kernel-6_39'
  • Jeffrey Lee's avatar
    Fix Service_Memory when shrinking appspace · 323e88c6
    Jeffrey Lee authored
    Update AreaShrink so that (when shrinking appspace) CheckAppSpace is
    passed the change amount as a negative number, so that Service_Memory is
    issued with the correct sign.
    Fixes issue reported on the forums, where BASIC was getting confused
    because appspace shrinks were being reported as if they were a grow
    It looks like this bug was introduced in Kernel-5_35-4_79_2_284
    (introduction of PMPs), where the logic for appspace shrinks (which must
    be performed via a grow of the free pool or some other DA) were moved
    out of AreaGrow and into AreaShrink (because appspace shrinks are now
    internally treated as "shrink appspace into free pool")
  • Jeffrey Lee's avatar
    Fix shrinkables check in AreaGrow · 86fe0712
    Jeffrey Lee authored
    TryToShrinkShrinkables_Bytes expected both R1 and R2 to be byte counts,
    but AreaGrow was calling with R1 as a byte count and R2 as a page count.
    This would have caused it to request the first-found shrinkable to
    shrink more than necessary, and also confuse the rest of AreaGrow when
    the page-based R2 result of TryToShrinkShrinkables gets converted to a
    byte count (when AreaGrow wants it as a page count)
  • Jeffrey Lee's avatar
    Fix combined freepool + appspace shrink · 76d04b25
    Jeffrey Lee authored
    When a DA tries to grow by more than the free pool size, the kernel
    should try to take the necessary remaining amount from application
    space. Historically this was handled as a combined "take from freepool
    and appspace" operation, but with Kernel-5_35-4_79_2_284 this was
    changed to use a nested call to OS_ChangeDynamicArea, so first appspace
    is shrunk into the free pool and then the target DA is grown using just
    the free pool.
    However the code was foolishly trying to use ChangeDyn_AplSpace as the
    argument to OS_ChangeDynamicArea, which that call doesn't recognise as a
    valid DA number. Change it to use ChangeDyn_FreePool ("grow free pool
    from appspace"), and also fix up a stack imbalance that would have
    caused it to misbehave regardless of the outcome.
  • Jeffrey Lee's avatar
    Fix GrowFreePool · 1a3c927f
    Jeffrey Lee authored
    Buggy since its introduction in Kernel-5_35-4_79_2_284, GrowFreePool was
    attempting to grow the free pool by shrinking application space, an
    operation which OS_ChangeDynamicArea doesn't support. Change it to grow
    the free pool instead, and fix a couple of other issues that would have
    caused it to work incorrectly (register corruption causing it to request
    a size change of zero, and incorrect assumption that
    OS_ChangeDynamicArea returns the amount unmoved, when really it returns
    the amount moved)
  • Jeffrey Lee's avatar
    Fix PMP appspace size check · 5014117d
    Jeffrey Lee authored
    Fix AreaGrow to read appspace size correctly when appspace is a PMP
    (i.e. an AMBControl node). Reading DANode_Size will only report the
    amount of memory currently paged in (e.g. by lazy task swapping),
    causing AreaGrow to underestimate how much it can potentially take from
    the area.
  • Jeffrey Lee's avatar
    Add missing AMBControl appspace shrink check · 0634b535
    Jeffrey Lee authored
    Fix GrowFreePoolFromAppSpace (i.e. appspace shrink operation) to issue
    UpCall_MemoryMoving / Service_Memory when attempting to shrink PMP-based
    appspace (i.e. AMBControl nodes). This fixes (e.g.) BASIC getting stuck
    in an abort loop if you try and use OS_ChangeDynamicArea to grow the
    free pool.
    Version 6.40. Tagged as 'Kernel-6_40'
  • Jeffrey Lee's avatar
    Fix OS_Memory 7 for discontiguous RAM · fb127e47
    Jeffrey Lee authored
    The current OS_Memory 7 implementation uses an address range structure
    returned by HAL_PhysInfo to decide which part of the physical address
    arrangement table to overwrite with RAM information. I suspect the
    original intention was for OS_Memory to use this address range to avoid
    marking the VRAM as DRAM (HAL_PhysInfo is expected to fill in the VRAM
    itself). But by overwriting everything between the start and the end
    address, OS_Memory will also overwrite any non-RAM areas which are
    sandwiched between RAM banks, e.g. the VideoCore-owned RAM on Pi models
    with >1GB RAM. There's also the problem that the address range returned
    by the HAL is using 32bit addresses, so it won't work as-is for RAM
    located above the 4GB barrier.
    Fix these issues by reworking the routine so that it ignores the address
    range returned by the HAL and instead detects VRAM by checking the
    IsVRAM flag in the PhysRamTable entry. And for detecting if the ROM is
    running from RAM, instead of using the address range we can rely on the
    flag available via OS_ReadSysInfo 8 (i.e. HAL_PlatformInfo), like
    OS_Memory 8 does.
    Also add a simple BASIC program (Dev.PhysInfo) to allow easy checking of
    HAL & OS physical address arrangement tables.
    Version 6.41. Tagged as 'Kernel-6_41'
  • Timothy E Baldwin's avatar
    Disable interrupts whilst checking for keys in OS_ReadC / INKEY · 9d5ab8de
    Timothy E Baldwin authored
    This ensures that on exit from OS_ReadC / INKEY either
    a character is returned or the input buffer is empty,
    and that Portable_Idle is only called when the input
    buffer is empty.
    This avoids a 10 microsecond delay and relying on timer
    interrupts to make progress and allows reliably waiting
    for input and another event by:
    Disable Interrupts
      Call INKEY(0), exit loop if key pressed
      Check other event, exit loop if key pressed
      Call Portable_Idle
    Version 6.42. Tagged as 'Kernel-6_42'
  • Timothy E Baldwin's avatar
    Fix cleaning · 5e131c13
    Timothy E Baldwin authored
    Move .gitignore file to root and populate with all temporary paths.
    This fixes .gitignore files being deleted during a ROM build.
    Version 6.42. Not tagged
  • Jeffrey Lee's avatar
    OS_DynamicArea 22 fixes · 88219988
    Jeffrey Lee authored
    Multiple fixes, mostly related to error handling.
    1. Ensure R1 is initialised correctly when generating BadPageNumber
    errors (labels 94 & 95). Generally this involves setting it to zero to
    indicate that no call to LogOp_MapOut is required. Failing to do this
    would typically result in a crash.
    2. When branching back to the start of the loop after calling
    GetNonReservedPage, ensure R0 is reset to zero. Failing to do this would
    have a performance impact on LogOp_MapOut, but shouldn't be fatal.
    3. In the main routine, postpone writing back DANode_Size until after
    the call to physical_to_ppn (because we may decide to abort the op
    and return an error without moving a page).
    4. Fix stack offset when accessing PMPLogOp_GlobalTBLFlushNeeded.
    Getting this wrong could potentially result in some TLB maintenance
    being skipped when moving uncacheable pages.
    5. Fix stack imbalance at label 94
    Version 6.43. Tagged as 'Kernel-6_43'
......@@ -29,20 +29,40 @@
/* Whether to use the XOS_Heap SWI or the local copy of the heap code */
/* Cross-check against XOS_Heap SWI (expects 100% identical behaviour) */
//#define CROSSCHECK
/* Cross-check against local heap code instead of XOS_Heap */
/* Maximum number of allocations to make */
#define MAX_ALLOCS 1024
#define VBIT (1<<28)
extern _kernel_oserror *CallHeap(_kernel_swi_regs *r);
#define CallHeap(R) _kernel_swi(OS_Heap,R,R)
#if defined(CROSSCHECK_LOCAL) && !defined(CROSSCHECK)
static _kernel_oserror *CallOSHeap(_kernel_swi_regs *r)
return _kernel_swi(OS_Heap,r,r);
extern _kernel_oserror *CallMyHeap(_kernel_swi_regs *r);
typedef _kernel_oserror *(*heapfunc_t)(_kernel_swi_regs *r);
typedef struct {
uint32_t *heap; /* Main heap */
uint32_t *backup; /* Backup copy of heap */
heapfunc_t heapfunc;
int calls;
} heap_t;
/* Workspace */
static uint32_t *heap=NULL; /* Main heap */
static uint32_t *backup=NULL; /* Backup copy of heap */
static heap_t heap; /* Main test heap */
static heap_t crosscheck; /* Secondary heap if cross-checking against OS */
static uint32_t allocsize=0; /* Heap memory block size */
static uint32_t *usedspace=NULL; /* Bitmap of used space; 1 bit per word */
static uint32_t seed=0; /* RNG seed */
......@@ -51,24 +71,44 @@ static uint32_t numblocks=0; /* Number of blocks currently allocated */
static uint32_t blocks[MAX_ALLOCS]; /* Offsets of blocks within heap */
static uint32_t currentop = 0; /* Current heap operation */
static uint32_t opsleft = 0; /* Number of ops left */
static _kernel_swi_regs r;
static _kernel_swi_regs regs;
static _kernel_swi_regs last;
static _kernel_swi_regs cr;
/* Utility functions */
static void init(void)
static _kernel_oserror *CallHeap(heap_t *h, _kernel_swi_regs *r)
printf("Seed %08x alloc size %08x\n",seed,allocsize);
r->r[1] = (int) h->heap;
return h->heapfunc(r);
static void init(heap_t *h, heapfunc_t heapfunc)
_kernel_swi_regs r;
h->heapfunc = heapfunc;
/* Make heap 4K aligned */
heap = (uint32_t *) (((uint32_t) malloc(allocsize+4096)+4095)&0xfffff000);
h->heap = (uint32_t *) (((uint32_t) malloc(allocsize+4096)+4095)&0xfffff000);
/* Same for backup */
backup = (uint32_t *) (((uint32_t) malloc(allocsize+4096)+4095)&0xfffff000);
/* Used space map */
usedspace = (uint32_t *) malloc(((allocsize+31*4)>>7)<<2);
h->backup = (uint32_t *) (((uint32_t) malloc(allocsize+4096)+4095)&0xfffff000);
/* Initialise heap */
r.r[0] = HeapReason_Init;
r.r[3] = allocsize;
_kernel_oserror *err = CallHeap(h,&r);
fprintf(stderr,"Heap initialise failed! %s\n",err->errmess);
static uint32_t getrand(uint32_t max)
......@@ -79,7 +119,7 @@ static uint32_t getrand(uint32_t max)
static void dumpheap(uint32_t *h)
fprintf(stderr,"heap @ %p:\nmag %x\nfree %x\nbase %x\nend %x\n",h,h[0],h[1],h[2],h[3]);
fprintf(stderr,"heap @ %p:\nmagic %x\nfree %x\nbase %x\nend %x\n",h,h[0],h[1],h[2],h[3]);
uint32_t free = h[1];
uint32_t next = 16;
......@@ -88,12 +128,12 @@ static void dumpheap(uint32_t *h)
if(free > next)
fprintf(stderr,"allocs between %x and %x:\n",next,free);
fprintf(stderr," allocs between %x and %x:\n",next,free);
do {
fprintf(stderr,"%x: alloc size %x\n",next,h[next>>2]);
fprintf(stderr," %x: alloc size %x\n",next,h[next>>2]);
if((h[next>>2] > h[2]) || (h[next>>2]+next > h[2]) || (h[next>>2]&3) || !h[next>>2])
fprintf(stderr,"bad block, skipping rest\n");
fprintf(stderr," bad block, skipping rest\n");
next += h[next>>2];
......@@ -101,47 +141,47 @@ static void dumpheap(uint32_t *h)
fprintf(stderr,"alloc mismatch! next=%x\n",next);
fprintf(stderr,"%x: free size %x next %x\n",free,h[(free+4)>>2],h[free>>2]);
fprintf(stderr," %x: free size %x next %x\n",free,h[(free+4)>>2],h[free>>2]);
if(h[(free+4)>>2] == h[free>>2])
fprintf(stderr,"consecutive free blocks!\n");
fprintf(stderr," consecutive free blocks!\n");
next = free+h[(free+4)>>2];
if((h[free>>2] & 3) || (h[free>>2] >= h[2]) || (h[free>>2]+free >= h[2]))
fprintf(stderr,"bad next ptr\n");
fprintf(stderr," bad next ptr\n");
if((h[(free+4)>>2] & 3) || (h[(free+4)>>2] >= h[2]) || (h[(free+4)>>2]+free >= h[2]))
fprintf(stderr,"bad size\n");
fprintf(stderr," bad size\n");
fprintf(stderr,"end of free list\n");
fprintf(stderr," end of free list\n");
free = free+h[free>>2];
fprintf(stderr,"next free is inside current?\n");
fprintf(stderr," next free is inside current?\n");
if(free > h[2])
fprintf(stderr,"free list extends beyond heap end\n");
fprintf(stderr," free list extends beyond heap end\n");
if(next > h[2])
fprintf(stderr,"next ptr beyond heap end\n");
fprintf(stderr," next ptr beyond heap end\n");
fprintf(stderr,"end allocs:\n");
while(next < h[2])
fprintf(stderr,"%x: alloc size %x\n",next,h[next>>2]);
fprintf(stderr," %x: alloc size %x\n",next,h[next>>2]);
if((h[next>>2] > h[2]) || (h[next>>2]+next > h[2]) || (h[next>>2]&3) || !h[next>>2])
fprintf(stderr,"bad block, skipping rest\n");
fprintf(stderr," bad block, skipping rest\n");
next += h[next>>2];
......@@ -214,25 +254,36 @@ static void fail(void)
fprintf(stderr,"Failed on sequence %d\n",sequence);
fprintf(stderr,"Last op registers:\n");
for(int i=0;i<5;i++)
fprintf(stderr,"r%d = %08x\n",i,last.r[i]);
fprintf(stderr," r%d = %08x\n",i,last.r[i]);
fprintf(stderr,"Result registers:\n");
for(int i=0;i<5;i++)
fprintf(stderr,"r%d = %08x\n",i,r.r[i]);
fprintf(stderr," r%d = %08x\n",i,regs.r[i]);
fprintf(stderr,"Crosscheck result registers:\n");
for(int i=0;i<5;i++)
fprintf(stderr," r%d = %08x\n",i,cr.r[i]);
fprintf(stderr,"Heap before op:\n");
fprintf(stderr,"Heap after op:\n");
fprintf(stderr,"Crosscheck heap before op:\n");
fprintf(stderr,"Crosscheck heap after op:\n");
fprintf(stderr,"Allocated blocks:\n");
for(uint32_t i=0;i<numblocks;i++)
fprintf(stderr," %08x\n",blocks[i]);
static uint32_t blocksize(uint32_t offset)
return heap[(offset-4)>>2];
return heap.heap[(offset-4)>>2];
static void tryuse(uint32_t offset)
......@@ -283,34 +334,49 @@ static void tryfree(uint32_t offset)
int main(int argc,char **argv)
_kernel_oserror *err;
_kernel_oserror *err = NULL;
_kernel_oserror err2;
/* TODO - Take parameters from command line */
allocsize = 8*1024;
allocsize = 8*1024; /* 8K is sensible minimum, due to max alignment/boundary used of 2K */
printf("Seed %08x alloc size %08x\n",seed,allocsize);
/* Initialise heap */
r.r[0] = HeapReason_Init;
r.r[1] = (int) heap;
r.r[3] = allocsize;
err = CallHeap(&r);
fprintf(stderr,"Heap initialise failed! %s\n",err->errmess);
/* Used space map */
usedspace = (uint32_t *) malloc(((allocsize+31*4)>>7)<<2);
usedspace[0] = 0xf;
/* Begin tests */
uint32_t temp,temp2,temp3,temp4;
uint32_t temp,temp2,temp3,temp4,temp5;
opsleft = getrand(128);
opsleft = getrand(128)+1;
case 0:
currentop = HeapReason_Get;
......@@ -321,19 +387,21 @@ int main(int argc,char **argv)
case 2:
currentop = HeapReason_ExtendBlock;
case 3:
currentop = HeapReason_GetAligned;
currentop = HeapReason_GetSkewAligned;
// printf(".");
r.r[0] = currentop;
regs.r[0] = currentop;
case HeapReason_Get:
......@@ -342,9 +410,9 @@ int main(int argc,char **argv)
opsleft = 0;
r.r[3] = temp = getrand(allocsize>>5)+1;
last = r;
err = CallHeap(&r);
regs.r[3] = temp = getrand(allocsize>>5)+1;
last = regs;
err = CallHeap(&heap,&regs);
if(err->errnum != ErrorNumber_HeapFail_Alloc)
......@@ -355,7 +423,7 @@ int main(int argc,char **argv)
temp2 = blocks[numblocks++] = r.r[2]-((uint32_t)heap);
temp2 = blocks[numblocks++] = regs.r[2]-((uint32_t)heap.heap);
if(blocksize(temp2) < temp+4)
fprintf(stderr,"Failed to allocate requested block size: %08x bytes at %08x\n",temp,temp2);
......@@ -371,10 +439,10 @@ int main(int argc,char **argv)
temp = getrand(numblocks);
r.r[2] = blocks[temp]+((uint32_t) heap);
regs.r[2] = blocks[temp]+((uint32_t) heap.heap);
tryfree(blocks[temp]); /* Must free beforehand */
last = r;
err = CallHeap(&r);
last = regs;
err = CallHeap(&heap,&regs);
fprintf(stderr,"Failed freeing block at %08x: %s\n",blocks[temp],err->errmess);
......@@ -389,13 +457,13 @@ int main(int argc,char **argv)
temp = getrand(numblocks);
r.r[2] = blocks[temp]+((uint32_t) heap);
regs.r[2] = blocks[temp]+((uint32_t) heap.heap);
temp2 = getrand(allocsize>>4)-(allocsize>>5);
r.r[3] = temp2;
regs.r[3] = temp2;
temp3 = blocksize(blocks[temp]);
tryfree(blocks[temp]); /* Must free beforehand */
last = r;
err = CallHeap(&r);
last = regs;
err = CallHeap(&heap,&regs);
if(err->errnum != ErrorNumber_HeapFail_Alloc)
......@@ -412,16 +480,16 @@ int main(int argc,char **argv)
if(r.r[2] && (r.r[2] != 0xffffffff))
if(regs.r[2] && (regs.r[2] != 0xffffffff))
if((int) (temp3+temp2) <= 4)
fprintf(stderr,"Resized block was kept when it should have been freed: block %08x by %08x\n",blocks[temp],(int) temp2);
blocks[temp] = r.r[2]-((uint32_t)heap);
blocks[temp] = regs.r[2]-((uint32_t)heap.heap);
if((blocksize(blocks[temp])-(temp3+temp2)) > 7)
if((blocksize(blocks[temp])-(temp3+temp2)) > 11)
fprintf(stderr,"Failed to resize block by required amount: block %08x by %08x\n",blocks[temp],(int) temp2);
......@@ -439,22 +507,25 @@ int main(int argc,char **argv)
case HeapReason_GetAligned:
case HeapReason_GetSkewAligned:
if(numblocks == MAX_ALLOCS)
opsleft = 0;
r.r[3] = temp = getrand(allocsize>>4)+1;
temp2 = 4<<getrand(9); /* Max 2K alignment (heap 4K aligned) */
regs.r[3] = temp = getrand(allocsize>>4)+1;
temp2 = 4<<getrand(9); /* Max 2K alignment */
temp3 = temp2*(1<<getrand(5));
if(temp3 > 4096) /* Max 2K boundary (heap 4K aligned) */
if(temp3 > 4096) /* Max 2K boundary */
temp3 = 2048;
if(temp3 < temp)
temp3 = 0;
r.r[2] = temp2;
r.r[4] = temp3;
last = r;
err = CallHeap(&r);
regs.r[2] = temp2;
regs.r[4] = temp3;
regs.r[5] = 0;
temp5 = (currentop == HeapReason_GetAligned ? regs.r[1] : regs.r[5]);
last = regs;
err = CallHeap(&heap,&regs);
if(err->errnum != ErrorNumber_HeapFail_Alloc)
......@@ -465,18 +536,19 @@ int main(int argc,char **argv)
temp4 = blocks[numblocks++] = r.r[2]-((uint32_t) heap);
temp4 = blocks[numblocks++] = regs.r[2]-((uint32_t) heap.heap);
if(blocksize(temp4) < temp+4)
fprintf(stderr,"Failed to allocate requested block size: %08x bytes at alignment %08x boundary %08x at %08x\n",temp,temp2,temp3,temp4);
if(temp4 & (temp2-1))
temp5 = temp4+temp5;
if(temp5 & (temp2-1))
fprintf(stderr,"Block allocated at wrong alignment: %08x bytes at alignment %08x boundary %08x at %08x\n",temp,temp2,temp3,temp4);
if(temp3 && ((temp4 & ~(temp3-1)) != ((temp4+temp-1) & ~(temp3-1))))
if(temp3 && ((temp5 & ~(temp3-1)) != ((temp5+temp-1) & ~(temp3-1))))
fprintf(stderr,"Block crosses boundary: %08x bytes at alignment %08x boundary %08x at %08x\n",temp,temp2,temp3,temp4);
......@@ -485,6 +557,70 @@ int main(int argc,char **argv)
if (opsleft)
if (heap.calls != crosscheck.calls+1)
fprintf(stderr,"Heaptest failure: Wrong heap call counts\n");
if (memcmp(heap.backup,crosscheck.heap,allocsize))
fprintf(stderr,"Heaptest failure: Heap & crosscheck are unexpectedly out of sync\n");
cr = last;
if((currentop == HeapReason_Free) || (currentop == HeapReason_ExtendBlock))
cr.r[2] += ((int)crosscheck.heap) - ((int)heap.heap);
if (err != NULL)
err2 = *err;
err2.errnum = 0;
err2.errmess[0] = 0;
err = CallHeap(&crosscheck,&cr);
if(err != NULL)
if((err->errnum != err2.errnum) || strcmp(err->errmess,err2.errmess))
fprintf(stderr,"Crosscheck failure: Error %08x %s\nCrosscheck %08x %s\n",err2.errnum,err2.errmess,err->errnum,err->errmess);
fprintf(stderr,"Crosscheck failure: Error %08x %s\nCrosscheck no error\n",err2.errnum,err2.errmess);
/* R2 is the only result register we care about */
if ((currentop == HeapReason_Get) || (currentop == HeapReason_ExtendBlock) || (currentop == HeapReason_GetAligned) || (currentop == HeapReason_GetSkewAligned))
if ((currentop == HeapReason_ExtendBlock) && (regs.r[2] == -1) && (cr.r[2] == -1))
/* OK */
else if ((regs.r[2] - (int)heap.heap) != (cr.r[2] - (int)crosscheck.heap))
fprintf(stderr,"Crosscheck failure: Block offset %08x crosscheck %08x\n",regs.r[2] - (int)heap.heap,cr.r[2] - (int)crosscheck.heap);
if (memcmp(heap.heap,crosscheck.heap,allocsize))
fprintf(stderr,"Crosscheck failure: Heaps different\n");
......@@ -50,12 +50,14 @@ HeapSavedReg_R1 # 4
HeapSavedReg_R2 # 4
HeapSavedReg_R3 # 4
HeapSavedReg_R4 # 4
HeapSavedReg_R5 # 4
HeapSavedReg_R13 # 4
HeapReturnedReg_R0 # 4
HeapReturnedReg_R1 # 4
HeapReturnedReg_R2 # 4
HeapReturnedReg_R3 # 4
HeapReturnedReg_R4 # 4
HeapReturnedReg_R5 # 4
HeapReturnedReg_R13 # 4
HeapReturnedReg_PSR # 4
ZeroPageSize * @
......@@ -82,8 +84,8 @@ HeapBackgroundError % 256
; C interface
CallHeap ROUT
CallMyHeap ROUT
; r0 = _kernel_swi_regs ptr for input/output
; Returns error ptr in r0
Push "r0,r4-r11,lr"
; > 5thColumn
RISC OS Support for extension ROMs
Author: Tim Dobson
Status: Draft
Issue: 0.03
Date Revision Changes
11-Oct-90 0.00 Started
16-Oct-90 0.01 Completed first draft
08-Feb-91 0.02 Updated to reflect reality
23-Apr-91 0.03 Added note about directly executable
extension ROMS
This document describes the enhancements to RISC OS to support extension (or
"5th column") ROMs.
Extension ROMs are ROMs fitted in addition to the main ROM set, which
provide software modules which are automatically loaded by RISC OS on
The availability, size and number of extension ROM sockets depends on which
type of RISC OS computer you are using.
In general, however, RISC OS recognises extension ROMs or ROM sets which are
8, 16 or 32 bits wide, provided the ROM adheres to the specification below.
32 bit wide extension ROM sets are directly executable in place, saving on
user RAM. 8 or 16 bit wide sets have to be copied into RAM to execute.
Creating an extension ROM
Extension ROMs appear in the ROM area of the memory map, ie between
&03400000 and &03FFFFFF. An extension ROM set must end on a 64K boundary or
at the start of another extension ROM. This is normally not a problem as it
is unlikely you would want to use a ROM smaller than a 27128 (16K), and the
normal way of addressing this would mean that the ROM would be visible in 1
byte out of each word, ie within a 64K addressable area.
Extension ROMs have a header at the end of the ROM image which indicates the
presence of a valid extension ROM. The header is at the end because RISC OS
scans the ROM area downwards from the top.
At the end of each ROM set of size 'n' bytes must be a 16-byte header as
Byte address Contents
n-16 1-word size field containing n
n-12 1-word checksum (bottom 32 bits of the sum of all
words from addresses 0 to n-16 inclusive)
n-8 2-word id "ExtnROM0" indicating a valid extension
ROM, ie
n-8 &45 ; "E"
n-7 &78 ; "x"
n-6 &74 ; "t"
n-5 &6E ; "n"
n-4 &52 ; "R"
n-3 &4F ; "O"
n-2 &4D ; "M"
n-1 &30 ; "0"
Note that the ROM header will not necessarily appear in the memory map in
the last 16 bytes if the ROM set is 8 or 16 bits wide. In the 8-bit case,
the header will appear in one of the four byte positions of the last 16
words, and in the 16-bit case, in one of the two half-word positions of the
last 8 words. However, RISC OS copes with this.
Extension ROMs also have a header at the *start* of the ROM set, which is
identical to the format of an expansion card's identity space. This is
because the Podule manager module handles much of the extension ROM
The format of the header at the start is as follows:-
Byte address Contents Meaning
0 &00 Extended expansion card identity,
not requesting IRQ or FIQ
1 &03 bit 0 set => there is a chunk
bit 1 set => interrupt status
pointers defined (necessary because
bit 0 is set)
bits 2,3 = 0 => 8-bits wide (NB this
should be set to 0 irrespective of
the actual width of the ROM set)
2 &00 Reserved, must be zero
3 &87 Product type (lo-byte)
4 &00 Product type (hi-byte)
See below
5 Manuf(lo) Manufacturer code (lo-byte)
6 Manuf(hi) Manufacturer code (hi-byte)
See below
7 Country Country code - see below
8 to 15 &00 Interrupt status pointers (extension
ROMs do not generate interrupts!)
16 onwards Chunk directory - see below
Product type code: Note that &0087 has been allocated as a product type code
for all extension ROMs.
Manufacturer code: All manufacturers of expansion cards and/or extension
ROMs should have a code for manufacturer. If you have not already been
allocated one, you should consult Acorn.
Country code: Every extension ROM should have a code for the country of
origin. These match those used by the International module, except that the
UK has a country code of 0 for expansion cards and extension ROMs. If you do
not already know the correct country code for your country, you should
consult Acorn.
The chunk directory in an extension ROM is identical to that in an expansion
card - see the chapter "Expansion Cards: Technical Details" in the RISC OS
Programmer's Reference Manual.
In extension ROMs which are directly executable (ie which are 32 bits wide),
the word immediately preceding the start of each module must contain (size
of module +4), ie an offset from itself to the first word after the module.
It is recommended that all extension ROMs be created like this, irrespective
of whether they are directly executable.
Additional interfaces to support extension ROMs
Changes to Podule manager
The Podule manager module is responsible for recognising extension ROMs,
although it is the kernel which is responsible for loading modules contained
in them.
The numbering scheme for expansion card slots has been extended to include
extension ROMs. The numbers for extension ROMs are -2, -3, -4... (-1 is
reserved for the main ROM, although the Podule manager itself does not
accept -1 for any of its SWI calls).
All Podule manager SWIs which take an expansion card slot number as a
parameter allow an extension ROM specifier instead.
The SWIs Podule_ReadID, Podule_ReadHeader, Podule_EnumerateChunks,
Podule_ReadChunk operate as one would expect when presented with an
extension ROM specifier.
The SWIs Podule_ReadBytes, Podule_WriteBytes, Podule_CallLoader will
normally fail because extension ROMs have no code space or loader.
SWI Podule_RawRead will read successive bytes out of the extension ROM,
taking the ROM width into account.
SWI Podule_RawWrite must not be used with an extension ROM specifier, as
writing to the ROM area can reprogram the memory and video controllers.
SWI Podule_HardwareAddress returns the base address of the specified
extension ROM, although this is not in general useful as the ROM width can
New SWIs
SWI Podule_EnumerateChunksWithInfo
in: R0 = chunk number (zero to start)
R3 = expansion card slot number or extension ROM number
out: R0 = next chunk number (zero if final chunk enumerated)
R1 = size (in bytes) if R0<>0 on exit
R2 = operating system identity byte if R0<>0 on exit
R4 = pointer to a copy of the module name if the chunk is a relocatable module, else preserved
R5 = pointer to a copy of the module's help string if the chunk is a relocatable module, else preserved
R6 = address of module if the chunk is a directly executable relocatable module
or 0 if the chunk is a non-directly-executable relocatable module
else preserved
SWI Podule_HardwareAddresses
in: R3 = expansion card slot number or extension ROM number
out: R0 = raw hardware address
R1 = combined hardware address
For an expansion card, the "raw hardware address" is the base address of the
expansion card, and the "combined hardware address" is the raw hardware
address (in bits 12-25) combined with the base address of the expansion
card's private CMOS RAM (in bits 0-11) (as returned by SWI
For an extension ROM, the two addresses are the same, and are the start
address of the extension ROM (ie the address of the first byte of the ROM).
Star commands
*Podules now displays the extension ROMs in the system as well as expansion cards.
Changes to kernel
SWI OS_Module
OS_Module 17 (Add expansion card module) - This call now allows R3 to be
either an expansion card slot number or an extension ROM number.
OS_Module 19 (Enumerate ROM modules) - This call now enumerates
over all ROM sections, ie extension ROM modules as well as main ROM and
expansion card modules. R2 on entry now specifies the ROM section number to
start scanning from, with the order of enumeration as follows:-
-1 (main ROM), 0, 1, 2, 3 (expansion cards), -2, -3, -4,... (extension ROMs)
Edition 1 of the PRM is incorrect when it states that on exit R1 (the
module number to scan from) is incremented and R2 (the expansion card number
to scan from) is preserved.
In fact R1 returns the module number of the found module plus one, where
modules are numbered from zero within each ROM section, and R2 returns the
ROM section number of the found module, which may be in a different ROM
section from the value passed in R2 on entry, if there are insufficient
modules in the specified section.
The values returned in R1 and R2 are therefore set up for the next call to
OS_Module 19.
The call returns the error "No more modules" (error number &107) if there
are no more modules from the point specified in the ordering.
New call
OS_Module 20 (Enumerate ROM modules with version)
This call is identical to OS_Module 19, except that on exit R6 holds a BCD
(binary coded decimal) form of the module's version number, as derived from
the module's help string. The top 16 bits of this value hold the integer
part of the version number, and the bottom 16 bits hold the fractional part,
eg if the version number of the module is "3.14" then the value returned
would be &00031400.
Module initialisation
The way in which the kernel initialises modules has been changed. If there
is more than one version of the same module present in the ROM (which
includes all ROM sections) then only the newest version of the module is
initialised, where newest means the version with the highest version number.
(If there are two copies of the same version, then directly executable
versions (ie in main ROM or in a 32-bit wide extension ROM) are considered
"newer". If they are equal in this respect, then the later one in scanning
order is considered to be newer.)
The kernel first scans down the list of modules in the main ROM. For each
module in this list, the kernel initialises the newest version of that
For each module in the main ROM, the newest version of that module
If an extension ROM contains a newer version of a module in the
main ROM, then the newer version will be initialised at the point in the
initialisation sequence where the main ROM version would have been
initialised. This allows main ROM modules to be replaced without the
problems associated with initialisation order.
The kernel then applies the same rule to all of the expansion cards in turn.
In each case the newest version of the module is initialised, but with the
hardware address (in R11) corresponding to that of the expansion card.
The kernel finally initialises any extension ROM modules that are the newest
versions, but which have not already been initialised in lieu of a module in the
main ROM or on an expansion card.
Star commands
*ROMModules now displays the version number of each module, as well as the
other information. Extension ROM modules are now included in the list. Note
that extension ROMs are numbered 1, 2, 3... in this command - these
correspond to ROM section numbers -2, -3, -4... respectively.
*Unplug can now unplug extension ROM modules, as well as modules in the main
ROM or in expansion cards. The syntax is now
*Unplug [<moduletitle> [<ROM section number>]]
*Unplug with no parameters does the same as it used to, ie display any
unplugged modules.
*Unplug with a module name but no ROM section number specified unplugs all
versions of that module in the system, and kills off any active module of
that name.
If a ROM section number is specified then only versions of that module
in that ROM section are unplugged.
The action of *RMReInit has changed slightly. If the specified module is
active, then the effect is as before, ie the module is killed and then
If the specified module is not active, but is in the ROM, then the unplug
bit in CMOS RAM is cleared for all versions of the specified module, and
then the newest version of the module is initialised.
New star command
*RMInsert <moduletitle> [<ROM section number>]
If no ROM section number is specified, then this command clears the unplug
bit for all versions of the specified module, without reinitialising any of
If a ROM section number is specified, then this command clears the unplug
bit for all versions of the specified module present in the given section,
without reinitialising any of them.
000 App space
01C System heap/svc stack
01E Soft CAM copy/und stack
01F Sound/pointer/random
020 RMA
02C L2PT and L1PT
030 I/O
038 ROM
040 Screen
060 Free pool
0E2 Sprites
164 Font cache
1E6 RAM disc
268 Another area 1
2EA Another area 2
36C Another area 3
3EE Another area 4
470 Another area 5
4F2 Another area 6
574 Another area 7
5F6 Another area 8
678 Another area 9
6FA Another area 10
77C Another area 11
7FE Nothing
800 Phys space copy
A00 Another area 12
A82 Another area 13
B04 Another area 14
B86 Another area 15
C08 Another area 16
C8A Another area 17
D0C Another area 18
D8E Another area 19
E10 Another area 20
E92 Another area 21
F14 Another area 22
F96 Nothing
000 App space
01C System heap/svc stack
01E Soft CAM copy/und stack
01F Sound/pointer/random
020 RMA
02C L2PT and L1PT
030 I/O
038 ROM
040 Screen
060 Free pool
162 Sprites
264 Font cache
366 RAM disc
468 Another area 1
56A Another area 2
66C Another area 3
76E Nothing
800 Phys space copy
A00 Another area 4
B02 Another area 5
C03 Another area 6
D04 Another area 7
E05 Another area 8
F06 Nothing
; > 5thColumn.Concept
RISC OS Support for extension ROMs
Author: Tim Dobson
Status: Draft
Issue: 0.02
Date Revision Changes
11-Oct-90 0.00 Started
16-Oct-90 0.01 Completed first draft
04-Feb-91 0.02 Updated to reflect reality
This document describes the purpose of the extension ROM system and
discusses various design issues. For the full technical documentation, refer
to the document "5thColumn.Manual".
The extension ROM system allows the development of hardware platforms fitted
with a normal 32 bit wide RISC OS ROM set plus one or more 8, 16 or 32 bit
ROMs or EPROMs containing software modules which add to or replace modules
in the main ROM set. This allows the same main ROM set to be used in a wider
variety of hardware platforms, removing the extra cost and lead times of
re-romming, and possibly reducing costs by allowing bulk purchase of the
main ROM set.
The extension ROM(s) appear in the memory map in unused parts of the low
(&03400000 to &037FFFFF) or high (&03800000 to &03FFFFFF) ROM areas. A 32
bit wide extension ROM set is directly executable in place, saving on user
RAM. 8 or 16 bit wide sets have to be copied into RAM to execute. By using
the low ROM area (whose access time is programmable independently from the
high area containing the main ROM set) slow EPROMs can be used.
A particularly attractive configuration might be to have 8 ROM sockets on
the board, 4 for the main ROM set, and the other 4 capable of taking either
one 32 bit wide set (eg a large set of applications eg Internet) or up to 4
individual 8 bit wide ROMs containing smaller applications or utilities.
The scheme also allows a machine to have limited protection against
unauthorised access, if the extension ROM contains a module which requires a
password to be entered before continuing.
In order to allow different sizes of EPROMs to be used without having to
have links on the board, the software will look for extension ROMs at higher
addresses first, and work backwards. This means that the high order address
lines (which should be tied to +5v on smaller sizes of EPROM) will be pulled
high initially, although they will be pulled low later on when looking for
further extension ROMs.
The way in which the kernel initialises modules has been changed. If there
is more than one version of the same module present in the ROM (which
includes the main ROM, expansion card ROMs and extension ROMs) then only the
newest version of the module is initialised. If an extension ROM contains a
newer version of a module in the main ROM, then the newer version will be
initialised at the point in the initialisation sequence where the main ROM
version would have been initialised. This allows main ROM modules to be
replaced without the problems associated with initialisation order.
; > PrivDoc.MMPM
Still to do on memory management, as of 26-May-93:
; Must be TMD
+ Make SoftCAMMap variable size
+ Finish routine to allocate backing L2 for an area
+ Write routine to allocate logical addresses for areas
+ Write routine to check for overlapping areas
+ Complete Create dynamic area routine
(done apart from final OS_ChangeDynamicArea to get required size)
+ Write Remove dynamic area routine
(done apart from initial OS_ChangeDynamicArea to shrink to zero size)
+ Write Return info on dynamic area routine
+ Write Enumerate dynamic areas routine
+ Write Renumber dynamic areas routine
+ Change OS_ReadDynamicArea to use new list
+ Change OS_ValidateAddress to use new list
+ Put in new error messages properly
* If CreateArea fails to grow area to required size, it should kill area and return error
* Change ChangeDynamicArea code to use lists:
+ Check enough is working for Wimp_ClaimFreeMemory to use OS_DynamicArea(create)
* Check PreShrink and PostShrink work completely OK
* Check PreGrow and PostGrow work (apart from passing in page blocks)
* Migrate existing areas to new world:
* Update InitDynamicAreas initially to fake up a node for the RMA, and check it works
* Use DynamicArea_Create to create RMA from scratch (if feasible)
* Update InitDynamicAreas to fake up a node for the system heap + check it (no way of using create routine)
* Change OS_ReadRAMFsLimits to use OS_ReadDynamicArea
* Write RAMFS area handlers
* Create RAMFS dynamic area using DynamicArea_Create, + check it works
* Do similar for font cache, sprite area
* Put in code to split grow block into chunks, and create page blocks (without checking for updates from PreGrow)
* Put in checks for PreGrow requesting particular pages, and call alternative code:
* Do the double shuffle
* Issue Service_PagesUnsafe/Safe
* Stop it getting the static pages (esp. cursor/sound page, L1 and maybe L2)
* Put in extra code to cope with doubly-mapped areas
* Write area handlers for screen, and move it to new world
* Change size of application space to 24M (check all refs to 16M in whole image)
* Put in indirections for hardware vector poking
* Change FPE to use indirections (KWelton)
* Move RMA to &02100000, and change size of app space to 28M
* Conversion to do late aborts
; Could be done by ANOther
* OS_Memory:
a) conversion bits
b) read phys.memory arrangement
c) read amounts of various sorts of memory
d) read controller addresses
\ No newline at end of file
; > PrivDoc.ScreenMode
Still to do on screen mode selection, as of 21-Jul-93:
Key: + Done and tested
- Done but not tested
* Still to do
x Not done for a good reason
+ Make OS_ReadModeVariable work with mode selectors
+ OS_ScreenMode(ReturnMode)
+ OS_ScreenMode(EnumerateModes)
+ Create variable holding video bandwidth
+ Add this reason code to just load up video bandwidth, VideoSize and issue service
+ Service_ModeExtension additions
+ Load up r4 and r5 with video bandwidth, VideoSize respectively
+ Change vdugrafg:SetUpSprModeData:04 to check for mode selector, and goto 10 if so
+ Check other occurrences of BranchIfKnownMode to look for similar bits
+ Put code to handle new sprite mode word into PushModeInfo (any monitor only?)
+ Remove new sprite mode word fudging in vdugrafg:SetupSprModeData and
+ Make SwitchOutputToSprite(new format) set up ECFIndex (it doesn't at the moment!)
+ Make sure tests for equal mode numbers don't assume equal ptrs to mode selectors are equivalent
+ Modify NewModes module to respond to Service_EnumerateScreenModes, to test enumeration.
+ OS_ScreenMode(SetMonitorType)
+ Allocate soft copy for monitortype
+ Write routine to update soft copy from CMOS
+ Call this routine in initialisation
+ Make *Configure MonitorType update soft copy
+ Change ReadMonitorType to read from soft copy
+ Add this reason code to either store given value or update from CMOS
+ Make sprites which have mode selectors as their mode word illegal
+ Move conversion of mode selectors to new format sprite mode words
into PreCreateHeader, rather than PostCreateHeader, so that it
doesn't call SetupSprModeData with a (now illegal) mode selector
-> MT ScreenModes module
-> AG Make switch output to sprite for a new format sprite make mode selector for current mode?
-> AG *ScreenSave in mode 50 seems to produce a sprite with a palette.
-> NK Trying to set a WimpMode with XEigFactor=27 caused data abort.
Investigate and/or range-limit values.
-> AG Put in support for returning errors from PushModeInfo (for bad mode
selectors and new format sprite mode words):
+ Make mode change routine check for error from PushModeInfo and FindOKMode
+ Make FindSubstitute check errors from PushModeInfo
+ Make FindOKMode check errors from FindSubstitute
+ Make CheckModeValid check errors from FindOKMode
+ Make SetupSprModeData capable of returning errors:
+ Ditto SpriteV handler (already OK)
+ Ditto PreCreateHeader
+ Ditto CreateHeader
+ Ditto GetSprite
-> AG Make SwitchOutputToSprite/Mask check errors from PushModeInfo
- Design and code algorithm for working out FIFO reload position for VIDC20
(Still need explanation from ARM of why 7 quad-words doesn't always work)
* OS_ScreenMode(SelectMode)
+ Make normal mode selection routine into a subroutine
+ Write veneers to put round call to this in OS_ScreenMode(SelectMode)
* Change actual mode change code to cope with mode selectors
+ Prevent main routine looking at shadow bit in mode selector
+ Modify FindOKMode to cope with mode selector
+ Modify OS_CheckModeValid to cope with mode selector
+ Make all pushed mode variables into words (not bytes)
+ Modify PushModeInfo to cope with mode selector
+ Make YEigFactor default to 2 if yres < xres/2 (and change spec. to reflect that)
+ Make numbered modes work after loading mode file
+ Allocate space for OS copy of mode selector
x Make OS mode selector part of saved VDU context
(not needed since sprites can't have mode selectors as their mode)
x Sort out internal mode variables PalIndex, ECFIndex wrt
converting existing mode numbers into mode selectors (no need, still use old workspace-getting code)
x Make mode selector blocks for all existing numbered modes
(no need, constructed on fly since only needed during svc call)
* Check that copying mode selector has no adverse effects
* Sort out why issuing a mode change with invalid mode selector doesn't give error
* Modify FindOKMode to cope with 16 and 32 bpp modes somehow
* Prevent pointer position from going into the sync pulse (causes screen picture disruption)
* Adjust borders on all modes, to cope with VIDC20 problem
(Needs algorithm from ARM that works!)
* Mode change happily passes round any old rubbish to Service_ModeExtension - it should:-
* First check that value is word-aligned - if not it may be a new sprite mode word
* Do a Validate_Address on fixed bit of block?
* What should *ScreenLoad do with a new format sprite?
......@@ -276,7 +276,7 @@ Usage:
void *RISCOS_AccessPhysicalAddress(unsigned int flags, void *phys, void **oldp)
void *RISCOS_AccessPhysicalAddress(unsigned int flags, uint64_t phys, void **oldp)
flags: bit 2 => make memory bufferable
other bits must be zero
......@@ -294,7 +294,7 @@ On exit:
Arranges for the physical address phys to be mapped in to logical memory.
In fact, the whole megabyte containing "phys" is mapped in (ie if phys =
In fact, at least the whole megabyte containing "phys" is mapped in (ie if phys =
&12345678, then &12300000 to &123FFFFF become available). The memory is
supervisor access only, non-cacheable, non-bufferable by default, and will
remain available until the next call to RISCOS_Release/AccessPhysicalAddress
......@@ -321,14 +321,16 @@ Usage:
void *old;
unsigned int *addr = (unsigned int *) 0x80005000;
unsigned int *addr2 = (unsigned int *) 0x90005000;
uint64_t addr_physical = (uint64_t) 0x80005000;
uint64_t addr2_physical = (uint64_t) 0x90005000;
uint32_t *addr_logical;
uint32_t *addr2_logical;
addr = (unsigned int *) RISCOS_AccessPhysicalAddress(addr, &old);
addr[0] = 3; addr[1] = 5;
addr_logical = (unsigned int *) RISCOS_AccessPhysicalAddress(0, addr_physical, &old);
addr_logical[0] = 3; addr_logical[1] = 5;
addr2 = (unsigned int *) RISCOS_AccessPhysicalAddress(addr2, NULL);
*addr2 = 7;
addr2_logical = (unsigned int *) RISCOS_AccessPhysicalAddress(0, addr2_physical, NULL);
*addr2_logical = 7;
......@@ -1029,7 +1029,22 @@ It returns the resultant virtual address corresponding to phys, or 0 for
failure. Failure can only occur if no RAM is available for page tables, or
if the virtual address space is exhausted.