From 7d4000d992b59f06110750273038aec5ce1301bc Mon Sep 17 00:00:00 2001
From: Ben Avison <bavison@gitlab.riscosopen.org>
Date: Fri, 3 Jun 2011 22:47:18 +0000
Subject: [PATCH] Initial import of S3C6410 HAL

Detail:
  The S3C6410 HAL is aimed at the Mini6410 board. There's a major bug
  somewhere which prevents the FP emulator from working (crashes on
  initialisation), and the interrupt handling is broken (which is believed to
  break USB). But video works (hardwired to 480x272), though the cursor hasn't
  been implemented yet, and the debugging console works.
Admin:
  Code submitted by Tom Walker

Version 0.01. Tagged as 'S3C6410-0_01'
---
 .gitattributes |    2 +
 Makefile       |   97 ++++
 MkClean,fd7    |   16 +
 MkRom,fd7      |   18 +
 VersionNum     |   14 +-
 hdr/StaticWS   |   59 +++
 hdr/Video      |  196 ++++++++
 s/Boot         | 1227 ++++++++++++++++++++++++++++++++++++++++++++++++
 s/IIC          |   66 +++
 s/Interrupts   |  312 ++++++++++++
 s/MachineID    |  245 ++++++++++
 s/NVRAM        |   69 +++
 s/RTC          |  212 +++++++++
 s/Timers       |  115 +++++
 s/Video        | 1177 ++++++++++++++++++++++++++++++++++++++++++++++
 15 files changed, 3818 insertions(+), 7 deletions(-)
 create mode 100644 .gitattributes
 create mode 100644 Makefile
 create mode 100644 MkClean,fd7
 create mode 100644 MkRom,fd7
 create mode 100644 hdr/StaticWS
 create mode 100644 hdr/Video
 create mode 100644 s/Boot
 create mode 100644 s/IIC
 create mode 100644 s/Interrupts
 create mode 100644 s/MachineID
 create mode 100644 s/NVRAM
 create mode 100644 s/RTC
 create mode 100644 s/Timers
 create mode 100644 s/Video

diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1f3dca7
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+hdr/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
+s/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b5118eb
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,97 @@
+# Copyright 2011 Castle Technology Ltd
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Makefile for Kernel
+#
+# ***********************************
+# ***    C h a n g e   L i s t    ***
+# ***********************************
+# Date       Name         Description
+# ----       ----         -----------
+# 25-May-94  AMcC         Created.
+#
+
+#
+# Paths
+#
+EXP_HDR = <export$dir>
+C_EXP_HDR = <cexport$dir>.Global.h
+
+#
+# Generic options:
+#
+MKDIR   = mkdir -p
+AS      = aasm
+ARMASM  = objasm
+CP      = copy
+RM      = remove
+CCFLAGS = -c -depend !Depend -IC:
+ASFLAGS = -depend !Depend ${THROWBACK} -Stamp -quit -To $@ -From
+ARMASMFLAGS = -depend !Depend -g -APCS 3/nofp/noswst ${THROWBACK}
+CPFLAGS = ~cfr~v
+
+TOKENISE = tokenise
+TOKENS   = Hdr:Tokens
+
+#
+# Program specific options:
+#
+COMPONENT = S3C6410
+TARGET    = bin.S3C6410
+DBGTARGET = aif.S3C6410
+GPATARGET = gpa.S3C6410
+EXPORTS   =
+
+OBJECTS   = o.Boot o.Interrupts o.Timers o.Video
+# o.Video o.RTC
+
+.s.o:;	${ARMASM} ${ARMASMFLAGS} $< $@
+
+#
+# Generic rules:
+#
+rom: ${TARGET}
+	@echo ${COMPONENT}: rom module built
+
+debug: ${GPATARGET}
+	@echo ${COMPONENT}: debug module built
+
+install_rom: ${TARGET}
+	${CP} ${TARGET} ${INSTDIR}.${COMPONENT} ${CPFLAGS}
+	@echo ${COMPONENT}: rom module installed
+
+clean:
+	${RM} ROM
+	${RM} ${TARGET}
+	-Wipe o.* ~C~V
+	-Wipe aif.* ~C~V
+	-Wipe gpa.* ~C~V
+	@echo ${COMPONENT}: cleaned
+
+export: ${EXPORTS}
+	@echo ${COMPONENT}: export complete
+
+resources:
+	@echo ${COMPONENT}: nothing to do
+
+${TARGET}: ${OBJECTS}
+	Link -bin -base 0xFC000000 -o $@ ${OBJECTS}
+
+${DBGTARGET}: ${OBJECTS}
+	Link -bin -base 0xFC000000 -aif -d -o $@ ${OBJECTS}
+
+${GPATARGET}: ${DBGTARGET}
+	ToGPA -s ${DBGTARGET} $@
+
+# Dynamic dependencies:
diff --git a/MkClean,fd7 b/MkClean,fd7
new file mode 100644
index 0000000..65ad88f
--- /dev/null
+++ b/MkClean,fd7
@@ -0,0 +1,16 @@
+| Copyright 2011 Castle Technology Ltd
+|
+| Licensed under the Apache License, Version 2.0 (the "License");
+| you may not use this file except in compliance with the License.
+| You may obtain a copy of the License at
+|
+|     http://www.apache.org/licenses/LICENSE-2.0
+|
+| Unless required by applicable law or agreed to in writing, software
+| distributed under the License is distributed on an "AS IS" BASIS,
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+| See the License for the specific language governing permissions and
+| limitations under the License.
+|
+Dir <Obey$Dir>
+amu_machine clean
diff --git a/MkRom,fd7 b/MkRom,fd7
new file mode 100644
index 0000000..04599cc
--- /dev/null
+++ b/MkRom,fd7
@@ -0,0 +1,18 @@
+| Copyright 2011 Castle Technology Ltd
+|
+| Licensed under the Apache License, Version 2.0 (the "License");
+| you may not use this file except in compliance with the License.
+| You may obtain a copy of the License at
+|
+|     http://www.apache.org/licenses/LICENSE-2.0
+|
+| Unless required by applicable law or agreed to in writing, software
+| distributed under the License is distributed on an "AS IS" BASIS,
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+| See the License for the specific language governing permissions and
+| limitations under the License.
+|
+Dir <Obey$Dir>
+time
+amu_machine rom debug THROWBACK=-throwback
+time
diff --git a/VersionNum b/VersionNum
index 71b6320..f56d869 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,15 +1,15 @@
-/* (0.00)
+/* (0.01)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
  * Last processed by srccommit version: 1.1.
  *
  */
-#define Module_MajorVersion_CMHG        0.00
+#define Module_MajorVersion_CMHG        0.01
 #define Module_MinorVersion_CMHG        
 #define Module_Date_CMHG                03 Jun 2011
 
-#define Module_MajorVersion             "0.00"
-#define Module_Version                  0
+#define Module_MajorVersion             "0.01"
+#define Module_Version                  1
 #define Module_MinorVersion             ""
 #define Module_Date                     "03 Jun 2011"
 
@@ -18,6 +18,6 @@
 #define Module_ComponentName            "S3C6410"
 #define Module_ComponentPath            "castle/RiscOS/Sources/HAL/S3C6410"
 
-#define Module_FullVersion              "0.00"
-#define Module_HelpVersion              "0.00 (03 Jun 2011)"
-#define Module_LibraryVersionInfo       "0:0"
+#define Module_FullVersion              "0.01"
+#define Module_HelpVersion              "0.01 (03 Jun 2011)"
+#define Module_LibraryVersionInfo       "0:1"
diff --git a/hdr/StaticWS b/hdr/StaticWS
new file mode 100644
index 0000000..c9c813c
--- /dev/null
+++ b/hdr/StaticWS
@@ -0,0 +1,59 @@
+; Copyright 2011 Castle Technology Ltd
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+;
+sb              RN      9
+
+                ^       0,sb
+OSheader        #       4
+OSentries       #       4*(HighestOSEntry+1)
+UART_Address    #       4
+CLK_Address     #       4
+Timer_Address   #       4
+INT_Address     #       4
+LCD_Address	#	4
+GPIO_Address	#	4
+USB_Address	#	4
+MEM_Address	#	4
+RTC_Address	#	4
+TimerPeriods    #       4*2
+VIDX_Size	#	4
+VID_BPP		#	4
+IOCRSoftCopy    #       1
+IOSystemType    #       1
+IOST_7500 * 1
+                #       2
+
+; workspace for video functions
+;
+VRAMWidth               #    1
+                        #    3
+VIDC_NextPaletteIndex   #    4   ; last index used in setting normal palette entry
+VIDC_SoftPalette0       #    4   ; soft copy of BBGGRRSS for normal palette entry 0
+                                 ; (used to support ReadPaletteEntry)
+VIDC_Interlace          #    4   ; flag from VIDCList3 SyncPol word
+VIDC_VertiDisplaySize   #    4   ; we keep this for vertical pointer clipping
+VIDC_PointerVAdjust     #    4   ; vertical adjust for pointer
+VIDC_PointerHAdjust     #    4   ; horizontal adjust for pointer
+VIDC_ExternalSoftCopy   #    4
+VIDC_FSynSoftCopy       #    4
+VIDC_ControlSoftCopy    #    4
+VIDC_HSWRSoftCopy       #    4   ; horizontal sync width
+VIDC_VSWRSoftCopy       #    4   ; vertical sync width
+IOMD_VInitSoftCopy      #    4
+IOMD_VEndSoftCopy       #    4
+;
+
+HAL_WsSize      *       :INDEX:@
+
+                END
diff --git a/hdr/Video b/hdr/Video
new file mode 100644
index 0000000..48ad069
--- /dev/null
+++ b/hdr/Video
@@ -0,0 +1,196 @@
+; Copyright 2011 Castle Technology Ltd
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+;
+
+; -----------------------------------------------------------------------------------
+
+;
+;VIDC20 parameters size (for table of VIDC20 registers)
+;
+VIDC20ParmsSize * (128*4) ; 128 words from 80xxxxxx to FFxxxxxx step 01000000
+
+;
+; VRAM SAM length in bytes
+;
+SAMLength *     512*4
+
+; -----------------------------------------------------------------------------------
+
+;
+; VIDC20 Registers
+;
+
+VIDCPalAddress          *       &10000000       ; used in palette programming
+
+LCDOffsetRegister0      *       &30000000
+LCDOffsetRegister1      *       &31000000
+
+VIDC20BorderColour      *       &40000000       ; added by mjs
+VIDC20PointerColour     *       &50000000       ; added by mjs
+
+HorizCycle              *       &80000000
+HorizSyncWidth          *       &81000000
+HorizBorderStart        *       &82000000
+HorizDisplayStart       *       &83000000
+HorizDisplayEnd         *       &84000000
+HorizBorderEnd          *       &85000000
+HorizCursorStart        *       &86000000       ; used in pointer programming
+HorizInterlace          *       &87000000
+
+VertiCycle              *       &90000000
+VertiSyncWidth          *       &91000000       ; Needed to set up FSIZE register in IOMD
+VertiBorderStart        *       &92000000       ; First register affected by *TV
+VertiDisplayStart       *       &93000000
+VertiDisplayEnd         *       &94000000
+VertiBorderEnd          *       &95000000
+VertiCursorStart        *       &96000000
+VertiCursorEnd          *       &97000000       ; Last register affected by *TV
+
+VIDCExternal            *       &C0000000
+VIDCFSyn                *       &D0000000
+VIDCControl             *       &E0000000
+VIDCDataControl         *       &F0000000
+
+; Pseudo-registers used to return additional information to kernel
+
+PseudoRegisters         *       5               ; number of pseudo-register entries at end of table
+
+PseudoRegister_HClockSpeed *    &FB000000       ; used to indicate VIDC hclock speed (and use it)
+PseudoRegister_ClockSpeed *     &FC000000       ; used to indicate real VIDC rclock speed
+
+; Bits in VCSR, VCER
+CursorSinglePanel       *       0 :SHL: 13
+CursorTopPanel          *       1 :SHL: 13
+CursorBottomPanel       *       1 :SHL: 14
+CursorStraddle          *       3 :SHL: 13
+
+
+; Bits in external register
+
+Ext_HSYNCbits   *       3 :SHL: 16
+Ext_InvertHSYNC *       1 :SHL: 16
+Ext_CompHSYNC   *       2 :SHL: 16
+Ext_InvertCompHSYNC *   3 :SHL: 16
+Ext_VSYNCbits   *       3 :SHL: 18
+Ext_InvertVSYNC *       1 :SHL: 18
+Ext_CompVSYNC   *       2 :SHL: 18
+Ext_InvertCompVSYNC *   3 :SHL: 18
+Ext_HiResMono   *       1 :SHL: 14
+Ext_LCDGrey     *       1 :SHL: 13
+Ext_DACsOn      *       1 :SHL: 12
+Ext_PedsOn      *       7 :SHL: 8
+Ext_PedsShift   *       8
+Ext_ERegShift   *       4
+Ext_ECKOn       *       1 :SHL: 2
+Ext_ERegBits    *       3 :SHL: 0
+Ext_ERegRed     *       0 :SHL: 0
+Ext_ERegGreen   *       1 :SHL: 0
+Ext_ERegBlue    *       2 :SHL: 0
+Ext_ERegExt     *       3 :SHL: 0       ; use this for lowest power
+
+; Bits in Frequency Synthesizer Register
+
+FSyn_VShift     *       8
+FSyn_RShift     *       0
+FSyn_ClearV     *       1 :SHL: 15
+FSyn_ForceLow   *       1 :SHL: 14
+FSyn_ClearR     *       1 :SHL: 7
+FSyn_ForceHigh  *       1 :SHL: 6
+
+FSyn_ResetValue *       FSyn_ClearV :OR: FSyn_ClearR :OR: FSyn_ForceLow :OR: (63 :SHL: FSyn_RShift) :OR: (0 :SHL: FSyn_VShift)           ; value to get PLL working properly
+
+; Bits in Control Register
+
+CR_DualPanel    *       1 :SHL: 13
+CR_Interlace    *       1 :SHL: 12
+CR_FIFOLoadShift *      8
+CR_LBPP0        *       0 :SHL: 5
+CR_LBPP1        *       1 :SHL: 5
+CR_LBPP2        *       2 :SHL: 5
+CR_LBPP3        *       3 :SHL: 5
+CR_LBPP4        *       4 :SHL: 5
+CR_LBPP5        *       6 :SHL: 5 ; spot the gap!
+CR_PixelDivShift *      2
+CR_VCLK         *       0 :SHL: 0
+CR_HCLK         *       1 :SHL: 0
+CR_RCLK         *       2 :SHL: 0
+
+; Bits in Data Control Register
+
+DCR_VRAMOff     *       0 :SHL: 18
+DCR_VRAMDiv1    *       1 :SHL: 18
+DCR_VRAMDiv2    *       2 :SHL: 18
+DCR_VRAMDiv4    *       3 :SHL: 18
+DCR_BusBits     *       3 :SHL: 16
+DCR_Bus31_0     *       1 :SHL: 16
+DCR_Bus63_32    *       2 :SHL: 16
+DCR_Bus63_0     *       3 :SHL: 16
+DCR_HDis        *       1 :SHL: 13
+DCR_Sync        *       1 :SHL: 12
+DCR_HDWRShift   *       0
+
+; -----------------------------------------------------------------------------------
+
+; mjs - this had better agree with the format specified in kernel s.vdu.vdumodes
+
+;
+; format of a VIDC list type 3
+;
+                                ^       4
+VIDCList3_PixelDepth            #       4
+VIDCList3_HorizSyncWidth        #       4
+VIDCList3_HorizBackPorch        #       4
+VIDCList3_HorizLeftBorder       #       4
+VIDCList3_HorizDisplaySize      #       4
+VIDCList3_HorizRightBorder      #       4
+VIDCList3_HorizFrontPorch       #       4
+VIDCList3_VertiSyncWidth        #       4
+VIDCList3_VertiBackPorch        #       4
+VIDCList3_VertiTopBorder        #       4
+VIDCList3_VertiDisplaySize      #       4
+VIDCList3_VertiBottomBorder     #       4
+VIDCList3_VertiFrontPorch       #       4
+VIDCList3_PixelRate             #       4
+VIDCList3_SyncPol               #       4  ; sync polarity/flag bits
+VIDCList3_ControlList           #       0  ; possibly empty list of pairs of index,value words
+;
+; and VIDCList3 is terminated by a -1 word
+;
+; Indices in VIDCList3_ControlList
+;
+                                ^       1
+ControlList_LCDMode             #       1
+ControlList_LCDDualPanelMode    #       1
+ControlList_LCDOffset0          #       1
+ControlList_LCDOffset1          #       1
+ControlList_HiResMode           #       1
+ControlList_DACControl          #       1
+ControlList_RGBPedestals        #       1
+ControlList_ExternalRegister    #       1
+ControlList_HClockSelect        #       1
+ControlList_RClockFrequency     #       1
+ControlList_DPMSState           #       1
+ControlList_Interlaced          #       1
+ControlList_InvalidReason       #       0
+
+; bits/flags in VIDCList3_SyncPol word:
+;
+SyncPol_InvertHSync        *  1
+SyncPol_InvertVSync        *  2
+SyncPol_InterlaceSpecified *  4   ; if set, interlace bit has been specified, else filled in by kernel
+SyncPol_Interlace          *  8   ; set=interlaced, either specified by service call claimant or filled in from *TV by kernel
+
+; -----------------------------------------------------------------------------------
+
+       END
diff --git a/s/Boot b/s/Boot
new file mode 100644
index 0000000..22aa033
--- /dev/null
+++ b/s/Boot
@@ -0,0 +1,1227 @@
+; Copyright 2011 Castle Technology Ltd
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+;
+        GET     Hdr:ListOpts
+        GET     Hdr:Macros
+        GET     Hdr:System
+        GET     Hdr:Machine.<Machine>
+        GET     Hdr:ImageSize.<ImageSize>
+        $GetCPU
+        $GetIO
+        $GetMEMC
+        $GetMEMM
+        $GetVIDC
+
+
+        GET     Hdr:Proc
+        GET     Hdr:OSEntries
+        GET     Hdr:HALEntries
+
+        GET     hdr.StaticWS
+
+
+
+
+
+DRAM0PhysRam *  &50000000               ; 2 DRAM banks
+DRAM1PhysRam *  &60000000
+
+UARTPhys     *  &7F005000
+
+
+	EXPORT	serial
+; This version assumes a RISC OS image starting 64K after us.
+
+        AREA    |!!!ROMStart|, CODE, READONLY, PIC
+
+        ENTRY
+
+HAL_Base
+
+vectors
+	B	start
+;        LDR     pc, ResetInd            ; Reset
+        LDR     pc, HaltInd             ; Undefined instruction
+        LDR     pc, HaltInd             ; SWI
+        LDR     pc, HaltInd             ; Prefetch abort
+        LDR     pc, HaltInd             ; Data abort
+        LDR     pc, HaltInd             ; (Address exception)
+        LDR     pc, HaltInd             ; IRQ
+        LDR     pc, HaltInd             ; FIQ
+
+ResetInd
+        DCD     0x50100220  ;(start - HAL_Base)+0x30000000
+HaltInd
+        DCD     0x50100028  ;(halt - HAL_Base) +0x30000000
+
+halt    B       halt
+
+        ASSERT  . - HAL_Base < 0x60
+        %       0x60 - (. - HAL_Base)
+ROMsize
+        DCD     0                       ; patched in by build system
+
+HALdescriptor   DATA
+        DCD     0
+        DCD     HAL_Base - HALdescriptor
+        DCD     64*1024
+        DCD     HAL_EntryTable - HALdescriptor
+        DCD     HAL_Entries
+        DCD     HAL_WsSize
+
+        MACRO
+        HALEntry $name
+        ASSERT  (. - HAL_EntryTable) / 4 = EntryNo_$name
+        DCD     $name - HAL_EntryTable
+        MEND
+
+        MACRO
+        NullEntry
+        DCD     HAL_Null - HAL_EntryTable
+        MEND
+
+;        IMPORT   Video_init
+
+        IMPORT   HAL_IRQEnable
+        IMPORT   HAL_IRQDisable
+        IMPORT   HAL_IRQClear
+        IMPORT   HAL_IRQSource
+        IMPORT   HAL_IRQStatus
+;        IMPORT   HAL_FIQEnable
+;        IMPORT   HAL_FIQDisable
+;        IMPORT   HAL_FIQDisableAll
+;        IMPORT   HAL_FIQClear
+;        IMPORT   HAL_FIQSource
+;        IMPORT   HAL_FIQStatus
+
+        IMPORT   HAL_Timers
+        IMPORT   HAL_TimerDevice
+        IMPORT   HAL_TimerGranularity
+        IMPORT   HAL_TimerMaxPeriod
+        IMPORT   HAL_TimerSetPeriod
+        IMPORT   HAL_TimerPeriod
+        IMPORT   HAL_TimerReadCountdown
+
+;        IMPORT   HAL_CounterRate
+;        IMPORT   HAL_CounterPeriod
+;        IMPORT   HAL_CounterRead
+;        IMPORT   HAL_CounterDelay
+
+;        IMPORT   HAL_IICBuses
+;        IMPORT   HAL_IICType
+;        IMPORT   HAL_IICSetLines
+;        IMPORT   HAL_IICReadLines
+
+;        IMPORT   HAL_NVMemoryType
+;        IMPORT   HAL_NVMemorySize
+;        IMPORT   HAL_NVMemoryPageSize
+;        IMPORT   HAL_NVMemoryProtectedSize
+;        IMPORT   HAL_NVMemoryProtection
+;        IMPORT   HAL_NVMemoryIICAddress
+;        IMPORT   HAL_NVMemoryRead
+;        IMPORT   HAL_NVMemoryWrite
+
+ ;       IMPORT   HAL_VideoFlybackDevice
+ ;       IMPORT   HAL_Video_SetMode
+        IMPORT   HAL_Video_WritePaletteEntry
+        IMPORT   HAL_Video_WritePaletteEntries
+ ;       IMPORT   HAL_Video_ReadPaletteEntry
+ ;       IMPORT   HAL_Video_SetInterlace
+ ;       IMPORT   HAL_Video_SetBlank
+ ;       IMPORT   HAL_Video_SetPowerSave
+ ;       IMPORT   HAL_Video_UpdatePointer
+        IMPORT   HAL_Video_SetDAG
+        IMPORT   HAL_Video_VetMode
+        IMPORT   HAL_Video_PixelFormats
+        IMPORT   HAL_Video_Features
+        IMPORT   HAL_Video_BufferAlignment
+        IMPORT   HAL_Video_OutputFormat
+
+;	IMPORT   HAL_ATAControllerInfo
+;	IMPORT   HAL_ATASetModes
+;	IMPORT   HAL_ATACableID
+        ;IMPORT   HAL_MatrixColumns
+        ;IMPORT   HAL_MatrixScan
+
+;        IMPORT HAL_MachineID
+
+	EXPORT  serial2
+	EXPORT	serialn
+	EXPORT  serial8
+	EXPORT	serials
+
+ ;	IMPORT 	RTC_Init
+
+HAL_EntryTable  DATA
+        HALEntry  HAL_Init
+
+        HALEntry HAL_IRQEnable
+        HALEntry HAL_IRQDisable
+        HALEntry HAL_IRQClear
+        HALEntry HAL_IRQSource
+        HALEntry HAL_IRQStatus
+        NullEntry ;HAL_FIQEnable
+        NullEntry ;HAL_FIQDisable
+        NullEntry ;HAL_FIQDisableAll
+        NullEntry ;HAL_FIQClear
+        NullEntry ;HAL_FIQSource
+        NullEntry ;HAL_FIQStatus
+
+        HALEntry HAL_Timers
+        HALEntry HAL_TimerDevice
+        HALEntry HAL_TimerGranularity
+        HALEntry HAL_TimerMaxPeriod
+        HALEntry HAL_TimerSetPeriod
+        HALEntry HAL_TimerPeriod
+        HALEntry HAL_TimerReadCountdown
+
+        NullEntry ;HAL_CounterRate
+        NullEntry ;HAL_CounterPeriod
+        NullEntry ;HAL_CounterRead
+        NullEntry ;HAL_CounterDelay
+
+        NullEntry ;HAL_NVMemoryType
+        NullEntry ;HAL_NVMemorySize
+        NullEntry ;HAL_NVMemoryPageSize
+        NullEntry ;HAL_NVMemoryProtectedSize
+        NullEntry ;HAL_NVMemoryProtection
+        NullEntry ;HAL_NVMemoryIICAddress
+        NullEntry ;HAL_NVMemoryRead
+        NullEntry ;HAL_NVMemoryWrite
+
+        NullEntry ;HAL_IICBuses
+        NullEntry ;HAL_IICType
+        NullEntry ;HAL_IICSetLines
+        NullEntry ;HAL_IICReadLines
+        NullEntry ;HAL_IICDevice
+        NullEntry ;HAL_IICTransfer
+        NullEntry ;HAL_IICMonitorTransfer
+
+        NullEntry ;HAL_VideoFlybackDevice
+        NullEntry ;HAL_Video_SetMode
+        HALEntry HAL_Video_WritePaletteEntry
+        HALEntry HAL_Video_WritePaletteEntries
+        NullEntry ;HAL_Video_ReadPaletteEntry
+        NullEntry ;HAL_Video_SetInterlace
+        NullEntry ;HAL_Video_SetBlank
+        NullEntry ;HAL_Video_SetPowerSave
+        NullEntry ;HAL_Video_UpdatePointer
+        HALEntry HAL_Video_SetDAG
+        HALEntry HAL_Video_VetMode
+        HALEntry HAL_Video_PixelFormats
+        HALEntry HAL_Video_Features
+        HALEntry HAL_Video_BufferAlignment
+        HALEntry HAL_Video_OutputFormat
+
+        NullEntry ;HAL_MatrixColumns
+        NullEntry ;HAL_MatrixScan
+
+        NullEntry ;HAL_TouchscreenType
+        NullEntry ;HAL_Touchscreenread
+        NullEntry ;HAL_Touchscreenread
+        NullEntry ;HAL_Touchscreenread
+
+        NullEntry ;HAL_MachineID
+
+        NullEntry ;HAL_ControllerAddress
+        HALEntry HAL_HardwareInfo
+        HALEntry HAL_SuperIOInfo
+        HALEntry HAL_PlatformInfo
+        NullEntry ;HAL_CleanerSpace
+
+        NullEntry ;HAL_UARTPorts
+        NullEntry ;HAL_UARTStartUp
+        NullEntry ;HAL_UARTShutdown
+        NullEntry ;HAL_UARTFeatures
+        NullEntry ;HAL_UARTReceiveByte
+        NullEntry ;HAL_UARTTransmitByte
+        NullEntry ;HAL_UARTLineStatus
+        NullEntry ;HAL_UARTInterruptEnable
+        NullEntry ;HAL_UARTRate
+        NullEntry ;HAL_UARTFormat
+        NullEntry ;HAL_UARTFIFOSize
+        NullEntry ;HAL_UARTFIFOClear
+        NullEntry ;HAL_UARTFIFOEnable
+        NullEntry ;HAL_UARTFIFOThreshold
+        NullEntry ;HAL_UARTInterruptID
+        NullEntry ;HAL_UARTBreak
+        NullEntry ;HAL_UARTModemControl
+        NullEntry ;HAL_UARTModemStatus
+        NullEntry ;HAL_UARTDevice
+
+        NullEntry ;HAL_Reset
+        HALEntry  HAL_DebugRX
+        HALEntry  HAL_DebugTX
+
+        NullEntry ;HAL_PCIFeatures
+
+        NullEntry ;HAL_PCIReadConfigByte
+        NullEntry ;HAL_PCIReadConfigHalfword
+        NullEntry ;HAL_PCIReadConfigWord
+        NullEntry ;HAL_PCIWriteConfigByte
+        NullEntry ;HAL_PCIWriteConfigHalfword
+        NullEntry ;HAL_PCIWriteConfigWord
+        NullEntry ;HAL_PCISpecialCycle
+        NullEntry ;HAL_PCISlotTable
+        NullEntry ;HAL_PCIAddresses
+
+        NullEntry ;HAL_ATAControllerInfo
+        NullEntry ;HAL_ATASetModes
+        NullEntry ;HAL_ATACableID
+
+        HALEntry HAL_InitDevices
+
+        NullEntry ;HAL_KbdScanSetup
+        NullEntry ;HAL_KbdScan
+        NullEntry ;HAL_KbdScanFinish
+        NullEntry ;HAL_KbdScanInterrupt
+
+	NullEntry ;HAL_PhysInfo
+
+	HALEntry  HAL_USBControllerInfo
+
+	NullEntry ;HAL_MonitorLeadID
+	NullEntry ;HAL_Video_Render
+
+	NullEntry ;HAL_USBPortPower
+	NullEntry ;HAL_USBPortStatus
+	NullEntry ;HAL_USBPortIRQ
+
+	NullEntry ;HAL_Video_IICOp
+
+HAL_Entries     * (.-HAL_EntryTable)/4
+
+; R11 is used as pointer to RISC OS entry table throughout pre-MMU stage.
+        MACRO
+        CallOSM $entry, $reg
+        LDR     ip, [v8, #$entry*4]
+        MOV     lr, pc
+        ADD     pc, v8, ip
+        MEND
+
+        MACRO
+        CallOS  $entry
+        ASSERT  $entry <= HighestOSEntry
+        MOV     lr, pc
+        LDR     pc, OSentries + 4*$entry
+        MEND
+
+
+start   MOV	R1,#65
+	BL 	serial
+
+	B realstart
+
+crashit B crashit
+
+serial	MOV 	R0,#0x7F000000
+	ORR     R0,R0,#0x5000
+	LDR	R2,[R0,#16]
+	TST     R2,#2
+	BEQ 	serial
+
+	STR	R1,[R0,#32]
+
+	MOV 	PC,LR
+
+serial2	LDR	R2,[R0,#16]
+	TST     R2,#2
+	BEQ 	serial2
+
+	STR	R1,[R0,#32]
+
+	MOV 	PC,LR
+
+realstart
+	ADRL    R5, HAL_Base + 64*1024          ; R5 -> RISC OS image
+
+        LDR     R11, [R5, #OSHdr_Entries]
+        ADD     R11, R11, R5                    ; R11 -> RISC OS entry table
+
+;	MOV	R1,#65
+;	BL      serial
+
+;	MOV 	R1,#66
+;	BL	serial
+
+        MOV     R0, #0
+        CallOSM OS_InitARM
+
+;	MOV 	R1,#66
+;	BL	serial
+
+;	MOV	a1,#0x48000000
+;	MOV	a2,#0xB0
+;	STR	a2,[a1,#0x28]
+
+	MOV	a1,#0
+	MOV	a2,#0x50000000
+	ADD	a2,a2,#0x500000
+;	ADD	a2,a2,#0x00400000
+	MOV	a3,#0x00800000
+	ADD	a3,a3,a2
+	MOV	a4,#-1
+
+	ADD	sp,a2,#4096
+	STR	a1,[sp,#-4]!
+	CallOSM	OS_AddRAM
+
+
+;	MOV	R1,#65
+;	Push	"R1"
+;	MOV	R1,#0
+;	Pull	"R1"
+;;	BL 	serial
+
+;	MOV	a2,#0x38000000
+;	MOV	a3,#0x00800000
+;	ADD	a3,a3,a2
+;	MOV	a4,#-1
+
+;	STR	a1,[sp,#-4]!
+;	MOV	a1, #0
+;	CallOSM	OS_AddRAM
+
+
+;	MOV	R1,#67
+;	BL	serial
+
+	ADRL    R1, HAL_Base + 64*1024
+	ADRL	R2, HALdescriptor
+	MOV	R3, R0
+	MOV	R0, #13
+	CallOSM	OS_Start
+	;B crashit
+;
+;
+;        MOV     R1, R5
+;        ADRL    R2, HALdescriptor
+;
+;        CallOSM OS_Start
+
+serial8 STMDB   sp!,{r1,r3,lr}
+        MOV 	r3,#28
+s8l     MOV	r1,r4,LSR r3
+	AND	r1,r1,#15
+	CMP	r1,#10
+	ADDCC	r1,r1,#48
+	ADDCS	r1,r1,#55
+	BL	serial2
+	SUBS	r3,r3,#4
+	BPL 	s8l
+
+	MOV	r1,#13
+	BL	serial2
+	MOV	r1,#10
+	BL	serial2
+
+	LDMIA	sp!,{r1,r3,pc}
+
+serial3	MOV	r0,#0x50000000
+	B	serial2
+
+serials STMDB 	sp!,{r1,r3,lr}
+ssl	LDRB	r1,[r4],#1
+	TST	r1,r1
+	BEQ	sdone
+	BL	serial2
+	B ssl
+
+sdone   LDMIA	sp!,{r1,r3,pc}
+
+serialn STMDB 	sp!,{lr}
+	MOV	r1,#13
+	BL	serial2
+	MOV	r1,#10
+	BL	serial2
+	LDMIA	sp!,{pc}
+
+Timer_txt = "Timer Address = "
+	= 0
+UART_txt = "UART Address = "
+	 = 0
+INT_txt  = "INT Address = "
+	 = 0
+CLK_txt	 = "CLK Address = "
+	 = 0
+LCD_txt	 = "LCD Address = "
+	 = 0
+MEM_txt	 = "MEM Address = "
+	 = 0
+CLKs_txt = "MPLLCON = "
+	 = 0
+CLKd_txt = "CLKDIVN = "
+	 = 0
+CLKc_txt = "CLOCKCON = "
+	 = 0
+GPIO_txt = "GPIO = "
+	 = 0
+Ready	 = "HAL_Init complete"
+	 = 0
+
+	ALIGN
+
+HAL_Init
+        Entry
+
+	STMDB	sp!,{r0-r1}
+
+;	MOV	r0,#0x50000000
+;	MOV	r1,#65
+;	BL	serial
+;	MOV	r1,#66
+;	BL	serial
+;
+;	MOV	r1,#13
+;	BL	serial
+;	MOV	r1,#10
+;	BL 	serial
+;
+	LDMIA	sp!,{r0-r1}
+
+        BL      SetUpOSEntries
+
+;	MOV     r1,#67
+;	BL      serial
+
+;	MOV	r0,#10
+;	BL	serial
+;	MOV	r1,#13
+;	BL	serial
+
+;;HL_halt
+;	B 	HL_halt
+;	ADRL	r1,OSentries
+;	BL	serial8
+;;
+;	MOV	r1,#13
+;	BL	serial
+;	MOV	r1,#10
+;	BL 	serial
+;
+;        MOV	r4,pc
+;	BL	serial8
+;
+;	MOV	r1,#13
+;	BL	serial
+;;	MOV	r1,#10
+ ;	BL 	serial
+
+;	LDR	r4,OSentries+4*OS_MapInIO
+;	BL	serial8
+
+;;	MOV	r1,#13
+;	BL	serial
+;	MOV	r1,#10
+;	BL 	serial
+
+        MOV     a1, #0		;Map in UART
+        LDR     a2, =0x7F005000
+        MOV     a3, #0x1000
+        CallOS  OS_MapInIO
+
+	STR	a1,UART_Address
+	MOV	a2,#0
+	STR	a2,[a1,#8]
+
+;;	MOV 	r1, #13
+;	BL	serial3
+;	MOV	r1, #10
+;	BL 	serial3
+
+	ADR	r4,UART_txt
+	MOV	r0,a1
+	BL 	serials
+	MOV	r4, a1
+	MOV	r0, r4
+	BL	serial8
+
+	;LDR	r4,UART_Address
+	;BL	serial8
+
+        ;MOV     a1, #0		;Map in MEMCTRL
+        ;MOV     a2, #0x48000000
+        ;MOV     a3, #0x100000
+        ;CallOS  OS_MapInIO
+	;STR	a1,MEM_Address
+
+	;ADR	r4,MEM_txt
+	;LDR	r0,UART_Address
+	;BL 	serials
+	;MOV	r4, a1
+	;MOV	r0, r4
+	;BL	serial8
+
+	;LDR	r4,MEM_Address
+	;BL	serial8
+        ;
+        ;MOV     a1, #0		;Map in CLK
+        ;MOV     a2, #0x4C000000
+        ;MOV     a3, #0x100000
+        ;CallOS  OS_MapInIO
+        ;
+	;STR	a1,CLK_Address
+        ;
+	;ADR	r4,CLK_txt
+	;LDR	r0,UART_Address
+	;BL	serials
+        ;
+	;LDR	r4,CLK_Address
+	;BL	serial8
+        ;
+        ;
+	;ADR	r4, CLKs_txt
+	;BL	serials
+	;LDR	r5,CLK_Address
+	;LDR	r4,[r5,#4]
+	;BL 	serial8
+        ;
+	;ADR	r4, CLKd_txt
+	;BL	serials
+	;LDR	r5,CLK_Address
+	;LDR	r4,[r5,#0x14]
+	;BL 	serial8
+        ;
+	;ADR	r4, CLKc_txt
+	;BL	serials
+	;LDR	r5,CLK_Address
+	;LDR	r4,[r5,#0x0C]
+	;BL 	serial8
+        ;
+        MOV     a1, #0		;Map in TIMER
+        LDR     a2, =0x7F006000
+        MOV     a3, #0x1000
+        CallOS  OS_MapInIO
+	STR	a1, Timer_Address
+
+	ADRL	r4,Timer_txt
+	LDR	r0,UART_Address
+	BL	serials
+
+	LDR	r4,Timer_Address
+	BL	serial8
+
+	LDR	r0,Timer_Address
+
+;Set up timer
+;PCLK = 66mhz ish
+	;MOV	r0, a1
+	MOV	r1, #0xF00 	;Prescaler
+	STR	r1, [r0]
+	MOV	r1, #0     	;Divider
+	STR	r1, [r0,#4]
+	MOV	r1, #0xFF00	;Time
+	STR	r1, [r0,#0x3C]
+	MOV	r1, #0x600000 	;Control
+	STR	r1, [r0,#8]
+	MOV	r1, #0x400000 	;Control
+	STR	r1, [r0,#8]
+	MOV	r1, #0x500000 	;Control
+	STR	r1, [r0,#8]
+	MOV	r1, #0x210	;Interrupt enable
+	STR	r1, [r0,#0x44]
+
+;Timer base now = 66/16 = 4.1mhz
+
+
+        MOV     a1, #0		;Map in INT
+        LDR     a2, =0x71200000
+        MOV     a3,   #0x200000
+        CallOS  OS_MapInIO
+	STR	a1, INT_Address
+
+	ADRL	r4,INT_txt
+	LDR	r0,UART_Address
+	BL	serials
+
+	LDR	r4,INT_Address
+	BL	serial8
+
+	LDR	a1,INT_Address
+
+	MOV	a2,#0
+	STR	a2,[a1,#0xC]
+	MOV	a2,#0xFFFFFFFF
+	STR	a2,[a1,#0x14]
+	STR	a2,[a1,#0x1C]
+	STR     a2,[a1,#0x24]
+	ADD	a1,a1,#0x100000
+	STR	a2,[a1,#0x14]
+	STR	a2,[a1,#0x1C]
+	STR	a2,[a1,#0x24]
+        SUB     a1,a1,#0x100000
+
+;	MOV	a2,#0x18
+	MOV	a3,#0x7C
+        ADD	a1,a1,#0x100
+	ADD	a4,a1,#0x100000
+	MOV	a2,#31
+setlp
+	AND	a2,a2,#31
+
+
+	STR	a2,[a1,a3]
+	ORR	a2,a2,#32
+	STR	a2,[a4,a3]
+	SUB	a2,a2,#1
+	SUBS	a3,a3,#4
+	BNE	setlp
+
+;Set up interrupt controller
+;Just disable everything!
+	;MOV	r0, a1
+        ;MOV	r1, #0
+	;STR	r1, [r0,#4] ;All interrupts in INT mode
+	;STR	r1, [r0,#0xC] ;Normal priorities
+        ;
+	;MOV	r1, #-1
+	;STR	r1, [r0]
+	;STR	r1, [r0,#0x10] ;No interrupts requested
+	;STR	r1, [r0,#0x18] ;No sub interrupts requested
+	;STR	r1, [r0,#8] ;All interrupts masked
+	;STR	r1, [r0,#0x1C] ;All sub interrupts masked
+
+        ;
+        ;MOV     a1, #0		;Map in GPIO
+        ;MOV     a2, #0x56000000
+        ;MOV     a3, #0x100000
+        ;CallOS  OS_MapInIO
+	;STR	a1, GPIO_Address
+
+	;MOV	r0, a1
+	;LDR	r1, =0x7FFFFF
+	;STR	r1, [r0]
+	;LDR	r1, =0x44555
+	;STR	r1, [r0,#0x10]
+	;LDR	r1, =0x7FF
+	;STR	r1, [r0,#0x18]
+	;LDR	r1, =0xAAAAAAAA
+	;STR	r1, [r0,#0x20]
+	;LDR	r1, =0xFFFF
+	;STR	r1, [r0,#0x28]
+	;LDR	r1, =0xAAAAAAAA
+	;STR	r1, [r0,#0x30]
+	;LDR	r1, =0xFFFF
+	;STR	r1, [r0,#0x38]
+	;LDR	r1, =0xAAAAA800
+	;STR	r1, [r0,#0x40]
+	;LDR 	r1, =0xFFFF
+	;STR	r1, [r0,#0x48]
+	;LDR	r1, =0x55AA
+	;STR	r1, [r0,#0x50]
+	;MOV	r1, #0xFF
+	;STR	r1, [r0,#0x58]
+        ;LDR	r1, =0xFF95FFBA
+	;STR	r1, [r0,#0x60]
+	;LDR	r1, =0xFFFF
+	;STR	r1, [r0,#0x68]
+	;LDR	r1, =0x2AFAAA
+	;STR	r1, [r0,#0x70]
+	;LDR	r1, =0x7FF
+	;STR	r1, [r0,#0x78]
+	;LDR	r1, =0x2AAAAAA
+	;STR	r1, [r0,#0xD0]
+	;LDR	r1, =0x1FFF
+	;STR	r1, [r0,#0xD8]
+
+        MOV     a1, #0		;Map in LCD
+        LDR     a2, =0x77100000
+        MOV     a3, #0x100000
+        CallOS  OS_MapInIO
+	STR	a1, LCD_Address
+
+	ADRL	r4,LCD_txt
+	LDR	r0,UART_Address
+	BL	serials
+
+	LDR	r4,LCD_Address
+	BL	serial8
+
+	LDR	r0,LCD_Address
+
+	MOV	r1, #0xC
+	STR	r1, [r0,#0x20]
+	MOV	r1, #0
+	STR	r1, [r0,#0x24]
+	STR	r1, [r0,#0x28]
+	STR	r1, [r0,#0x2C]
+	STR	r1, [r0,#0x30]
+
+	STR	r1, [r0,#0x40]
+	LDR	r1, = 272 + (480 << 11)
+	STR	r1, [r0,#0x44]
+	LDR	r1, = 480 * 272 * 4
+	STR	r1, [r0,#0x48]
+
+	LDR	r1, = 1 + (1 << 8) + (1 << 16) + (1 << 24)
+	STR	r1, [r0,#0x10]
+	LDR	r1, = 39 + (2 << 8) + (1 << 16) + (0 << 24)
+	STR	r1, [r0,#0x14]
+	LDR	r1, = 479 + (271 << 11)
+	STR	r1, [r0,#0x18]
+
+	MOV	r1, #0x60
+	STR	r1, [r0, #4]
+	MOV	r1, #0
+	STR	r1, [r0, #8]
+	STR	r1, [r0]
+
+	LDR	r1, = 0x50100000
+	STR	r1, [r0, #0xA0]
+	STR	r1, [r0, #0xA4]
+	LDR	r1, = 0x50100000 + (640 * 272)
+	STR	r1, [r0,#0xD0]
+	STR	r1, [r0,#0xD4]
+	LDR	r1, = 480 + (160 << 13)
+	STR	r1, [r0,#0x100]
+
+	MOV	r1, #0xD
+	ORR	r1, r1, #0x20000
+	STR	r1, [r0,#0x20]
+	MOV	r1, #0x13
+	ORR	r1, r1, #(9 << 6)
+	ORR	r1, r1, #0x80
+	STR	r1, [r0]
+
+	MOV	r1, #0
+	STR     r1, [r0,#0x130]
+
+	STR	r1, [r0,#0x140]
+	STR	r1, [r0,#0x148]
+	STR	r1, [r0,#0x150]
+	STR	r1, [r0,#0x158]
+
+	STR	r1, [r0,#0x170]
+	STR	r1, [r0,#0x180]
+	MOV	r1,#1
+	STR	r1, [r0,#0x1A0]
+	MOV	r1,#0
+	STR	r1, [r0,#0x1A4]
+	STR	r1, [r0,#0x1B0]
+	STR	r1, [r0,#0x1B4]
+
+	MOV	r1, #-1
+	STR	r1, [r0,#0x144]
+	STR	r1, [r0,#0x14C]
+	STR	r1, [r0,#0x154]
+	STR	r1, [r0,#0x15C]
+
+        MOV     a1, #0		;Map in host interface
+        MOV     a2, #0x74000000
+        MOV     a3, #0x1000
+        CallOS  OS_MapInIO
+
+	MOV	a2, #0
+	STR	a2, [a1, #0xC]
+
+        MOV     a1, #0		;Map in host interface
+        LDR     a2, =0x74108000
+        MOV     a3, #0x1000
+        CallOS  OS_MapInIO
+
+	MOV	a2, #0
+	STR	a2, [a1, #0xC]
+
+
+        MOV     a1, #0		;Map in system controller
+        LDR     a2, =0x7E00F000
+        MOV     a3, #0x1000
+        CallOS  OS_MapInIO
+	LDR	a2, [a1, #0x30]
+	ORR	a2, a2, #8
+	STR	a2, [a1, #0x30]
+	LDR	a2, [a1, #0x38]
+	ORR	a2, a2, #0x40000000
+	STR	a2, [a1, #0x38]
+	LDR	a2, [a1, #0x900]
+	ORR	a2,a2,#0x10000
+	STR	a2, [a1, #0x900]
+
+
+
+        MOV     a1, #0		;Map in GPIO
+        LDR     a2, =0x7F008000
+        MOV     a3, #0x1000
+        CallOS  OS_MapInIO
+
+	Push "a1"
+	ADRL	r4,GPIO_txt
+	LDR	r0,UART_Address
+	BL	serials
+
+	Pull "r4"
+	Push "r4"
+
+	BL	serial8
+	Pull "a1"
+
+	LDR	a2, [a1, #0x1A0]
+	BIC	a2, a2, #3
+	ORR	a2, a2, #1
+	STR	a2, [a1, #0x1A0]
+	LDR	a2, [a1, #0x80]
+	BIC	a2, a2, #15
+	ORR	a2, a2, #1
+	STR	a2, [a1, #0x80]
+	LDR	a2, [a1, #0x84]
+	ORR	a2, a2, #1
+	STR	a2, [a1, #0x84]
+
+	LDR	a2, =0xAAAAAAAA
+	STR	a2, [a1, #0x100]
+	STR	a2, [a1, #0x120]
+
+	;LDR	r0,LCD_Address
+	;LDR	r1, = (4 << 8) ;4 << 8
+	;ORR	r1, r1, #((3<<5) + (11<<1))
+	;STR	r1, [r0]
+	;LDR	r1, = 271 << 14
+;	;ORR	r1, r1, #(1 << 24)
+	;ORR	r1, r1, #(4 << 6)
+	;ORR	r1, r1, #12
+;	;ORR	r1, r1, #1
+	;STR	r1, [r0, #4]
+        ;LDR	r1, = 479 << 8
+	;ORR	r1, r1, #(35 << 19)
+        ;ORR	r1, r1, #18
+	;STR	r1, [r0, #8]
+        ;MOV	r1, #12 ;4
+	;STR	r1, [r0, #12]
+	;MOV	r1, #(1<<12)
+	;;MOV	r1, #(1<<11)
+	;ORR	r1, r1, #(1<<9)
+	;ORR	r1, r1, #(1<<8)
+	;ORR	r1, r1, #(1<<3)
+	;ORR	r1, r1, #2
+;	MOV	r1, #0x308
+	;STR	r1, [r0, #16]
+	;MOV	r1, #(0x30000000 >> 1)
+	;STR	r1, [r0, #0x14] ;Start
+	;MOV	r1, #0x2A800
+	;ORR	r1, r1, #0x10000
+	;STR	r1, [r0, #0x18] ;End
+	;MOV	r1, #240
+;	ORR	r1, r1, #(80 << 11)   Modulo
+	;STR	r1, [r0, #0x1C]
+	;MOV	r1, #0
+	;STR	r1, [r0, #0x50]
+	;STR	r1, [r0, #0x60]
+
+	;MOV	r1, #1
+	;STR	r1, [r0, #0x5C]
+
+	;LDR	r1, [r0]
+	;ORR	r1, r1, #1
+	;STR	r1, [r0]
+
+;	MOV	r1, #0x1000000
+;	ORR	r1, r1, #0xFF
+;        STR	r1, [r0, #0x50]
+
+        MOV     a1, #0		;Map in USB
+        LDR     a2, =0x74300000
+        MOV     a3, #0x100000
+        CallOS  OS_MapInIO
+	STR	a1, USB_Address
+        ;
+        ;MOV     a1, #0		;Map in RTC
+        ;MOV     a2, #0x57000000
+        ;MOV     a3, #0x100000
+        ;CallOS  OS_MapInIO
+	;STR	a1, RTC_Address
+        ;
+	;MOV	a2, #1
+	;STRB	a2, [a1, #0x40]
+        ;
+	;MOV	r4, a1
+	;LDR	r0, UART_Address
+	;BL	serial8
+        ;
+	;LDR 	r0, UART_Address
+	;ADRL	r4, Ready
+	;BL	serials
+	;BL	serialn
+
+;	MOV 	r1, #13
+;	BL	serial3
+;	MOV	r1, #10
+;	BL 	serial3
+
+	;MOV	R0, a1
+	;MOV	R1, #68
+	;BL 	serial2
+
+;	B crashit
+
+;        STR     a1, IO_Address
+;        ADD     a2, a1, #IOMDPhys - IOPhys
+;        STR     a2, IOMD_Address
+;        ADD     a3, a1, #VIDCPhys - IOPhys
+;        STR     a3, VIDC_Address
+;
+;        LDRB    a1, [a2, #IOMD_ID0]
+;        LDRB    a4, [a2, #IOMD_ID1]
+;        ORR     a1, a1, a4, LSL #8
+;        LDR     a4, =IOMD_Original
+;        TEQ     a1, a4
+;        MOVEQ   ip, #0                    ; assume Medusa
+;        MOVNE   ip, #IOST_7500            ; else assume Morris
+;        STRB    ip, IOSystemType
+;
+;        MOV     a1, #0
+;        MOV     a2, #EASIPhys
+;        MOV     a3, #EASISize
+;        CallOS  OS_MapInIO
+;        STR     a1, EASI_Address
+
+;        BL      Video_init
+;
+;	LDR 	a1, IOMD_Address  	; SuperIO at IOMD-0x1f0000
+;	SUB	a1, a1, #0x1f0000
+;
+;	MOV	a2, #0x55               ; Enter config mode
+;	STRB	a2, [a1, #0xfc0]
+;	STRB	a2, [a1, #0xfc0]
+;	MOV	a2, #0x0d
+;	STRB	a2, [a1, #0xfc0]
+;
+;	ADR	a2, SuperIOTab
+;SPL	LDRB 	a3, [a2], #1
+;	CMP	a3, #0xff
+;	LDRNEB  a4, [a2], #1
+;	STRNEB	a3, [a1, #0xfc0]
+;	STRNEB  a4, [a1, #0xfc4]
+;	BNE 	SPL
+;
+;	MOV 	a2, #0xaa       	; Leave config mode
+;	STRB	a2, [a1, #0xfc0]
+;
+        EXIT
+;
+; Initialise and relocate the entry table.
+SetUpOSEntries  ROUT
+        STMDB	sp!,{lr}
+;	STMDB	sp!,{r0-r1}
+;;;	MOV	r1,#65
+;	BL	serial
+;	LDMIA	sp!,{r0-r1}
+
+        STR     a1, OSheader
+        LDR     a2, [a1, #OSHdr_NumEntries]
+        CMP     a2, #HighestOSEntry+1
+        MOVHI   a2, #HighestOSEntry+1
+
+        ADR     a3, OSentries
+        LDR     a4, [a1, #OSHdr_Entries]
+        ADD     a4, a4, a1
+
+;	STMDB 	sp!,{r0-r4}
+;	MOV	r4, a2
+;	BL 	serial8
+;	LDMIA	sp!,{r0-r4}
+
+05      SUBS    a2, a2, #1
+        LDR     ip, [a4, a2, LSL #2]
+        ADD     ip, ip, a4
+        STR     ip, [a3, a2, LSL #2]
+        BNE     %BT05
+
+;	MOV	r1,#66
+;	BL	serial
+
+        LDMIA	sp!,{pc}
+;
+;
+
+HAL_Null
+        MOV     pc, lr
+
+HAL_DebugTX
+	STMDB   sp!,{r0-r4,lr}
+	MOV	r1,a1
+	LDR	r0,UART_Address
+	BL      serial2
+	LDMIA 	sp!,{r0-r4,pc}
+
+HAL_DebugRX
+	STMDB	sp!,{r1-r4,lr}
+	LDR	r1,UART_Address
+	LDR	r0,[r1,#16]
+
+	TST	r0,#1
+	MOVEQ	r0,#-1
+	LDMEQIA	sp!,{r1-r4,pc}
+
+        LDR	r0,[r1,#0x24]
+	;MOV	r0,#-1
+	LDMIA	sp!,{r1-r4,pc}
+
+
+USBc_txt = "HAL_USBControllerInfo"
+	 = 0
+
+HAL_USBControllerInfo
+	CMP	r0,#0  ;Only one host controller
+	MOV	r0,#0
+	MOVNE	pc,lr
+
+;	STMDB	sp!,{r0-r4,lr}
+;	LDR	r1,UART_Address
+;	ADR	r4,USBc_txt
+;	BL	serials
+;	BL	serialn
+;	LDMIA	sp!,{r0-r4,lr}
+
+	STR	r0,[r1] ;OHCI controller
+	STR	r0,[r1,#4] ;Flags
+	LDR	r0,USB_Address
+	STR	r0,[r1,#8] ;Address
+	MOV	r0, #47
+	STR	r0,[r1,#12] ;Device
+
+	MOV 	pc,lr
+
+HAL_HardwareInfo
+	MOV	ip, #0
+	STR	ip, [a1]
+	STR	ip, [a2]
+	STR	ip, [a3]
+	MOV	pc, lr
+
+HAL_PlatformInfo
+	MOV	ip, #16
+	STR	ip, [a2]
+	MOV	ip, #31
+	STR	ip, [a3]
+	MOV	pc, lr
+
+HAL_SuperIOInfo
+	MOV	ip, #0
+	STR	ip, [a1]
+	STR	ip, [a2]
+	MOV 	pc, lr
+
+;
+;HAL_ControllerAddress
+;        MOV     a1, #0                  ; Default to "not fitted"
+;        AND     a3, a2, #&FF            ; Get sequence number.
+;        MOV     a2, a2, LSR #8          ; Get controller type.
+;        CMP     a2, #4
+;        ADDLS   pc, pc, a2, LSL #2
+;        MOV     pc, lr
+;        B       ca_EASIspeed
+;        B       ca_EASIspace
+;        MOV     pc, lr
+;        B       ca_VIDC20
+;        B       ca_IOMD
+;
+;ca_EASIspeed
+;        LDR     ip, IOMD_Address
+;        CMP     a3, #EASISlots
+;        ADDLO   a1, ip, #IOMD_ECTCR
+;        MOV     pc, lr
+;
+;ca_EASIspace
+;        LDR     ip, EASI_Address
+;        CMP     a3, #EASISlots
+;        ADDLO   a1, ip, a3, LSL #EASISlotSizeShift
+;        MOV     pc, lr
+;
+;ca_VIDC20
+;        TEQ     a3, #0
+;        LDREQ   a1, VIDC_Address
+;        MOV     pc, lr
+;
+;ca_IOMD
+;        TEQ     a3, #0
+;        LDREQ   a1, IOMD_Address
+;        MOV     pc, lr
+;
+;HAL_HardwareInfo
+;        LDR     ip, =&01010101
+;        STR     ip, [a1]
+;        MOV     ip, #1
+;        STR     ip, [a2]
+;        MOV     ip, #0
+;        STR     ip, [a3]
+;        MOV     pc, lr
+;
+;HAL_SuperIOInfo
+;        LDR     ip, =&00311111
+;        STR     ip, [a1]
+;        LDR     ip, =&00011100
+;        STR     ip, [a2]
+;        MOV     pc, lr
+;
+;HAL_PlatformInfo
+;        ADR     a4, %86
+;        LDR     ip, IOMD_Address
+;        LDRB    ip, [ip, #IOMD_ID0]
+;82
+;        LDR     a1, [a4], #4
+;        TEQ     a1, #&80000000     ;terminator
+;        TEQNE   a1, ip
+;        LDMEQIA a4, {a4,ip}
+;        STREQ   a4, [a2]
+;        STREQ   ip, [a3]
+;        MOVEQ   pc, lr
+;        ADD     a4, a4, #2*4
+;        B       %BT82
+;86
+;        DCD     IOMD_Original :AND: &FF, &00000005, &0000000F
+;        DCD     IOMD_7500     :AND: &FF, &00000001, &0000000F
+;        DCD     IOMD_7500FE   :AND: &FF, &00000001, &0000000F
+;        DCD     IOMD_IOMD2    :AND: &FF, &0000000F, &0000000F
+;        DCD     &80000000,                       0,         0  ;terminator
+;
+;;must return address of at least 64k of physical space suitable for
+;;cache cleaning (at least 4k aligned, preferably 64k aligned)
+;;or, return -1 if HAL knows not needed (eg. knows core in system)
+;;
+;HAL_CleanerSpace
+;        [ {FALSE}
+;          ???don't know what do yet, in generic memory size case
+;        |
+;          MOV   a1, #&10000000  ; return start of physical RAM
+;        ]
+;        MOV     pc, lr
+;
+;        LTORG
+;
+;
+;        ! 0, "TODO - Sort out keyboard scan for IOMD HAL"
+;HAL_KbdScan
+;        MOV     a1, #&C0000000 ; scan complete, keyboard present
+;HAL_KbdScanSetup
+;HAL_KbdScanInterrupt
+;HAL_KbdScanFinish
+;        MOV     pc, lr
+;
+;SuperIOTab
+;	= 0x01,0x87,0x02,0x1c,0x03,0x78,0x04,0x03,0x05,0x00,0x06,0xff
+;	= 0x07,0x00,0x08,0x00,0x09,0x00,0x0a,0x00,0x00,0xbb,0xff
+;
+
+;HAL_DebugTX
+;	B serial
+
+HAL_InitDevices
+	Entry
+
+	;BL 	RTC_Init
+
+	EXIT
+
+
+        END
diff --git a/s/IIC b/s/IIC
new file mode 100644
index 0000000..4174017
--- /dev/null
+++ b/s/IIC
@@ -0,0 +1,66 @@
+; Copyright 2011 Castle Technology Ltd
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+;
+        GET     Hdr:ListOpts
+        GET     Hdr:Macros
+        GET     Hdr:System
+        GET     Hdr:Machine.<Machine>
+        GET     Hdr:ImageSize.<ImageSize>
+        $GetIO
+
+        GET     Hdr:OSEntries
+        GET     Hdr:HALEntries
+
+        GET     hdr.StaticWS
+
+        EXPORT  HAL_IICBuses
+        EXPORT  HAL_IICType
+        EXPORT  HAL_IICSetLines
+        EXPORT  HAL_IICReadLines
+
+        AREA    |Asm$$Code|, CODE, READONLY, PIC
+
+HAL_IICBuses
+        MOV     a1, #1
+        MOV     pc, lr
+
+HAL_IICType
+        MOV     a1, #IICFlag_LowLevel
+ [ MaxI2Cspeed >= 400
+        ORR     a1, a1, #IICFlag_Fast
+ ]
+        MOV     pc, lr
+
+; In:  a1 = bus number, a2 = SDA, a3 = SCL
+; Out: a1 = SDA, a2 = SCL
+HAL_IICSetLines
+        LDRB    ip, IOCRSoftCopy
+        LDR     a4, IOMD_Address
+        ADD     a2, a2, a3, LSL #1      ; bit 1 = SCL, bit 0 = SDA
+        BIC     ip, ip, #3
+        ORR     ip, ip, a2
+        STRB    ip, IOCRSoftCopy
+        STRB    ip, [a4, #IOCControl]
+10      LDRB    a1, [a4, #IOCControl]
+        MOV     a2, a1, LSR #1
+        AND     a1, a1, #1
+        AND     a2, a2, #1
+        MOV     pc, lr
+
+HAL_IICReadLines
+        LDR     a4, IOMD_Address
+        B       %BT10
+
+        END
+
diff --git a/s/Interrupts b/s/Interrupts
new file mode 100644
index 0000000..770dbf1
--- /dev/null
+++ b/s/Interrupts
@@ -0,0 +1,312 @@
+; Copyright 2011 Castle Technology Ltd
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+;
+        GET     Hdr:ListOpts
+        GET     Hdr:Macros
+        GET     Hdr:System
+        GET     Hdr:Machine.<Machine>
+        GET     Hdr:ImageSize.<ImageSize>
+        $GetIO
+        GET     Hdr:DevNos
+
+        GET     Hdr:OSEntries
+        GET     Hdr:HALEntries
+
+        GET     hdr.StaticWS
+
+        AREA    |Asm32$$Code|, CODE, READONLY, PIC, ALIGN=5
+
+NoInterrupt     * 38
+
+        EXPORT  HAL_IRQSource
+        EXPORT  HAL_IRQEnable
+        EXPORT  HAL_IRQDisable
+        EXPORT  HAL_IRQClear
+        EXPORT  HAL_IRQStatus
+;        EXPORT  HAL_FIQSource
+;        EXPORT  HAL_FIQEnable
+;        EXPORT  HAL_FIQDisable
+;        EXPORT  HAL_FIQDisableAll
+;        EXPORT  HAL_FIQClear
+;        EXPORT  HAL_FIQStatus
+
+	IMPORT  serial2
+	IMPORT	serials
+	IMPORT	serialn
+	IMPORT	serial8
+
+HAL_IRQSource
+	;STMDB	sp!,{r0-r5,lr}
+	;LDR	r0, UART_Address
+	;ADR	r4, IRQSR2_txt
+	;BL 	serials
+	;LDMIA	sp!,{r0-r5,lr}
+
+        LDR     r3, INT_Address
+	LDR	r0, [r3,#0xF00]
+        CMP	r0, #0
+	ADDEQ	r3, r3, #0x100000
+	LDREQ	r0, [r3,#0xF00]
+	;STMDB	sp!,{r0-r5,lr}
+	;MOV	r4,r0
+	;LDR	r0, UART_Address
+	;BL	serial8
+	;LDMIA	sp!,{r0-r5,lr}
+;	LDR	r1, [r3]
+;
+;        MOV     r0, #31
+;	MOV	r2, #1
+;irqlp   CMP	r0, #-1
+;	BEQ 	noirq
+;	TST     r1, r2, LSL r0
+;	SUBEQ   r0,r0,#1
+;	BEQ 	irqlp
+;
+;noirq
+	;STMDB	sp!,{r0-r5,lr}
+        ;STMDB	sp!,{r0}
+	;LDR	r0, UART_Address
+	;ADR	r4, IRQSR_txt
+	;;BL 	serials
+	;;LDMIA	sp!,{r4}
+	;BL	serial8
+	;LDMIA	sp!,{r0-r5,pc}
+
+	MOV 	pc,lr
+
+;HAL_FIQSource
+;        LDR     r3, IOMD_Address
+;        LDRB    r0, [r3, #IOCFIQREQ]
+;        ORR     r0, r0, r0, LSR #4
+;        ORR     r0, r0, r0, LSR #2
+;        ORR     r0, r0, r0, LSR #1
+;        ADD     r0, r0, #1              ; r0 = 2, 4, 8, 16, 32, 64, 128 or 256
+;        MOV     r1, #&0E800000
+;        MUL     r0, r1, r0              ; r0>>29 = 0, 1, 3, 7, 6, 5, 2 or 4
+;        LDRB    r0, [pc, r0, LSR #29]
+;        MOV     pc, lr
+;	        DCB     0, 1, 6, 2, 7, 5, 4, 3
+
+;HAL_FIQEnable
+;        LDR     a4, IOMD_Address
+;        MOV     ip, #1
+;        MRS     a3, CPSR
+;        MOV     ip, ip, LSL a1
+;        ORR     a2, a3, #F32_bit+I32_bit
+;        MSR     CPSR_c, a2
+;        LDRB    a1, [a4, #IOCFIQMSK]
+;        ORR     a2, a1, ip
+;        STRB    a2, [a4, #IOCFIQMSK]
+;        MSR     CPSR_c, a3
+;        AND     a1, a1, ip
+;        MOV     pc, lr
+
+;HAL_FIQDisable
+;        LDR     a4, IOMD_Address
+;        MOV     ip, #1
+;        MRS     a3, CPSR
+;        MOV     ip, ip, LSL a1
+;        ORR     a2, a3, #F32_bit+I32_bit
+;        MSR     CPSR_c, a2
+;        LDRB    a1, [a4, #IOCFIQMSK]
+;        BIC     a2, a1, ip
+;        STRB    a2, [a4, #IOCFIQMSK]
+;        MSR     CPSR_c, a3
+;        AND     a1, a1, ip
+;        MOV     pc, lr
+;
+;HAL_FIQDisableAll
+;        LDR     a4, IOMD_Address
+;        MOV     a1, #0
+;        STRB    a1, [a4, #IOCFIQMSK]
+;        MOV     pc, lr
+;
+;HAL_FIQClear
+;        MOV     pc, lr
+;
+;HAL_FIQStatus
+;        LDR     a4, IOMD_Address
+;        MOV     ip, #1
+;        LDRB    a2, [a4, #IOCFIQSTA]
+;        AND     a1, a2, ip, LSL a1
+;        MOV     pc, lr
+
+
+
+IRQSR2_txt	= "Getting IRQ source"
+		= 10,13,0
+
+IRQEN_txt	= "IRQ enable = "
+		= 0
+IRQDS_txt	= "IRQ disable = "
+		= 0
+IRQCL_txt	= "IRQ clear = "
+		= 0
+IRQSR_txt	= "IRQ source = "
+		= 0
+
+	ALIGN
+
+HAL_IRQEnable
+	STMDB	sp!,{lr}
+;	CMP	a1, #16
+;	LDMEQIA sp!,{pc}
+
+;	STMDB	sp!,{r0-r5}
+;	MOV	r4,a1
+;	LDR	r0, UART_Address
+;	MOV	r4,a1
+;	BL	serial8
+;	LDMIA	sp!,{r0-r5}
+
+	STMDB	sp!,{r0-r5}
+
+	LDR	a2, INT_Address
+	TST	a1, #32
+	ANDNE	a1, a1, #31
+	ADDNE	a2, a2, #0x100000
+
+	MOV	a4, #1
+	MOV	a1, a4, LSL a1
+
+	;LDR	a3, [a2,#8]
+	;BIC	a3, a3, a1
+	STR	a1, [a2,#0x10]
+
+	;STMDB	sp!,{a2}
+
+	STMDB	sp!,{r0-r5}
+	STMDB	sp!,{a2}
+	STMDB	sp!,{a1}
+	LDR	r0, UART_Address
+	ADR	r4, IRQEN_txt
+	BL 	serials
+	LDMIA   sp!,{r4}
+	BL	serial8
+	LDMIA   sp!,{r4}
+	BL	serial8
+	LDMIA	sp!,{r0-r5}
+
+	;LDMIA	sp!,{a2}
+	;STMDB	sp!,{r0-r5}
+	;LDR	r0, UART_Address
+	;MOV	r4,a2
+	;BL	serial8
+	;LDMIA	sp!,{r0-r5}
+
+	LDMIA	sp!,{r0-r5}
+
+	LDMIA	sp!,{pc}
+	MOV 	pc,lr
+
+HAL_IRQDisable
+	;STMDB	sp!,{lr}
+	;STMDB 	sp!,{r0-r5}
+
+	LDR	a2, INT_Address
+	TST	a1, #32
+	ANDNE	a1, a1, #31
+	ADDNE	a2, a2, #0x100000
+
+	MOV	a4, #1
+	MOV	a1, a4, LSL a1
+
+;	LDR	a3, [a2,#8]
+;	ORR	a3, a3, a1
+	STR	a1, [a2,#0x14]
+
+	;STMDB	sp!,{r0-r5}
+	;STMDB	sp!,{a1}
+	;LDR	r0, UART_Address
+	;ADR	r4, IRQDS_txt
+	;BL 	serials
+	;LDMIA   sp!,{r4}
+	;BL	serial8
+	;LDMIA	sp!,{r0-r5}
+
+	;LDMIA	sp!,{r0-r5}
+	;LDMIA	sp!,{pc}
+	MOV 	pc,lr
+
+HAL_IRQClear
+;	STMDB	sp!,{lr}
+	STMDB	sp!,{r0-r12,lr}
+;	CMP	a1, #16
+;	MOVEQ	a4, #3
+;	LDRQ	a2, LCD_Address
+;	STR
+
+;	STREQ	a4, [a2, #0x54]
+;	STREQ	a4, [a2, #0x58]
+
+;	MOV	a4, #1
+;	MOV	a1, a4, LSL a1
+	CMP	a1,#0x1C
+	LDREQ	a2,Timer_Address
+	LDREQ	a3,[a2,#0x44]
+	ORREQ	a3,a3,#0x200
+	STREQ	a3,[a2,#0x44]
+
+        LDR     a2, INT_Address
+	;TST	a1, #32
+	;ANDNE	a1, a1, #31
+	;ADDNE	a2, a2, #0x100000
+ 	STR	a1, [a2,#0xF00]
+        ADD	a2, a2, #0x100000
+	STR	a1, [a2,#0xF00]
+
+;	STR	a1, [a2, #0x10]
+
+;	MOV	r4,a1
+;;	LDR	r0, UART_Address
+;	BL 	serial8
+	;STMDB	sp!,{r0-r5}
+	;STMDB	sp!,{a1}
+	;ADR	r0, UART_Address
+	;ADR	r4, IRQCL_txt
+	;BL 	serials
+	;LDMIA   sp!,{r4}
+	;BL	serial8
+	;LDMIA	sp!,{r0-r5}
+
+	LDMIA	sp!,{r0-r12,lr}
+
+;	LDMIA	sp!,{pc}
+        MOV     pc, lr
+
+HAL_IRQStatus
+;	MOV	a1,#1
+	;STMDB	sp!,{lr}
+	;STMDB	sp!,{r0-r5}
+	;STMDB	sp!,{a1}
+	;LDR	r0, UART_Address
+	;ADR	r4, IRQST_txt
+	;BL 	serials
+	;LDMIA   sp!,{r4}
+	;BL	serial8
+	;LDMIA	sp!,{r0-r5}
+
+	MOV	a1, #1
+	MOV	a4, #1
+	MOV	a1, a4, LSL a1
+        LDR     a2, INT_Address
+	LDR	a3, [a2]
+	AND	a1, a3, a4
+	;LDMIA	sp!,{pc}
+        MOV     pc, lr
+
+IRQST_txt	= "IRQ status = "
+		= 0
+	ALIGN
+        END
diff --git a/s/MachineID b/s/MachineID
new file mode 100644
index 0000000..57c95dd
--- /dev/null
+++ b/s/MachineID
@@ -0,0 +1,245 @@
+; Copyright 2011 Castle Technology Ltd
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+;
+        GET     Hdr:ListOpts
+        GET     Hdr:Macros
+        GET     Hdr:System
+        GET     Hdr:Machine.<Machine>
+        GET     Hdr:ImageSize.<ImageSize>
+        $GetIO
+        GET     Hdr:Proc
+
+        GET     Hdr:OSEntries
+        GET     Hdr:HALEntries
+
+        GET     hdr.StaticWS
+
+        AREA    |Asm$$Code|, CODE, READONLY, PIC
+
+        EXPORT  HAL_MachineID
+
+        IMPORT  HAL_TimerPeriod
+        IMPORT  HAL_TimerSetPeriod
+
+; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+;
+;       ReadUniqueID - Read unique machine ID
+;
+; 10-Dec-93  BCockburn  Modified to leave raw 64 bit ID from chip in RawMachineID
+
+defaultlatch *  20000-1 ; TMD 21-May-93: "-1" correction applied
+
+Tsyc    *       5       ; time between frames - minimum of 1µs, so give it a bit more
+Trstl   *       500     ; time reset pulse held low - minimum of 480µs, so give it a bit more
+Trsth   *       500     ; time reset pulse held high - minimum of 480µs, so give it a bit more
+Tlow0   *       80      ; time for write0 low - min 60µs, max 120µs
+Tlow1   *       5       ; time for write1 low - min 1µs, max 15µs
+Tslot   *       90      ; time for total read/write slot - min 60µs, max 120µs
+Trdlow  *       5       ; time for read slot low before release - min 1µs, max 15µs
+Trddat  *       3       ; time after read slot high before read it
+
+        ASSERT  Tslot-Tlow0 > Tsyc
+        ASSERT  Trdlow+Trddat < 15
+
+; Macro to set wire to a given state, and optionally count transitions (starting at low) while waiting for a given time
+
+        MACRO
+        SetWire $hilo, $time, $monstate, $count
+        LCLS    reg
+ [ "$hilo"="LOW"
+reg     SETS    "r4"
+ |
+        ASSERT  "$hilo"="HIGH"
+reg     SETS    "r5"
+ ]
+ [ ($time) = 0
+        STRB    $reg, [r1, #IOCControl]         ; set appropriate level on line
+ |
+        ASSERT  ($time) < 32768
+        MOV     r12, #(($time)*2):AND:&FF
+        STRB    r12, [r1, #Timer0LL]            ; program low latch
+        MOV     r12, #(($time)*2):SHR:8
+        STRB    r12, [r1, #Timer0LH]            ; program high latch
+        STRB    $reg, [r1, #IOCControl]         ; set appropriate level on line
+        STRB    r12, [r1, #Timer0GO]            ; and start timer
+        LDRB    r12, [r1, #IOCIRQSTAA]          ; dummy instruction to avoid bug in IOC
+        LDRB    r12, [r1, #IOCIRQSTAA]          ; dummy instruction (repeated for FE)
+        STRB    r11, [r1, #IOCIRQCLRA]          ; immediately clear IRQ bit
+  [ "$monstate"<>""
+        MOV     $monstate, #0
+  ]
+  [ "$count"<>""
+        MOV     $count, #0
+  ]
+10
+        LDRB    r12, [r1, #IOCIRQSTAA]
+        TST     r12, r11
+  [ "$count"<>""
+        ADDEQ   $count, $count, #1
+  ]
+  [ "$monstate"=""
+        BEQ     %BT10                                   ; not timed out, so just loop
+  |
+        BNE     %FT30                                   ; timed out
+        LDRB    r12, [r1, #IOCControl]
+        TST     r12, #IOEB_unique_machine_ID_bit
+        BEQ     %BT10                                   ; if still low then loop to 10
+
+        ADD     $monstate, $monstate, #1                ; increment number of transitions
+20
+        LDRB    r12, [r1, #IOCIRQSTAA]
+        TST     r12, r11
+   [ "$count"<>""
+        ADDEQ   $count, $count, #1
+   ]
+        BNE     %FT30                                   ; timed out
+        LDRB    r12, [r1, #IOCControl]
+        TST     r12, #IOEB_unique_machine_ID_bit
+        BNE     %BT20                                   ; if still high then loop to 20
+        ADD     $monstate, $monstate, #1                ; increment number of transitions
+        B       %BT10
+30
+  ]
+ ]
+        MEND
+
+HAL_MachineID
+        Entry "r4-r11",8
+        MOV     r0, #0
+        LDR     r1, IOMD_Address
+        MRS     r8, CPSR                                ; remember PSR in r8
+        ORR     r3, r8, #I32_bit+F32_bit
+        MSR     CPSR_c, r3                              ; FIQs and IRQs off
+        LDRB    r3, IOCRSoftCopy
+        BIC     r4, r3, #IOEB_unique_machine_ID_bit     ; r4 is value to pull ID line low
+        ORR     r5, r3, #IOEB_unique_machine_ID_bit     ; r5 is value to pull ID line high
+        MOV     r11, #timer0_bit
+        BL      SendResetPulse
+        BVS     ResetFailed
+        BL      SendCommandWord
+
+        MOV     r7, #0                                  ; no. of bytes to store = 8 bits type + 48 bits ID + 8 bits checksum
+10
+        BL      GetAByte
+        STRB    r6, [sp, r7]
+        ADD     r7, r7, #1
+        CMP     r7, #8
+        BNE     %BT10
+
+        BL      RestoreIOCState
+        MOV     r1, sp
+        BL      CheckCRC
+        BVS     IDError
+        LDMIA   sp, {r0, r1}
+        EXIT
+
+ResetFailed
+        BL      RestoreIOCState
+IDError
+        MOV     r0, #0
+        MOV     r1, #0                                  ; indicate no ID by putting zero here
+        EXIT
+
+RestoreIOCState Entry
+        STRB    r3, [r1, #IOCControl]                   ; put back old value
+        MOV     r0, #0
+        BL      HAL_TimerPeriod
+        MOV     r1, r0
+        MOV     r0, #0
+        BL      HAL_TimerSetPeriod
+        MSR     CPSR_c, r8                              ; restore old interrupt state
+        EXIT
+
+SendResetPulse ROUT
+        SetWire HIGH, Tsyc
+        SetWire LOW, Trstl,,r6
+        SetWire HIGH, Trsth,r10
+        TEQ     r6, #0
+;        ADREQ   r0, IOCBugHappenedError
+        BEQ     %FT05
+        CMP     r10, #3                                 ; H-L-H is ok
+        MOVEQ   pc, lr                                  ; V clear
+;        ADRHI   r0, TooManyTransitionsError             ; H-L-H-L...
+;        CMP     r10, #2
+;        ADREQ   r0, NeverWentHighAgainError             ; H-L
+;        CMP     r10, #1
+;        ADREQ   r0, NeverWentLowError                   ; H
+;        ADRCC   r0, NeverWentHighError                  ; stayed low permanently even though we released it
+05
+        SETV
+        MOV     pc, lr
+
+ [ {FALSE} ; only for debugging
+NeverWentHighError
+        =       "Never went high", 0
+NeverWentLowError
+        =       "Never went low", 0
+NeverWentHighAgainError
+        =       "Never went high again", 0
+TooManyTransitionsError
+        =       "Too many transitions", 0
+IOCBugHappenedError
+        =       "IOC bug happened", 0
+        ALIGN
+ ]
+
+SendCommandWord ROUT
+        CLRV
+        LDR     r6, =&10F               ; &0F is command word
+10
+        MOVS    r6, r6, LSR #1
+        MOVEQ   pc, lr
+        BCS     SendOne
+        SetWire LOW, Tlow0
+        SetWire HIGH, Tslot-Tlow0
+        B       %BT10
+
+SendOne
+        SetWire LOW, Tlow1
+        SetWire HIGH, Tslot-Tlow1
+        B       %BT10
+
+GetAByte ROUT
+        MOV     r6, #&80
+10
+        SetWire LOW, Trdlow
+        SetWire HIGH, Trddat
+        LDRB    r10, [r1, #IOCControl]
+        SetWire HIGH, Tslot-Trdlow-Trddat
+        MOVS    r10, r10, LSR #IOEB_ID_bit_number+1    ; move bit into carry
+        MOVS    r6, r6, RRX
+        BCC     %BT10
+        MOV     r6, r6, LSR #24
+        MOV     pc, lr
+
+CheckCRC ROUT
+        MOV     r2, #0
+        MOV     r3, #7                          ; number of bytes to do
+10
+        LDRB    r4, [r1], #1
+        EOR     r2, r2, r4
+        MOV     r4, #8                          ; number of bits to do
+20
+        MOVS    r2, r2, LSR #1                  ; shift bit out into carry
+        EORCS   r2, r2, #&8C                    ; feedback carry into other bits
+        SUBS    r4, r4, #1                      ; one less bit to do
+        BNE     %BT20                           ; loop until done whole byte
+        SUBS    r3, r3, #1                      ; one less byte to do
+        BNE     %BT10                           ; loop until done all 7 bytes
+        LDRB    r4, [r1], #1                    ; read CRC
+        CMP     r4, r2                          ; if correct
+        MOVEQ   pc, lr                          ; exit (V clear)
+        RETURNVS                                ; else exit indicating error
+
+        END
diff --git a/s/NVRAM b/s/NVRAM
new file mode 100644
index 0000000..ac716bf
--- /dev/null
+++ b/s/NVRAM
@@ -0,0 +1,69 @@
+; Copyright 2011 Castle Technology Ltd
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+;
+        GET     Hdr:ListOpts
+        GET     Hdr:Macros
+        GET     Hdr:System
+        GET     Hdr:Machine.<Machine>
+        GET     Hdr:ImageSize.<ImageSize>
+        $GetIO
+
+        GET     Hdr:OSEntries
+        GET     Hdr:HALEntries
+
+        GET     hdr.StaticWS
+
+    	EXPORT	HAL_NVMemoryType
+    	EXPORT	HAL_NVMemorySize
+    	EXPORT  HAL_NVMemoryPageSize
+    	EXPORT	HAL_NVMemoryProtectedSize
+    	EXPORT	HAL_NVMemoryProtection
+    	EXPORT	HAL_NVMemoryIICAddress
+    	EXPORT	HAL_NVMemoryRead
+    	EXPORT	HAL_NVMemoryWrite
+
+        AREA    |Asm$$Code|, CODE, READONLY, PIC
+
+HAL_NVMemoryType
+    	LDR 	R0, =NVMemoryFlag_IIC :OR: NVMemoryFlag_ProtectAtEnd
+        MOV     pc, lr
+
+HAL_NVMemorySize
+    	MOV 	R0, #256
+        MOV     pc, lr
+
+HAL_NVMemoryPageSize
+        MOV     R0, #16
+        MOV     pc, lr
+
+HAL_NVMemoryProtectedSize
+    	MOV 	R0, #0
+        MOV     pc, lr
+
+; in: r0 = 0/1 to unprotect/protect
+HAL_NVMemoryProtection
+        MOV     pc, lr
+
+HAL_NVMemoryIICAddress
+    	MOV 	R0, #&a0
+        MOV     pc, lr
+
+HAL_NVMemoryRead
+        MOV     pc, lr
+
+HAL_NVMemoryWrite
+        MOV     pc, lr
+
+        END
+
diff --git a/s/RTC b/s/RTC
new file mode 100644
index 0000000..55e4761
--- /dev/null
+++ b/s/RTC
@@ -0,0 +1,212 @@
+; Copyright 2011 Castle Technology Ltd
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+;
+        GET     Hdr:ListOpts
+        GET     Hdr:Macros
+        GET     Hdr:System
+        GET     Hdr:Machine.<Machine>
+        GET     Hdr:ImageSize.<ImageSize>
+        $GetIO
+
+        GET     Hdr:OSEntries
+        GET     Hdr:HALEntries
+        GET     Hdr:HALDevice
+        GET     Hdr:RTCDevice
+
+        GET     hdr.StaticWS
+
+
+        AREA    |Asm$$Code|, CODE, READONLY, PIC
+
+        EXPORT  RTC_Init
+
+	IMPORT  serial8
+
+
+;       Note - debug stuff won't work since we don't get passed a HAL workspace pointer!
+;        IMPORT  DebugHALPrint
+;        IMPORT  DebugHALPrintReg
+;        IMPORT  DebugMemDump
+;        IMPORT  DebugHALPrintByte
+
+; TWL/TPS RTC IIC address
+TPSRTC_IIC     * &4b
+
+; Some RTC registers
+SECONDS_REG       * &1C
+RTC_CTRL_REG      * &29
+RTC_STATUS_REG    * &2a
+
+
+        MACRO
+        CallOS  $entry, $tailcall
+        ASSERT  $entry <= HighestOSEntry
+ [ "$tailcall"=""
+        MOV     lr, pc
+ |
+   [ "$tailcall"<>"tailcall"
+        ! 0, "Unrecognised parameter to CallOS"
+   ]
+ ]
+        LDR     pc, OSentries + 4*$entry
+        MEND
+
+RTC_Init
+	STMDB	sp!,{lr}
+	MOV	r0,   #0xF9000000
+	ORR	r0, r0, #0xF00000
+	ADR	r1, RTCDevice
+	LDR	r4, [r1, #HALDevice_Activate]
+	BL	serial8
+	LDMIA	sp!,{lr}
+        ; Just register our HAL Device with the OS
+        MOV     a1, #0
+        ADR     a2, RTCDevice
+        CallOS  OS_AddDevice, tailcall
+
+RTCDevice
+        DCW     HALDeviceType_SysPeri + HALDeviceSysPeri_RTC
+        DCW     HALDeviceID_RTC_TPS65950
+        DCD     HALDeviceBus_Pro
+        DCD     0               ; API version
+        DCD     RTCDesc
+        DCD     0               ; Address - N/A
+        %       12              ; Reserved
+        DCD     RTCActivate
+        DCD     RTCDeactivate
+        DCD     RTCReset
+        DCD     RTCSleep
+        DCD     -1              ; Interrupt N/A
+        DCD     0
+        %       8
+        DCB     RTCTimeFormat_BCD
+        DCB     RTCFormatFlags_BCD_YearLOIsGood ; todo - add RTCFormatFlags_BCD_NeedsYearHelp once NVRAM is implemented
+        %       2
+        DCD     RTCReadTime
+        DCD     RTCWriteTime
+
+RTCDesc
+        DCB "S3C6410 real-time clock",0
+
+        ALIGN
+
+RTCActivate
+        MOV     a1, #1
+RTCDeactivate
+RTCReset
+        MOV     pc, lr
+
+RTCSleep
+        MOV     a1, #0 ; Previously at full power
+        MOV     pc, lr
+
+RTCReadTime
+        ; In:
+        ; a1 = HALDevice ptr
+        ; a2 = RTCTimeStruct ptr
+        ; a3 = IICOp func ptr
+        ; a4 = kernel workspace ptr
+        ; Out:
+        ; a1 = return code
+        ; RTCTimeStruct updated
+        Push    "v1-v3,lr"
+        MOV     v1, a3
+        MOV     v2, a4
+        MOV     v3, a2
+
+	STMDB	sp!, {r2-r12}
+	MOV	r0, #13
+	ORR	r0,r0,#&20000
+	ORR	r0,r0,#&3C0000
+	MOV	r1,#&57000000
+	MOV	r2,#&100000
+	SWI	0x68
+	MOV	a1, r3
+	LDMIA	sp!, {r2-r12}
+
+	;LDR	a1, RTC_Address
+
+	LDRB	a2, [a1, #0x70]
+	STRB	a2, [v3, #RTCTimeStruct_BCD_Seconds]
+	LDRB	a2, [a1, #0x74]
+	STRB	a2, [v3, #RTCTimeStruct_BCD_Minutes]
+	LDRB	a2, [a1, #0x78]
+	STRB	a2, [v3, #RTCTimeStruct_BCD_Hours]
+	LDRB	a2, [a1, #0x7C]
+	STRB	a2, [v3, #RTCTimeStruct_BCD_DayOfMonth]
+	LDRB	a2, [a1, #0x84]
+	STRB	a2, [v3, #RTCTimeStruct_BCD_Month]
+	LDRB	a2, [a1, #0x88]
+	STRB	a2, [v3, #RTCTimeStruct_BCD_YearLO]
+	MOV	a2, #0
+	STRB    a2, [v3, #RTCTimeStruct_BCD_Centiseconds]
+
+        ; Construct a fakey YearHI by looking at YearLO
+        ; Anything 70 or above is considered 1970+, else 2000+
+        ; This should work OK, since RISC OS clamps the time to 1970 for unix compatability (or it does on boot, at least)
+        LDRB    a2, [v3, #RTCTimeStruct_BCD_YearLO]
+        CMP     a2, #&70
+        MOVGE   a3, #&19
+        MOVLT   a3, #&20
+        STRB    a3, [v3, #RTCTimeStruct_BCD_YearHI]
+	MOV	a1, #0
+        ASSERT  RTCRetCode_OK = 0
+        Pull    "v1-v3,pc"
+
+RTCWriteTime
+        ; In:
+        ; a1 = HALDevice ptr
+        ; a2 = RTCTimeStruct ptr
+        ; a3 = IICOp func ptr
+        ; a4 = kernel workspace ptr
+        ; Out:
+        ; a1 = return code
+        Push    "v1-v3,lr"
+        MOV     v1, a3
+        MOV     v2, a4
+        MOV     v3, a2
+        ; Writing the time safely involves several transfers:
+        ; 1. Write 0 to RTC_CTRL_REG to stop the clock (just in case there are any issues with the clock updating while it's being written to)
+        ; 2. Write the new time values
+        ; 3. Write 1 to RTC_CTRL_REG to start the clock
+
+	STMDB	sp!, {r2-r12}
+	MOV	r0, #13
+	ORR	r0,r0,#&20000
+	ORR	r0,r0,#&3C0000
+	MOV	r1,#&57000000
+	MOV	r2,#&100000
+	SWI	0x68
+	MOV	a1, r3
+	LDMIA	sp!, {r2-r12}
+
+;	LDR	a1, RTC_Address
+
+	LDRB	a2, [v3, #RTCTimeStruct_BCD_Seconds]
+	STRB	a2, [a1, #0x70]
+	LDRB	a2, [v3, #RTCTimeStruct_BCD_Minutes]
+	STRB	a2, [a1, #0x74]
+	LDRB	a2, [v3, #RTCTimeStruct_BCD_Hours]
+	STRB	a2, [a1, #0x78]
+	LDRB	a2, [v3, #RTCTimeStruct_BCD_DayOfMonth]
+	STRB	a2, [a1, #0x7C]
+	LDRB	a2, [v3, #RTCTimeStruct_BCD_Month]
+	STRB	a2, [a1, #0x84]
+	LDRB	a2, [v3, #RTCTimeStruct_BCD_YearLO]
+	STRB	a2, [a1, #0x88]
+
+        Pull    "v1-v3,pc"
+
+
+        END
diff --git a/s/Timers b/s/Timers
new file mode 100644
index 0000000..02551f9
--- /dev/null
+++ b/s/Timers
@@ -0,0 +1,115 @@
+; Copyright 2011 Castle Technology Ltd
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+;
+        GET     Hdr:ListOpts
+        GET     Hdr:Macros
+        GET     Hdr:System
+        GET     Hdr:Machine.<Machine>
+        GET     Hdr:ImageSize.<ImageSize>
+        $GetIO
+
+        GET     Hdr:OSEntries
+        GET     Hdr:HALEntries
+
+        GET     hdr.StaticWS
+
+        AREA    |Asm$$Code|, CODE, READONLY, PIC
+
+        EXPORT  HAL_Timers
+        EXPORT  HAL_TimerDevice
+        EXPORT  HAL_TimerGranularity
+        EXPORT  HAL_TimerMaxPeriod
+        EXPORT  HAL_TimerSetPeriod
+        EXPORT  HAL_TimerPeriod
+        EXPORT  HAL_TimerReadCountdown
+
+        EXPORT  HAL_CounterRate
+        EXPORT  HAL_CounterPeriod
+        EXPORT  HAL_CounterRead
+        EXPORT  HAL_CounterDelay
+
+	EXPORT	HAL_VideoFlybackDevice
+
+	IMPORT	serials
+	IMPORT	serial8
+
+HAL_Timers
+        MOV     a1, #1                  ; 1 timer
+        MOV     pc, lr
+
+HAL_TimerDevice
+        ADD     a1, a1, #28             ; device 14
+        MOV     pc, lr
+
+HAL_VideoFlybackDevice
+	MOV	a1, #-1
+	MOV	pc, lr
+
+HAL_CounterRate
+HAL_TimerGranularity
+        LDR     a1, =4000000            ; 4MHz
+        MOV     pc, lr
+
+HAL_TimerMaxPeriod
+        MOV     a1, #&10000             ; 16-bit counter
+        MOV     pc, lr
+
+TSet_txt	= "Timer set = "
+		= 0
+
+	ALIGN
+
+HAL_TimerSetPeriod
+        LDR     a3, Timer_Address
+
+	STR	a2, [a3, #0x3C]
+
+        ADR     a4, TimerPeriods
+        STR     a2, [a4, a1, LSL #2]
+
+	STMDB	sp!,{r0-r5,lr}
+	STMDB	sp!,{a2}
+	LDR	r0, UART_Address
+	ADR	r4, TSet_txt
+	BL	serials
+	LDMIA	sp!,{r4}
+	BL	serial8
+	LDMIA	sp!,{r0-r5,pc}
+        ;MOV     pc, lr
+
+HAL_TimerPeriod
+        ADR     a4, TimerPeriods
+        LDR     a1, [a4, a1, LSL #2]
+        MOV     pc, lr
+
+HAL_CounterRead
+        MOV     a1, #0
+        ; Fall through
+
+HAL_TimerReadCountdown
+        LDR     a4, Timer_Address
+
+	LDR	a1, [a4, #0x40]
+
+        MOV     pc, lr
+
+HAL_CounterPeriod
+        LDR     a1, TimerPeriods + 0
+        MOV     pc, lr
+
+; If they want n ticks, wait until we've seen n+1 transitions of the clock.
+HAL_CounterDelay
+        MOV     pc, lr
+
+        END
diff --git a/s/Video b/s/Video
new file mode 100644
index 0000000..862b519
--- /dev/null
+++ b/s/Video
@@ -0,0 +1,1177 @@
+; Copyright 2011 Castle Technology Ltd
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+;
+        GET     Hdr:ListOpts
+        GET     Hdr:Macros
+        GET     Hdr:System
+        GET     Hdr:Machine.<Machine>
+        GET     Hdr:ImageSize.<ImageSize>
+        $GetIO
+        GET     Hdr:Proc
+
+        GET     Hdr:OSEntries
+        GET     Hdr:HALEntries
+
+        EXPORT  HAL_Video_PixelFormats
+        EXPORT  HAL_Video_Features
+        EXPORT  HAL_Video_BufferAlignment
+        EXPORT  HAL_Video_OutputFormat
+        GET     hdr.StaticWS
+        GET     hdr.Video
+
+        AREA    |Asm$$Code|, CODE, READONLY, PIC
+
+        EXPORT  Video_init
+        ;EXPORT  HAL_VideoFlybackDevice
+        EXPORT  HAL_Video_SetMode
+        EXPORT  HAL_Video_WritePaletteEntry
+        EXPORT  HAL_Video_WritePaletteEntries
+        EXPORT  HAL_Video_ReadPaletteEntry
+        EXPORT  HAL_Video_SetInterlace
+        EXPORT  HAL_Video_SetBlank
+        EXPORT  HAL_Video_SetPowerSave
+        EXPORT  HAL_Video_UpdatePointer
+        EXPORT  HAL_Video_SetDAG
+        EXPORT  HAL_Video_VetMode
+
+	IMPORT 	serials
+	IMPORT	serial8
+; -----------------------------------------------------------------------------------
+
+Video_init ROUT
+    	Push     "lr"
+	Pull 	"pc"
+;    MOV      lr, #-1
+;    STR      lr, VIDC_NextPaletteIndex  ; init to invalid
+;    MOV      lr, #0
+;    STR      lr, VIDC_SoftPalette0
+;    STR      lr, VIDC_Interlace
+    ; Read IOMD_VIDCR and use it to recalculate the VRAM size (based around our knowledge of the values that Allocate_DRAM programs)
+    ; However RPCemu is buggy and always reports DRAMMode + bit 4 set!
+    ; Luckily we only need bits 2 & 3 to get the VRAM size
+;    ASSERT   SAMLength/2/256 = 4 ; 1MB
+;    LDR      lr, IOMD_Address
+;    LDRB     lr, [lr, #IOMD_VIDCR]
+;    MOV      lr, lr, LSR #2
+;    AND      lr, lr, #3 ; Should be 0, 1, 2 depending on VRAM size
+;    STRB     lr, VRAMWidth
+;    Pull     "pc"
+
+; -----------------------------------------------------------------------------------
+
+;HAL_VideoFlybackDevice
+;        MOV     a1, #3
+;        MOV     pc, lr
+
+; -------------------------------------------------------------------------
+
+;
+;  void HAL_Video_SetMode(const void *VIDCList3)
+;
+;  program VIDC20 registers from VIDCList3 specification
+;
+;  in: VIDClist -> video mode list (in VIDCList type 3 format)
+;
+
+VID_Tbl DATA
+	& 1 ;1 bpp
+	& 1 ;2 bpp
+	& 1 ;4 bpp
+	& 2 ;8 bpp
+	& 3 ;16 bpp
+	& 2 ;32 bpp
+
+Vid_txt = "Set mode X = "
+	= 0
+BPP_txt = "Set mode BPP = "
+	= 0
+Pal_txt = "Set pal - "
+	= 0
+	ALIGN
+
+HAL_Video_SetMode ROUT
+
+	STMDB	sp!,{r0-r4,lr}
+ ;	STMDB	sp!,{r0}
+
+;	LDR	r1, [r0, #VIDCList3_HorizDisplaySize]
+;	STR	r1, VIDX_Size
+;	SUB	r1, r1, #480
+;	MOV	r1, r1, LSR #1
+;	LDR	r2, LCD_Address
+;;	LDR	r3, [r2]
+;	BIC	r3, r3, #1
+;	STR	r3, [r2]
+;	MOV	r1, r1, LSL #11
+;	ORR	r1, r1, #240
+;	STR 	r1, [r2, #0x1C]
+;	ORR	r3, r3, #1
+;	STR	r3, [r2]
+;
+;;	LDR	r1, [r0, #VIDCList3_PixelDepth]
+;	STR	r1, VID_BPP
+;;;
+;	LDR	r0,LCD_Address
+;	ADD	r1, r1, #8
+;	MOV	r1, r1, LSL #1
+;	ORR	r1, r1, #((3<<5) + (4<<8))
+;	STR	r1, [r0]
+;
+;	LDR	r1, [r0, #16]
+;	BIC	r1, r1, #3
+;	LDR	r2, VID_BPP
+;	ADR	r3, VID_Tbl
+;	LDR	r2, [r3, r2, LSL #2]
+;	ORR	r1, r1, r2
+;	STR	r1, [r0, #16]
+;
+;	LDR	r0, UART_Address
+;	ADR	r4, Vid_txt
+;	BL	serials
+;	LDR	r4, VIDX_Size
+;	BL	serial8
+
+;	ADR	r4, BPP_txt
+;	BL	serials
+;	LDMIA	sp!,{r1}
+;	LDR	r4, [r1, #VIDCList3_PixelDepth]
+;	BL	serial8
+
+	LDMIA 	sp!,{r0-r4, pc}
+	;MOV	pc,lr
+;        Push    "r4, r7,r8,r10,r11, lr"
+;        MOV     r3, r0                    ; r3 -> VIDCList3
+;
+;        SUB     sp, sp, #VIDC20ParmsSize  ; create workspace for VIDC20 table on stack
+;        SUB     r11, sp, #(&80*4)         ; r11 indexes into table workspace (allowing for
+;                                          ; VIDC register numbers starting at &80)
+;
+;        MOV     r2, #-1                   ; first clear all entries to -1 (means dont program reg)
+;        MOV     r4, #VIDC20ParmsSize
+;        MOV     r14, sp
+;10
+;        STR     r2, [r14], #4
+;        SUBS    r4, r4, #4
+;        BNE     %BT10
+;
+;        LDR     r2, [r3, #VIDCList3_HorizSyncWidth]
+;        BIC     r2, r2, #1                ; must be even
+;        SUB     r2, r2, #8                ; horiz parameters start off at n-8
+;        ORR     r14, r2, #HorizSyncWidth
+;        STR     r14, [r11, #HorizSyncWidth :SHR: 22]
+;
+;        LDR     r4, [r3, #VIDCList3_HorizBackPorch]
+;        ADD     r2, r2, r4
+;;        BIC     r2, r2, #1
+;        SUB     r2, r2, #4                ; HBSR is N-12
+;        ORR     r14, r2, #HorizBorderStart
+;        STR     r14, [r11, #HorizBorderStart :SHR: 22]
+;
+;        LDR     r4, [r3, #VIDCList3_HorizLeftBorder]
+;        ADD     r2, r2, r4
+;        BIC     r2, r2, #1
+;        SUB     r2, r2, #6                ; HDSR is N-18
+;        ORR     r14, r2, #HorizDisplayStart
+;        STR     r14, [r11, #HorizDisplayStart :SHR: 22]
+;
+;        LDR     r4, [r3, #VIDCList3_HorizDisplaySize]
+;        BIC     r4, r4, #1
+;        LDR     r7, [r3, #VIDCList3_PixelDepth]
+;        MOV     r10, r4, LSL r7           ; number of bits in one displayed raster (not needed later any more)
+;
+;        ANDS    r8, r10, #31              ; if line length not multiple of 32
+;        MOVNE   r8, #DCR_HDis             ; then set HDis bit
+;        ORR     r8, r8, r10, LSR #5       ; OR in number of words per line
+;
+;;; Note - the DCR_Bus bits get overridden and the HDWR bits modified further down the line by the mode change code
+;; on the basis of how much VRAM we've got, and on whether we have a dual-panel LCD or not...
+;
+;        ORR     r8, r8, #DCR_VRAMOff :OR: DCR_Bus31_0 :OR: DCR_Sync
+;        ORR     r8, r8, #VIDCDataControl
+;        STR     r8, [r11, #VIDCDataControl :SHR: 22]
+;
+;        ADD     r2, r2, r4                ; HDER is also N-18
+;        ORR     r14, r2, #HorizDisplayEnd
+;        STR     r14, [r11, #HorizDisplayEnd :SHR: 22]
+;
+;        LDR     r4, [r3, #VIDCList3_HorizRightBorder]
+;        ADD     r2, r2, r4
+;        ADD     r2, r2, #6                ; HBER is N-12
+;        BIC     r2, r2, #1
+;        ORR     r14, r2, #HorizBorderEnd
+;        STR     r14, [r11, #HorizBorderEnd :SHR: 22]
+;
+;        LDR     r4, [r3, #VIDCList3_HorizFrontPorch]
+;        ADD     r2, r2, r4
+;        ADD     r2, r2, #4                ; HCR is N-8
+;        BIC     r2, r2, #3                ; must be mult of 4
+;        ORR     r14, r2, #HorizCycle
+;        STR     r14, [r11, #HorizCycle :SHR: 22]
+;
+;        ADD     r2, r2, #8                ; HIR is N/2
+;        MOV     r2, r2, LSR #1
+;        ORR     r14, r2, #HorizInterlace
+;        STR     r14, [r11, #HorizInterlace :SHR: 22]
+;
+;        LDR     r2, [r3, #VIDCList3_VertiSyncWidth]
+;        SUB     r2, r2, #2                ; vertical registers are N-2
+;        ORR     r14, r2, #VertiSyncWidth
+;        STR     r14, [r11, #VertiSyncWidth :SHR: 22]
+;
+;        LDR     r4, [r3, #VIDCList3_VertiBackPorch]
+;        ADD     r2, r2, r4
+;        ORR     r14, r2, #VertiBorderStart
+;        STR     r14, [r11, #VertiBorderStart :SHR: 22]
+;
+;        LDR     r4, [r3, #VIDCList3_VertiTopBorder]
+;        ADD     r2, r2, r4
+;        ORR     r14, r2, #VertiDisplayStart
+;        STR     r14, [r11, #VertiDisplayStart :SHR: 22]
+;
+;        LDR     r4, [r3, #VIDCList3_VertiDisplaySize]
+;        STR     r4, VIDC_VertiDisplaySize              ; save it for cursor clipping
+;        ADD     r2, r2, r4
+;        ORR     r14, r2, #VertiDisplayEnd
+;        STR     r14, [r11, #VertiDisplayEnd :SHR: 22]
+;
+;        LDR     r4, [r3, #VIDCList3_VertiBottomBorder]
+;        ADD     r2, r2, r4
+;        ORR     r14, r2, #VertiBorderEnd
+;        STR     r14, [r11, #VertiBorderEnd :SHR: 22]
+;
+;        LDR     r4, [r3, #VIDCList3_VertiFrontPorch]
+;        ADD     r2, r2, r4
+;        ORR     r14, r2, #VertiCycle
+;        STR     r14, [r11, #VertiCycle :SHR: 22]
+;
+;        LDR     r4, [r3, #VIDCList3_SyncPol]
+;        TST     r4, #SyncPol_Interlace
+;        MOVEQ   r14, #0
+;        MOVNE   r14, #1
+;        STR     r14, VIDC_Interlace
+;        MOV     r14, #VIDCExternal
+;        TST     r4, #SyncPol_InvertHSync
+;        ORRNE   r14, r14, #Ext_InvertHSYNC
+;        TST     r4, #SyncPol_InvertVSync
+;        ORRNE   r14, r14, #Ext_InvertVSYNC
+;        ORR     r14, r14, #Ext_DACsOn
+;        ORR     r14, r14, #Ext_ERegExt
+;        STR     r14, [r11, #VIDCExternal :SHR: 22]
+;
+;        MOV     r14, #VIDCControl
+;        STR     r14, [r11, #VIDCControl :SHR: 22]
+;
+;        Push    "r3";
+
+; Now go through VIDC control parameters list (not all indices can be handled yet)
+
+;        ADD     r3, r3, #VIDCList3_ControlList-8  ; point at 1st entry -8
+;50
+;;        LDR     r4, [r3, #8]!                   ; load next index
+;        CMP     r4, #-1                         ; if -1 then end of list
+;        BEQ     %FT60                           ; so skip
+;
+;        CMP     r4, #0                          ; if non-zero (CS if zero)
+;        CMPNE   r4, #ControlList_InvalidReason  ; and if known reason
+;        LDRCC   r2, [r3, #4]                    ; then load value
+;        BLCC    ProcessControlListItem          ; and process this item
+;        B       %BT50                           ; go onto next item in list
+;
+; put a minimum of 4, cos 800 x 600 x 1bpp don't work otherwise
+;FIFOLoadTable
+;        &       0                               ; dummy entry (not used)
+;        &       0                               ; never use 0
+;        &       0                               ; use 1 up to (and including) here
+;        &       0                               ; use 2 up to (and including) here
+;        &       0                               ; use 3 up to (and including) here
+;        &       60000 :SHL: 3                   ; use 4 up to (and including) here
+;        &       75000 :SHL: 3                   ; use 5 up to (and including) here
+;        &       90000 :SHL: 3                   ; use 6 up to (and including) here
+;                                                ; else use 7
+
+;60
+;        Pull    "r3"
+;        LDR     r0, [r3, #VIDCList3_PixelRate]  ; get pixel rate
+;        MOV     r10, r0, LSL r7                 ; peak mem b/w (x 1E3 bits/sec) - save for FIFO calculation
+;
+;        MOV     R1, #0
+;        LDRB    R1, IOSystemType
+;        TST     R1, #IOST_7500
+;        LDREQ   R1, =24000              ;(Medusa), VIDC20 at 24MHz;
+;        MOVNE   R1, #32000              ;Morris, VIDC20L at 32Mhz ;
+
+;        BL      ComputeModuli   ; out: r0 = FSync bits, r1 = CR bits
+
+;        ORR     r0, r0, #VIDCFSyn
+;        STR     r0, [r11, #VIDCFSyn :SHR: 22]
+;
+;        LDR     r0, [r11, #VIDCControl :SHR: 22]
+;        ORR     r0, r0, r1
+
+;        TEQ     r7, #5          ; if 32 bpp, then stick in 6 not 5
+;        MOVEQ   r7, #6
+;        ORR     r0, r0, r7, LSL #5
+
+; now work out FIFO load position - r10 is b/w in thousands of bytes/sec
+
+; do it by means of a binary chop on 3 bits
+
+;        ADR     r4, FIFOLoadTable
+;        LDR     r2, [r4, #4*4]                  ; load 0-3/4-7 split
+;        CMP     r10, r2
+;        MOVLS   r7, #0                          ; if <=, then bottom half
+;        MOVHI   r7, #4                          ; else top half
+;        ADDHI   r4, r4, #4*4                    ; and advance table pointer
+;
+;        LDR     r2, [r4, #2*4]
+;        CMP     r10, r2
+;        ORRHI   r7, r7, #2
+;        ADDHI   r4, r4, #2*4
+;
+;        LDR     r2, [r4, #1*4]
+;        CMP     r10, r2
+;        ORRHI   r7, r7, #1
+;
+;        ORR     r0, r0, r7, LSL #CR_FIFOLoadShift
+;        STR     r0, [r11, #VIDCControl :SHR: 22]
+;
+;        ADD     R0, r11, #(&80*4)           ; R0 -> VIDC20 table (remove offset for reg indices starting at &80)
+;        BL      ProgramVIDC20Regs
+;
+        ; now make sure video DMA enabled
+        ;
+;        LDR     r7, IOMD_Address
+;        LDRB    r8, [r7, #IOMD_VIDCR]
+;        AND     r8, r8, #&7F                 ; knock out IOMD_VIDCR_Dup
+;        ORR     r8, r8, #IOMD_VIDCR_Enable   ; enable video DMA
+;        STRB    r8, [r7, #IOMD_VIDCR]
+;
+;        ADD     sp, sp, #VIDC20ParmsSize   ; drop workspace for table
+;        Pull    "r4, r7,r8,r10,r11, pc"
+
+; -------------------------------------------------------------------------
+
+;
+;       ProcessControlListItem
+;
+; in:   r2  = value for item
+;       r4  = index for item (guaranteed in range)
+;       r11 -> VIDC register array
+;
+; out:  r0-r2, r4, r7, r8, r10 may be corrupted
+;       r3, r9, r11 must be preserved
+
+ProcessControlListItem Entry
+        ADD     pc, pc, r4, LSL #2
+        NOP
+        B       ProcessControlListNOP                   ; 0 - NOP
+        B       ProcessControlListLCDMode               ; 1 - LCD mode
+        B       ProcessControlListLCDDualPanelMode      ; 2 - LCD dual-panel mode
+        B       ProcessControlListLCDOffsetRegister0    ; 3 - LCD offset register 0
+        B       ProcessControlListLCDOffsetRegister1    ; 4 - LCD offset register 1
+        B       ProcessControlListHiResMode             ; 5 - Hi-res mode
+        B       ProcessControlListDACControl            ; 6 - DAC control
+        B       ProcessControlListRGBPedestals          ; 7 - RGB pedestal enables
+        B       ProcessControlListExternalRegister      ; 8 - External register
+        B       ProcessControlListHClockSelect          ; 9 - HClk select/specify
+        B       ProcessControlListNOP                   ; 10 - RClk frequency
+        B       ProcessControlListDPMSState             ; 11 - DPMS state
+        B       ProcessControlListNOP                   ; 12 - Interlaced mode
+
+  ! 0, "mjsHAL - no LCD support (VIDCList3 control list stuff)"
+
+ProcessControlListLCDMode
+        ;;;mjsHAL we have no support
+        EXIT
+
+ProcessControlListHiResMode
+        MOV     r1, #Ext_HiResMono              ; bit of a misnomer, it's not nec. mono
+05
+        MOV     r0, #VIDCExternal
+10
+        MOV     r7, r1
+        TEQ     r2, #0                          ; if value non-zero
+        MOVNE   r2, r1                          ; then use value in r1
+15
+        AND     r2, r2, r7                      ; ensure only relevant bits set
+        LDR     lr, [r11, r0, LSR #22]           ; load word from register bank
+        BIC     lr, lr, r7                      ; knock out bits in mask
+        ORR     lr, lr, r2                      ; OR in new bits
+        STR     lr, [r11, r0, LSR #22]           ; and store in array
+;
+ProcessControlListNOP
+        EXIT
+
+ProcessControlListDACControl
+        MOV     r1, #Ext_DACsOn
+        B       %BT05
+
+ProcessControlListRGBPedestals
+        MOV     r0, #VIDCExternal
+        MOV     r2, r2, LSL #Ext_PedsShift
+        MOV     r7, #Ext_PedsOn
+        B       %BT15
+
+ProcessControlListExternalRegister
+        MOV     r0, #VIDCExternal
+        MOV     r7, #&FF
+        B       %BT15
+
+ProcessControlListLCDDualPanelMode
+        ;;;mjsHAL we have no support
+        EXIT
+
+ProcessControlListLCDOffsetRegister0
+        ;;;mjsHAL we have no support
+        EXIT
+
+ProcessControlListLCDOffsetRegister1
+        ;;;mjsHAL we have no support
+        EXIT
+
+ProcessControlListHClockSelect
+        MOV     r0, #PseudoRegister_HClockSpeed ; pseudo-register holding HClock speed
+        ORR     r2, r2, r0                      ; form combined value
+        STR     r2, [r11, r0, LSR #22]           ; store in register
+        EXIT
+
+ProcessControlListDPMSState
+        ; no longer used in HAL code (kernel keeps DPMSState)
+        EXIT
+;
+; void HAL_Video_WritePaletteEntry(uint type, uint pcolour, uint index)
+;
+; write palette entry to video controller
+;
+;  type     = 0 for normal palette entry
+;             1 for border colour
+;             2 for pointer colour
+;          >= 3 reserved
+;  pcolour  = palette entry colour in BBGGRRSS format (Blue,Green,Red,Supremacy)
+;  index    = index of entry  (0..255 for normal, 0 for border, 0..3 for pointer)
+;             note that RISC OS only uses 1..3 for pointer (0 is assumed to be transparent)
+;
+
+
+HAL_Video_WritePaletteEntry ROUT
+	STMDB	sp!,{r0-r3,lr}
+	CMP	r0, #0
+	LDMNEIA	sp!,{r0-r3,pc}
+
+	LDR	r0, LCD_Address
+
+	MOV	r3, #512
+	STR	r3,[r0,#0x1A0]
+
+	ADD	r3, r0, #0x400
+	ADD	r3, r3, r2, LSL #2
+
+;	MOV     r2, r1, LSR #8
+	;AND	r2, r2, #0xF0
+;	AND	r2, r2, #0xF8
+;	MOV	r2, r2, LSL #(11-3)
+
+;	MOV	r3, r1, LSR #16
+	;AND	r3, r3, #0xF0
+;	AND	r3, r3, #0xF8
+;	ORR	r2, r2, r3, LSL #(6-3)
+
+;	MOV	r3, r1, LSR #24
+	;AND	r3, r3, #0xF0
+;	AND     r3, r3, #0xF8
+;	ORR	r2, r2, r3, LSR #2
+
+	MOV	r1, r1, LSR #8
+
+;	Push	"r0,r1,r2,r3,r4,r5"
+;	LDR	r0, UART_Address
+;	ADR	r4, Pal_txt
+;	BL	serials
+ ;	Pull	"r0,r1,r2,r3,r4,r5"
+ ;	Push	"r0,r1,r2,r3,r4,r5"
+;;;	LDR	r0, UART_Address
+;	MOV	r4, r3
+;	BL	serial8
+;	Pull	"r0,r1,r2,r3,r4,r5"
+;	Push	"r0,r1,r2,r3,r4,r5"
+;	LDR	r0, UART_Address
+;	MOV	r4, r1
+;	BL	serial8
+;	Pull	"r0,r1,r2,r3,r4,r5"
+
+
+	STR 	r1, [r3]
+
+	MOV	r3,#1
+	STR	r3,[r0,#0x1A0]
+
+	LDMIA	sp!,{r0-r3,pc}
+
+;        AND     r12, r1, #&F0               ; 000000S0 (4 MSbits of supremacy)
+;        MOV     r1, r1, LSR #8              ; 00BBGGRR
+;        ORR     r1, r1, r12, LSL #20        ; 0SBBGGRR
+;
+;        LDR     r12, VIDC_Address
+;
+;        CMP     r0, #1
+;        BLO     HV_WritePaletteEntry_type0
+;        BEQ     HV_WritePalettEntry_type1
+;;       else fall through to WritePaletteEntry_type2
+;
+;HV_WritePaletteEntry_type2
+;        CMP     r2, #3                      ; index must be in range 0..3
+;        MOVHI   pc, lr
+;        SUBS    r2, r2, #1                  ; reduce 1..3 to 0..2
+;        MOVMI   pc, lr                      ; pointer colour 0 is always transparent on VIDC20
+;        ORR     r1, r1,#VIDC20PointerColour ; munge in base address of register
+;        ADD     r1, r1, r2, LSL #28         ; add in index (0..2), in bits 28,29 of register
+;        STR     r1, [r12]
+;        MOV     pc, lr
+;;
+;HV_WritePaletteEntry_type0
+        ;Note: we only need to hit VIDCPalAddress if the index is not a direct increment
+        ;of the last programmed index
+        ;but, for insurance against permanent misalignment if any rogue accesses avoid this
+        ;interface, we force an update for index 0
+        ;
+;        CMP     r2, #255                  ; index must be in range 0..255
+;        MOVHI   pc, lr
+;
+;        CMP     r2, #0
+;
+;        STREQ   r1, VIDC_SoftPalette0
+;
+;        LDRNE   r0, VIDC_NextPaletteIndex  ;increment from last index programmed
+;        MOVEQ   r0, #-1                    ;forced invalid for index 0
+;
+;        TEQ     r0, r2
+;        ORRNE   r0, r2, #VIDCPalAddress
+;        STRNE   r0, [r12]                 ; only update PalAddress if necessary
+;        STR     r1, [r12]                 ; update palette entry
+;        ADD     r2, r2, #1
+;        AND     r2, r2, #&FF
+;        STR     r2, VIDC_NextPaletteIndex
+;        MOV     pc, lr
+;
+;
+;HV_WritePalettEntry_type1
+;        CMP     r2, #0                     ; index must be 0
+;        MOVNE   pc, lr
+;        ORR     r1, r1,#VIDC20BorderColour ; munge in base address of register
+;        STR     r1, [r12]
+;        MOV     pc, lr
+
+; -------------------------------------------------------------------------
+
+;
+; void HAL_Video_WritePaletteEntries(uint type, const uint *pcolours, uint index, uint Nentries)
+;
+; write block of palette entries to video controller
+;
+;  type     = 0 for normal palette entry
+;             1 for border colour
+;             2 for pointer colour
+;          >= 3 reserved
+;  pcolours = pointer to block of palette entry colours in BBGGRRSS format (Blue,Green,Red,Supremacy)
+;  index    = start index in palette (for first entry in block)
+;             note that RISC OS only uses 1..3 for pointer (0 is assumed to be transparent)
+;  Nentries = number of entries in block (must be >= 1)
+;
+HAL_Video_WritePaletteEntries ROUT
+	;MOV	pc,lr
+        Push    "r4, lr"
+;
+;        CMP     r2, #255                    ; all indices in loop must be in range 0..255
+;        BHI     %FT20
+;        ADD     r4, r2, r3
+;        CMP     r4, #256
+;        BHI     %FT20
+
+	B	%FT50
+
+;        CMP     r0, #0
+;        BNE     %FT50
+;;
+; type 0, try to be efficient
+;
+;        LDR     r12, VIDC_Address
+;
+;        CMP     r2, #0
+;
+;        LDREQ   r0, [r1]
+;        STREQ   r0, VIDC_SoftPalette0
+;
+;        LDRNE   r0, VIDC_NextPaletteIndex
+;        MOVEQ   r0,#-1                      ; insurance! (see comments for WritePaletteEntry_type0)
+;
+;        TEQ     r0, r2
+;        ORRNE   r0, r2, #VIDCPalAddress
+;        STRNE   r0, [r12]                   ; only update PalAddress if necessary
+;
+;        ADD     r0, r2, r3
+;        AND     r0, r0, #&FF
+;        STR     r0, VIDC_NextPaletteIndex
+;
+;        MOV     r4, r1
+;10
+;        LDR     r1, [r4], #4
+;        AND     r0, r1, #&F0                ; 000000S0 (4 msbits of supremacy)
+;        MOV     r1, r1, LSR #8              ; 00BBGGRR
+;        ORR     r1, r1, r0, LSL #20         ; 0SBBGGRR
+;        STR     r1, [r12]
+;        SUBS    r3, r3, #1
+;        BNE     %BT10
+20
+        Pull    "r4, pc"
+
+; not type 0
+
+50
+        MOV     r4, r1
+60
+        LDR     r1, [r4], #4        ; next pcolour
+        Push    "r2, r3"
+        BL      HAL_Video_WritePaletteEntry
+        Pull    "r2, r3"
+        ADD     r2, r2, #1
+        SUBS    r3, r3, #1
+        BNE     %BT60
+        Pull    "r4, pc"
+;
+;; -------------------------------------------------------------------------
+
+;
+; uint HAL_Video_ReadPaletteEntry(uint type, uint pcolour, uint index)
+;
+; return the effective palette entry after taking into account any hardware
+; restrictions in the video controller, assuming it was programmed with pcolour
+;
+;  type     = 0 for normal palette entry
+;             1 for border colour
+;             2 for pointer colour
+;          >= 3 reserved
+;  pcolour  = palette entry colour in BBGGRRSS format (Blue,Green,Red,Supremacy)
+;  index    = index of entry  (0..255 for normal, 0 for border, 0..3 for pointer)
+;             note that RISC OS only uses 1..3 for pointer (0 is assumed to be transparent)
+;  returns  : effective BBGGRRSS
+;
+;  mjs: depending on h/w capabilities, specific HALs may have to
+;       remember current settings (eg. bits per pixel), keep soft copy
+;       of entries or whatever, in their workspace. Because the HAL API
+;       supplies a pcolour, the need to keep a full palette soft copy
+;       in the HAL is minimised
+
+HAL_Video_ReadPaletteEntry ROUT
+        MOV	r0, #0
+	MOV	pc,lr
+;        CMP     r0, #0
+;        BNE     HV_ReadPaletteEntry_not_type0
+;
+; type 0
+; only 4 bits of S, and only 16 S entries
+; S for indices 16..255 comes from palette entry 0
+;
+;        CMP     r2, #16
+;        LDRHS   r12, VIDC_SoftPalette0
+;        MOVLO   r12, r1
+;
+;        AND     r12, r12, #&000000F0  ; effective S bits
+;        BIC     r0, r1, #&000000FF    ; effective BGR bits
+;        ORR     r0, r0, r12           ; munge together
+;        MOV     pc, lr
+;
+;HV_ReadPaletteEntry_not_type0
+; no special restrictions, just that there are only 4 bits of S
+;        BIC     r0, r1, #&0000000F
+;        MOV     pc, lr
+
+; -------------------------------------------------------------------------
+
+; void HAL_Video_SetInterlace(uint interlace)
+;
+;  interlace = 0/1 for interlace off/on
+
+HAL_Video_SetInterlace ROUT
+
+;        LDR     r1, VIDC_ControlSoftCopy
+;        BIC     r1, r1, #CR_Interlace
+;        TST     r0, #1
+;        ORRNE   r1, r1, #CR_Interlace    ; zero => no interlace
+
+;        LDR     r0, VIDC_Address
+;        STR     r1, [r0]                ; program VIDC
+        MOV     pc, lr
+
+; -------------------------------------------------------------------------
+
+; void HAL_Video_SetBlank(uint blank, uint DPMS)
+;
+; blank = 0/1 for unblank/blank
+; DMPS  = 0..3 as specified by monitor DPMSState (from mode file)
+;         0 for no DPMS power saving
+
+; HAL is expected to attempt to turn syncs off according to DPMS, and
+; to turn video DMA off for blank (and therefore on for unblank) if possible.
+; HAL is not expected to do anything else, eg. blank all palette entries.
+; Such things are the responsibility of the OS, and also this call is expected
+; to be fast. May be called with interrupts off.
+
+HAL_Video_SetBlank ROUT
+
+;        LDR     r3, VIDC_Address
+
+;        TEQ     r0, #0
+;        BEQ     %FT50
+;
+; blanking
+;
+;        TST     r1, #1                  ; if hsyncs should be off,
+;        LDRNE   r2, =HorizSyncWidth + ((1:SHL:14) -1)   ; maximum value in h.sync width register
+;        STRNE   r2, [r3]
+;
+;        TST     r1, #2                  ; if vsyncs should be off,
+;        LDRNE   r2, =VertiSyncWidth + ((1:SHL:13) -1)   ; maximum value in v.sync width register
+;        STRNE   r2, [r3]
+;
+;        LDR     r2, VIDC_ExternalSoftCopy
+;        AND     r1, r1, #3
+;        TEQ     r1, #3                                         ; if both syncs off
+;        BICEQ   r2, r2, #Ext_HSYNCbits :OR: Ext_VSYNCbits;
+;        ORREQ   r2, r2, #Ext_InvertHSYNC :OR: Ext_InvertVSYNC  ; set sync signals to low (less power)
+;        BIC     r2, r2, #Ext_DACsOn                            ; turn off the DACs
+;        STR     r2, [r3]
+;
+;        LDR     r0, IOMD_Address
+;        LDRB    r1, [r0, #IOMD_VIDCR]
+;        BIC     r1, r1, #IOMD_VIDCR_Enable   ; disable video DMA
+;        STRB    r1, [r0, #IOMD_VIDCR]
+
+        MOV     pc, lr
+;
+; unblanking
+;
+;50      LDR     r2, VIDC_ExternalSoftCopy
+;        STR     r2, [r3]                     ; restore DACs and sync type
+;
+;        TST     r1, #1                       ; if hsyncs were turned off,
+;        LDRNE   r2, VIDC_HSWRSoftCopy        ; then restore from soft copy
+;        STRNE   r2, [r3]
+;
+;        TST     r1, #2                       ; if vsyncs were turned off,
+;        LDRNE   r2, VIDC_VSWRSoftCopy        ; then restore from soft copy
+;        STRNE   r2, [r3]
+;
+;        LDR     r0, IOMD_Address
+;        LDRB    r1, [r0, #IOMD_VIDCR]
+;        ORR     r1, r1, #IOMD_VIDCR_Enable   ; enable video DMA
+;        STRB    r1, [r0, #IOMD_VIDCR]
+;
+;        MOV     pc, lr
+
+; -------------------------------------------------------------------------
+
+; void HAL_Video_SetPowerSave(uint powersave)
+;
+; powersave = 0/1 for power save off/on
+
+HAL_Video_SetPowerSave ROUT
+	MOV	pc,lr
+;        LDR     r1, VIDC_Address
+;
+;        TEQ     r0, #0
+;        BEQ     %FT50
+;
+; power save on
+;
+;        LDR     r2, =&C0000003    ;dac off, ereg set to external LUT
+;        STR     r2, [r1]
+;
+;        LDR     r2, =&D0004000    ;Vclk off, Pcomp=0
+;        STR     r2, [r1]
+;
+;        LDR     r2, =&E0004049    ;PoDown, Hclk
+;        STR     r2, [r1]
+;
+;        MOV     pc, lr
+;
+; power save off
+;
+;50
+;        LDR     r2, VIDC_ControlSoftCopy       ;restore from soft copy
+;        STR     r2, [r1]
+;
+;        LDR     r2, VIDC_ExternalSoftCopy      ;restore from soft copy
+;        STR     r2, [r1]
+;
+;        LDR     r2, VIDC_FSynSoftCopy          ;restore from soft copy
+;;
+; [ {TRUE}
+;        LDR     R3, =FSyn_ResetValue    ; set test bits on, and r > v
+;        ORR     R3, R3, #VIDCFSyn
+;        STR     R3, [R1]
+
+; we may need some delay in here...
+
+;        LDR     R3, =FSyn_ClearR :OR: FSyn_ClearV :OR: FSyn_ForceLow :OR: FSyn_ForceHigh
+;        ORR     R2, R2, R3
+;        BIC     R2, R2, #FSyn_ForceHigh ; force test bits on, except this one
+;        STR     R2, [R1]
+
+; we may also need some delay in here...
+
+;        BIC     R2, R2, R3              ; remove test bits
+; ]
+;        STR     r2, [r1]
+
+;        MOV     pc, lr
+
+; -------------------------------------------------------------------------
+
+; void HAL_Video_UpdatePointer(uint flags, int x, int y, const shape_t *shape)
+;
+; Update the displayed position of the current pointer shape (or turn
+; shape off)
+;
+; HAL code may need to take note of shape updated flag, and make its
+; own new copies if true. This is to handle cases like dual scan LCD
+; pointer, which typically needs two or more shapes buffers for the
+; hardware. This work should _only_ be done when the updated flag
+; is true, or possibly because provoked by clipping requirements.
+; A simple HAL, using the kernel shape buffer directly, may be able to
+; ignore the updated flag.
+;
+; flags:
+;   bit 0  = pointer display enable (0=off, 1=on)
+;   bit 1  = pointer shape update (0=no change, 1=updated)
+;   bits 2..31 reserved (0)
+; xpos = x position of top left of pointer (xpos = 0 for left of display)
+; ypos = y position of top left of pointer (ypos = 0 for top of display)
+; shape points to shape_t descriptor block:
+;   typedef struct shape_t
+;   {
+;     uint8   width;      /* unpadded width in bytes (see notes) */
+;     uint8   height;     /* in pixels */
+;     uint8   padding[2]; /* 2 bytes of padding for field alignment */
+;     void   *buffLA;     /* logical address of buffer holding pixel data */
+;     void   *buffPA;     /* corresponding physical address of buffer */
+;   }
+;
+; Notes:
+; 1) if flags bit 0 is 0 (pointer off), x, y, shape are undefined
+; 2) the shape data from RISC OS is always padded with transparent pixels
+;    on the rhs, to a width of 32 pixels (8 bytes)
+; 3) pointer clipping is the responsibility of the HAL (eg. may be able to
+;    allow display of pointer in border region on some h/w)
+; 4) buffer for pixel data is aligned to a multiple of 256 bytes or better
+;
+; This call is made by the OS at a time to allow smoothly displayed changes
+; (on a VSync)
+
+HAL_Video_UpdatePointer ROUT
+
+	MOV 	pc,lr
+;        Push    "r4, r5, lr"
+;
+;        LDR     r14, VIDC_Address
+;
+;        TST     r0, #1
+;        BEQ     %FT90          ; pointer off
+;
+;
+; process x (and assume shape width is padded 32 pixels)
+;
+;        LDR     r4, VIDC_PointerHAdjust
+;        ADDS    r1, r1, r4
+;        MOVLT   r1, #0                    ; x:= x+fudge, clamped to 0
+;
+;;        CMP     r1, #&4000                ; VIDC has 14 bits for cursor start
+;        MOVGE   r1, #&4000
+;        SUBGE   r1, r1, #1
+;
+;        ORR     r1, r1, #HorizCursorStart
+;        STR     r1, [r14]
+;
+; process y
+;
+;        LDRB    r4, [r3, #1]              ; height from shape_t block
+;        LDR     r5, [r3, #8]              ; buffer physical address from shape_t block
+;
+;        CMP     r2, #0                    ; if -ve y
+;        BICLT   r2, r2, #1                ; TEMP FUDGE - really ought to have two copies, one offset by 1 row
+;                                          ; because VIDC can only cope with 16 byte aligned data pointer
+;        ADDLT   r4, r4, r2                ; reduce height
+;        SUBLT   r5, r5, r2, LSL #3        ; and advance data pointer (8 bytes per row) to clip pointer to 0
+;        MOVLT   r2, #0
+;        CMP     r4, #0
+;        BLE     %FT90                     ; pointer off if clipped to oblivion
+;
+;        LDR     r1, VIDC_VertiDisplaySize
+;;        SUB     r1, r1, r2                       ; if display_height - y < pointer height
+;        CMP     r1, r4
+;        MOVLT   r4, r1                           ; clip pointer height
+;        CMP     r4, #0
+;        BLE     %FT90                            ; pointer off if clipped to oblivion
+
+;        LDR     r1, VIDC_PointerVAdjust
+;        ADD     r2, r2, r1                       ; y := y+adjust
+
+;        ORR     r1, r2, #VertiCursorStart
+;        STR     r1, [r14]
+
+;        ADD     r2, r2, r4                ; y:= y+height
+;        ORR     r1, r2, #VertiCursorEnd
+;        STR     r1, [r14]
+;
+;        LDR     r14, IOMD_Address
+;        STR     r5, [r14, #IOMD_CURSINIT]
+;
+;        Pull    "r4, r5, pc"
+
+;90
+;
+; pointer off
+;
+;        MOV     r4, #VertiCursorStart
+;        STR     r4, [r14]
+;        MOV     r4, #VertiCursorEnd
+;        STR     r4, [r14]
+;
+;        Pull    "r4, r5, pc"
+
+; -------------------------------------------------------------------------
+
+; void HAL_Video_SetDAG(uint DAG, uint paddr)
+;
+; set Video DMA address generator value to given physical address
+;
+; DAG   = 0 set start address of current video display
+;         1 set start address of total video buffer
+;         2 set end address (exclusive) of total video buffer
+;         3 set start address of VDU buffer (i.e. as set by OS_Byte 112)
+;         all other values reserved
+; paddr = physical address for given DAG
+;
+; Notes:
+; The OS has a video buffer which is >= total display size, and may be using
+; bank switching (several display buffers) or hardware scroll within the
+; total video buffer.
+;
+; DAG=1 will be start address of current total video buffer
+; DAG=2 will be end address (exclusive) of current total video buffer
+; DAG=0 will be start address in buffer for current display
+;
+; HALs should respond as follows:
+; 1) If they have no hardware scroll support, only DAG=0 is significant,
+;    and the end address of the current display is implied by the size
+;    of the current mode. Calls with DAG=1,2 should be ignored.
+; 2) If they support hardware scroll, DAG=0 again defines display start.
+;    DAG=2 defines the last address (exclusive) that should be displayed
+;    before wrapping back (if reached within display size), and DAG=1
+;    defines the address to which accesses should wrap back.
+
+VBL_Wait	;LDR r0, LCD_Address
+ ;	LDR	r1, [r0]
+;;	MOV	r1, r1, LSR #18
+;	BICS	r1, r1, #0xFC00
+;	BNE	VBL_Wait
+
+	MOV	pc,lr
+
+DAG_txt = "DAG = "
+	= 0
+
+HAL_Video_SetDAG ROUT
+
+	CMP	r0, #0
+	MOVNE	pc, lr
+
+	STMDB 	sp!,{r0-r5,lr}
+	;STMDB	sp!,{r1}
+	;STMDB	sp!,{r1}
+	;LDR	r0, UART_Address
+	;ADR	r4, DAG_txt
+	;BL	serials
+	;LDMIA	sp!,{r4}
+	;BL	serial8
+
+
+;	BL	VBL_Wait
+
+	;LDMIA	sp!,{r1}
+ 	LDR	r0, LCD_Address
+
+	STR	r1,[r0,#0xA0]
+	STR	r1,[r0,#0xA4]
+	LDR	r2, = (640*272)
+	ADD	r1, r1, r2
+	BIC	r1, r1, #0xFF000000
+	STR	r1,[r0,#0xD0]
+	STR	r1,[r0,#0xD4]
+;	LDR 	r2, [r0]
+;	BIC	r2, r2, #1
+;	STR	r2, [r0]
+
+;	MOV	r1, r1, LSR #1
+;	STR	r1, [r0, #0x14]
+;	BIC	r1, r1, #0xFF000000
+;	BIC	r1, r1, #0x00800000
+
+;	LDR	r2, VIDX_Size
+;	LDR	r3, VID_BPP
+;	MOV	r2, r2, LSL r3
+;	MOV	r2, r2, LSR #3
+;;	MOV	r3, #272
+;	MUL	r2, r3, r2
+;	MOV	r2, r2, LSR #1
+
+;	ADD	r1, r1, r2 ;#0xFF00
+;	ADD	r1, r1, #0x400
+;	STR	r1, [r0, #0x18]
+
+;	LDR	r2, [r0]
+;	ORR	r2, r2, #1
+;	STR	r2, [r0]
+
+;	MOV	pc,lr
+
+	LDMIA	sp!,{r0-r5,pc}
+
+;        LDR     r12, IOMD_Address
+;
+;        CMP     r0, #2
+;        MOVHI   pc, lr
+;
+;        CMP     r0, #1
+;        BEQ     %FT20
+;        BHI     %FT40
+;;
+; DAG=0 program VInit
+;
+;;        STR     r1, IOMD_VInitSoftCopy   ; save VInit so that writes to VEnd can check
+;        LDR     r2, IOMD_VEndSoftCopy
+;        CMP     r1, r2                   ; if VInit >= VEnd then set L bit
+;        ORRCS   r1, r1, #IOMD_DMA_L_Bit
+;        STR     r1, [r12, #IOMD_VIDINIT]
+;        MOV     pc, lr
+;
+; DAG=1 program VStart
+;
+;20      STR     r1, [r12, #IOMD_VIDSTART]
+ ;       MOV     pc, lr
+;
+;
+; DAG=2 program VEnd
+;
+;40      MOV     r2, #0                          ; we must adjust address to that of
+;        LDRB    r2, VRAMWidth                   ; last DMA fetch, allowing for fetch size
+;        CMP     r2, #1
+;        MOVLO   r2, #16                         ; DRAM-only, subtract 16 (quadword)
+;        MOVEQ   r2, #SAMLength/2                ; 1 bank of VRAM - 1/2 SAM
+;        MOVHI   r2, #SAMLength                  ; 2 banks of VRAM - 1/2 SAM * 2
+;        SUB     r1, r1, r2
+;        STR     r1, IOMD_VEndSoftCopy           ; remember VEnd value
+;        LDR     r2, IOMD_VInitSoftCopy          ; load current VInit
+;        CMP     r2, r1                          ; if VInit >= VEnd
+;        ORRCS   r2, r2, #IOMD_DMA_L_Bit         ; then set L bit
+;;        STR     r2, [r12, #IOMD_VIDINIT]        ; store VInit
+;        STR     r1, [r12, #IOMD_VIDEND]         ; and VEnd
+;        MOV     pc, lr
+
+; -------------------------------------------------------------------------
+
+;
+; uint HAL_Video_Features(void)
+;
+; returns a flags word:
+;    bit 0     h/w scroll is supported
+;    bit 1     h/w pointer is supported
+;    bit 2     interlace is supported with progressive framestore
+;    other bits reserved (returned as 0)
+
+HAL_Video_Features ROUT
+        MOV   a1, #0   ; hw scroll, h/w pointer, no interlace
+        MOV   pc, lr
+
+; -------------------------------------------------------------------------
+
+;
+; uint HAL_Video_PixelFormats(void)
+;
+;
+; returns flags word:
+;    bit 0     1 bpp is supported
+;    bit 1     2 bpp is supported
+;    bit 2     4 bpp is supported
+;    bit 3     8 bpp is supported
+;    bit 4    16 bpp is supported
+;    bit 5    32 bpp is supported
+;    other bits reserved (returned as 0)
+;    bits 0-5 refer to support with standard RO pixel layout (little endian
+;    packing for 1,2,4 bpp, 5-5-5 RGB for 16 bpp, etc.)
+;    other formats may be introduced when/if RO supports them
+
+HAL_Video_PixelFormats ROUT
+        MOV   a1, #2_111111   ; 1,2,4,8,16,32 bpp
+        MOV   pc, lr
+
+; -------------------------------------------------------------------------
+
+;
+; uint HAL_Video_BufferAlignment(void)
+;
+; returns the required alignment for the framestore buffer, in bytes
+; (expected to be a power of 2)
+
+HAL_Video_BufferAlignment ROUT
+        MOV   a1, #32          ; align to 32 bytes
+        MOV   pc, lr
+
+; -------------------------------------------------------------------------
+
+;
+; uint HAL_Video_OutputFormat(void)
+;
+; returns current video output format
+;      0 = analogue (or 'normal', unspecified)
+;      1 = 16-bit non-multiplexed RGB 5-6-5 (Chrontel 7003 format 0)
+;     ...
+;     10 = Chrontel 7003 format 9
+;  >= 11 reserved
+;
+
+HAL_Video_OutputFormat
+        MOV   a1, #0     ;normal/unspecified
+        MOV   pc, lr
+
+; -------------------------------------------------------------------------
+
+;;;mjsHAL - is the mode workspace really generic enough to pass to HAL?
+;;;
+
+;
+; int HAL_Video_VetMode(const void *VIDClist, const void *workspace)
+;
+; VIDClist  -> generic video controller list (VIDC list type 3)
+; workspace -> mode workspace (if mode number), or 0
+; returns 0 if OK (may be minor adjusts to VIDClist and/or workspace values)
+;         non-zero if not OK
+;
+HAL_Video_VetMode ROUT
+        MOV   r0,#0    ; do nothing for now
+        MOV   PC,LR
+
+; -------------------------------------------------------------------------
+
+        END
+
-- 
GitLab