From fa159ee5eec87c1efe529e8de0f1e1baa4171d36 Mon Sep 17 00:00:00 2001
From: Mike Stephens <mstephen@gitlab.riscosopen.org>
Date: Thu, 5 Oct 2000 11:55:13 +0000
Subject: [PATCH] further kernel/HAL split work in video area almost-HAL code
 for VIDC20/IOMD in vdu.vduhint, now almost divorced from kernel workspace
 tested briefly in Ursula desktop environment

Version 5.35, 4.79.2.4. Tagged as 'Kernel-5_35-4_79_2_4'
---
 VersionASM       |  12 +-
 VersionNum       |  16 +--
 hdr/KernelWS     |  14 ++-
 s/ARM600         | 134 ++++----------------
 s/vdu/vdudecl    |  10 +-
 s/vdu/vdudriver  |  31 ++---
 s/vdu/vduhint    | 311 ++++++++++++++++++++++-------------------------
 s/vdu/vdupalxx   |  24 ++--
 s/vdu/vdupointer |   2 +-
 s/vdu/vduwrch    |  87 ++++++-------
 10 files changed, 276 insertions(+), 365 deletions(-)

diff --git a/VersionASM b/VersionASM
index 4d38de21..97cf8ae4 100644
--- a/VersionASM
+++ b/VersionASM
@@ -11,10 +11,10 @@
                         GBLS    Module_HelpVersion
 Module_MajorVersion     SETS    "5.35"
 Module_Version          SETA    535
-Module_MinorVersion     SETS    "4.79.2.3"
-Module_Date             SETS    "03 Oct 2000"
-Module_ApplicationDate2 SETS    "03-Oct-00"
-Module_ApplicationDate4 SETS    "03-Oct-2000"
-Module_FullVersion      SETS    "5.35 (4.79.2.3)"
-Module_HelpVersion      SETS    "5.35 (03 Oct 2000) 4.79.2.3"
+Module_MinorVersion     SETS    "4.79.2.4"
+Module_Date             SETS    "05 Oct 2000"
+Module_ApplicationDate2 SETS    "05-Oct-00"
+Module_ApplicationDate4 SETS    "05-Oct-2000"
+Module_FullVersion      SETS    "5.35 (4.79.2.4)"
+Module_HelpVersion      SETS    "5.35 (05 Oct 2000) 4.79.2.4"
                         END
diff --git a/VersionNum b/VersionNum
index 69df788d..b689cf6c 100644
--- a/VersionNum
+++ b/VersionNum
@@ -4,16 +4,16 @@
  *
  */
 #define Module_MajorVersion_CMHG        5.35
-#define Module_MinorVersion_CMHG        4.79.2.3
-#define Module_Date_CMHG                03 Oct 2000
+#define Module_MinorVersion_CMHG        4.79.2.4
+#define Module_Date_CMHG                05 Oct 2000
 
 #define Module_MajorVersion             "5.35"
 #define Module_Version                  535
-#define Module_MinorVersion             "4.79.2.3"
-#define Module_Date                     "03 Oct 2000"
+#define Module_MinorVersion             "4.79.2.4"
+#define Module_Date                     "05 Oct 2000"
 
-#define Module_ApplicationDate2         "03-Oct-00"
-#define Module_ApplicationDate4         "03-Oct-2000"
+#define Module_ApplicationDate2         "05-Oct-00"
+#define Module_ApplicationDate4         "05-Oct-2000"
 
-#define Module_FullVersion              "5.35 (4.79.2.3)"
-#define Module_HelpVersion              "5.35 (03 Oct 2000) (4.79.2.3)"
+#define Module_FullVersion              "5.35 (4.79.2.4)"
+#define Module_HelpVersion              "5.35 (05 Oct 2000) (4.79.2.4)"
diff --git a/hdr/KernelWS b/hdr/KernelWS
index 6f0fa693..40b3d330 100644
--- a/hdr/KernelWS
+++ b/hdr/KernelWS
@@ -683,7 +683,7 @@ TotalScreenSize # 4     ; Amount configured for screen (in bytes)
 
 MaxMode # 4             ; Maximum mode number allowed (20 for now)
 
-VinitCopy # 4   ; Copy of Vinit for VDU 23;12 or 13
+        # 4             ; SPARE
 
 CursorFlags # 4 ; Silly Master cursor movement flags
 
@@ -1030,9 +1030,7 @@ EvtHan          #       4
 ; (256 words) which is no longer adequate, so we can reuse it
 
 JordanWS        #       0
-VInitSoftCopy   #       4       ; soft copy of VInit so we can set L bit correctly
-VEndSoftCopy    #       4       ; soft copy of VEnd  ------------""---------------
-VStartSoftCopy  #       4       ; soft copy of VStart so we can calculate VIDINITB correctly
+                #       3*4     ; SPARE
 DAList          #       4       ; Pointer to first node on dynamic area list
 
 
@@ -1104,12 +1102,16 @@ InitKbdWs       #       16      ; Workspace for reset keyboard IRQ code (was 12
 CLine_Softcopy  #        1      ; Added for Morris - Monitor id
 
 VRAMWidth       #       1       ; 0 => no VRAM, 1 => 32-bits wide, 2 => 64-bits wide
-                [ :LNOT: STB
+
+     [ {FALSE} ;;; mjsHAL no LCD support
 LCD_Active      #       1       ; Added to support LCD/CRT switching. bm 6 bits 0=>External CRT in use, 1=>Mono, 2=>Passive colour, 3=>Active colour
                                 ;                                     bit 7     unset=>single panel, set=>dual panel
 LCD_Inverted    #       1       ; Added to support LCD palette inversion. 0=normal, 1=inverted. Note that the inversion is invisible to apps.
  ! 0, "LCD_Active flag byte held at  ":CC::STR:(LCD_Active)
-                ]
+     |
+                # 2  ; SPARE
+     ]
+
  [ HAL
                 AlignSpace
 HAL_Descriptor  #       4
diff --git a/s/ARM600 b/s/ARM600
index 85ce92b7..70f3e545 100644
--- a/s/ARM600
+++ b/s/ARM600
@@ -181,99 +181,10 @@ OneMByte                EQU     (1024*1024)
 SixteenMByte            EQU     (1024*1024 * 16)
 
 ; *****************************************************************************
-;
-;       SetDAG - Program DMA address generator R1 with physical address R0
-;       NB on IOMD this is the true physical address, not just offset into VRAM or DRAM
-;
-; in:   r0 = physical address
-;       r1 = index of DMA address generator to program, as defined in vdudecl
-;
-; out:  All registers preserved, operation ignored if illegal
-;
-
-SetDAG  Entry   "r0-r1,r12"
-        MOV     r12, #IOMD_Base
-        CMP     r1, #1
-        BEQ     %FT10
-        BHI     %FT20
-
-; Program VInit
-
-00
-        ASSERT  MEMCDAG_VInit = 0
-        MOV     r14, #0
-        STR     r0, [r14, #VInitSoftCopy]       ; save VInit so that writes to VEnd can check
-        LDR     r14, [r14, #VEndSoftCopy]
-        CMP     r0, r14                         ; if VInit >= VEnd then set L bit
-        ORRCS   r0, r0, #IOMD_DMA_L_Bit
-        STR     r0, [r12, #IOMD_VIDINIT]
-
-        [ :LNOT: STB
-        MOV     r1, #0
-        LDRB    r1, [r1, #LCD_Active]
-        TST     r1, #&80
-        EXIT    EQ                              ;Exit if not a dual-panel LC display
-        ]
-
-        ;Otherwise, we are going to have to update VIDINITB too...
-        MOV     r1, #VduDriverWorkSpace
-        LDR     r1, [r1, #ScreenSize]
-        BIC     r0, r0, #IOMD_DMA_L_Bit
-        ADD     r0, r0, r1, LSR #1              ;R0 = VIDINIT+(screensize/2)
-        CMP     r0, r14                         ;If VIDINITB>=VEnd...
-        ORREQ   r0, r0, #IOMD_DMA_L_Bit         ;Set the L bit if =
-        SUBGT   r0, r0, r14                     ;VIDINITB=VIDINITB-VEnd
-        MOVGT   r14, #0
-        LDRGT   r1, [r14, #VStartSoftCopy]
-        ADDGT   r0, r0, r1                      ;VIDINITB=VIDINITB+VStart
-        SUBGT   r0, r0, #16                     ;Quad word correction. /** You are not expected to understand this **/ :-)
-        STR     r0, [r12, #IOMD_VIDINITB]
-        EXIT
-
-; Program VStart
-
-10
-        ASSERT  MEMCDAG_VStart = 1
-        MOV     r14, #0
-        STR     r0, [r14, #VStartSoftCopy]
-        STR     r0, [r12, #IOMD_VIDSTART]
-        EXIT
-
-20
-        CMP     r1, #3
-        EXIT    HI
-        BEQ     %FT30
-
-; Program VEnd
-
-        ASSERT  MEMCDAG_VEnd = 2
-        MOV     r14, #0
-        STR     r0, [r14, #VEndSoftCopy]        ; remember old VEnd value
-        LDR     r14, [r14, #VInitSoftCopy]      ; load old VInit
-        CMP     r14, r0                         ; if VInit >= VEnd
-        ORRCS   r14, r14, #IOMD_DMA_L_Bit       ; then set L bit
-        STR     r14, [r12, #IOMD_VIDINIT]       ; store VInit
-        STR     r0, [r12, #IOMD_VIDEND]         ; and VEnd
-
-        [ :LNOT: STB
-        MOV     r14, #0
-        LDRB    r14, [r14, #LCD_Active]
-        TST     r14, #&80
-        EXIT    EQ                              ; Not a dual-panel LCD so no need to hang around....
-        ]
-
-        ;Check whether we need to update VIDINITB or not...
-
-        EXIT
-
-; Program CInit
-
-30
-        ASSERT  MEMCDAG_CInit = 3
-        STR     r0, [r12, #IOMD_CURSINIT]
-        EXIT
-
 
+; mjs Oct 2000 kernel/HAL split
+; SetDAG stuff is no more, routines like SetVinit now call equivalent HAL
+; routine
 
 ; **************** CAM manipulation utility routines ***********************************
 
@@ -631,7 +542,16 @@ SSETMEMC ROUT
         ORR     r11, r11, #MEMCADR
         STR     r11, [r12, #MEMC_CR_SoftCopy]
 
-; We now have to mimic the relevant bits of the MEMC1 control register
+; mjs Oct 2000 kernel/HAL split
+;
+; The kernel itself should now never call this SWI, but grudgingly has
+; to maintain at least bit 10 of soft copy
+;
+; Here, we only mimic action of bit 10 to control video/cursor DMA (eg. for ADFS)
+; The whole OS_UpdateMEMC thing would ideally be withdrawn as archaic, but
+; unfortunately has not even been deprecated up to now
+
+; for reference, the bits of the MEMC1 control register are:
 ;
 ; bits 0,1 => unused
 ; bits 2,3 => page size, irrelevant since always 4K
@@ -642,20 +562,20 @@ SSETMEMC ROUT
 ; bit 11   => Sound DMA enable
 ; bit 12   => OS mode
 
-        Push    "r10"
-        MOV     r12, #IOMD_Base
-        TST     r11, #1 :SHL: 10   ; see if video DMA wants to be enabled
-        LDRB    r11, [r12, #IOMD_VIDCR]
-        AND     r11, r11, #(&7F :AND: :NOT: IOMD_VIDCR_Enable)  ; knock out bit 7 and video DMA enable bit
-        ORRNE   r11, r11, #IOMD_VIDCR_Enable
-  [ :LNOT: STB
-        MOV     r10, #0
-        LDRB    r10, [r10, #LCD_Active]
-        TST     r10, #&80
-        ORRNE   r11, r11, #IOMD_VIDCR_Dup                       ;Set bit 7 if we're on an LCD dual-panel display
-  ]
-        Pull    "r10"
-        STRB    r11, [r12, #IOMD_VIDCR]
+        Push  "r0-r3, r9, r14"   ; can corrupt r12
+        TST   r11, #(1 :SHL: 10)
+        MOVEQ r0, #1             ; blank (video DMA disable)
+        MOVNE r0, #0             ; unblank (video DMA enable)
+        MOV   r1, #0             ; no funny business with DPMS
+;;;
+;;;mjsHAL my temporary macros aren't defined early enough!
+;;;        mjsAddressHAL
+;;;        mjsCallHAL    HAL_Video_SetBlank
+   LDR     r9, =mjs_tempHALworkspace
+   LDR     r9, [r9]
+   BL      HAL_Video_SetBlank
+;;;
+        Pull  "r0-r3, r9, r14"
 
         WritePSRc SVC_mode+I_bit, r11
         ExitSWIHandler
diff --git a/s/vdu/vdudecl b/s/vdu/vdudecl
index a48b7718..0558b07e 100644
--- a/s/vdu/vdudecl
+++ b/s/vdu/vdudecl
@@ -46,14 +46,12 @@ Link    RN 14
 
 PhysCursorStartAdr * CursorSoundPhysRAM
 
-; Reason codes for generalised DAG interface - independent of MEMC type
+; Reason codes for generalised DAG interface
 
-MEMCDAG_VInit   *       0
-MEMCDAG_VStart  *       1
-MEMCDAG_VEnd    *       2
-MEMCDAG_CInit   *       3
+HALDAG_VInit   *       0
+HALDAG_VStart  *       1
+HALDAG_VEnd    *       2
 
-MEMCDAG_MaxReason *     3
 
  [ ModeSelectors
 
diff --git a/s/vdu/vdudriver b/s/vdu/vdudriver
index 8ce6a02c..10804940 100644
--- a/s/vdu/vdudriver
+++ b/s/vdu/vdudriver
@@ -609,10 +609,7 @@ VduBadExit                              ; jumped to if an error in VDU code
 
 ModeChangeSub ROUT
         Push    lr
-        [ :LNOT: STB
-        MOV     r1, #0
-        STRB    r1, [r1, #LCD_Active]   ;Default to non-lcd active, single panel (mainly for Stork power-saving info)
-        ]
+
         MOV     R1, #Service_PreModeChange
         IssueService
         TEQ     R1, #0                  ; was service claimed ?
@@ -723,7 +720,8 @@ TV_Mode_string
         BL      IssueModeService
 
 
-        [ LCDPowerCtrl :LAND: :LNOT: STB
+        [ {FALSE} ;;; LCDPowerCtrl :LAND: :LNOT: STB
+                  ;;; mjsHAL no LCD support
         ;Switch LCD off here if it is _not_ an LCD mode
         MOV     R3, #0
         LDRB    R3, [R3, #LCD_Active]
@@ -867,15 +865,19 @@ TV_Mode_string
 
         ADD     R13, R13, #PushedInfoSize       ; junk stacked data
 
-;;; mjsHAL - still some hardware dependency here - IOMD for DMA etc
-;;;          needs transfer to HAL routine, either as part of hit-specific-VIDC
-;;;          call above, or as additional call(s)
-
-        MOV     R0, #(1 :SHL: 10)       ; enable video DMA
-        ORR     R1, R0, #(1 :SHL: 9)    ; refresh only in vflyback
-        SWI     XOS_UpdateMEMC
+        ; for backward compatibility, show that video DMA is enabled in
+        ; MEMC soft copy (DON'T call OS_UpdateMEMC, which would also
+        ; make redundant call to HAL)
+        ;
+        SavePSR R2
+        MOV     R0, #0
+        WritePSRc SVC_mode+I_bit+F_bit, R14
+        LDR     R1, [R0, #MEMC_CR_SoftCopy]
+        ORR     R1, R1, #(1 :SHL: 10)
+        STR     R1, [R0, #MEMC_CR_SoftCopy]
+        RestPSR R2
 
-        BL      SetVendDefault                  ; set to ScreenEndAdr-16
+        BL      SetVendDefault
 
         MOV     R1, #ScreenEndAdr               ; need to reload cos corrupt
         LDR     R2, [WsPtr, #TotalScreenSize]
@@ -891,7 +893,8 @@ TV_Mode_string
         BL      SetMouseRectangle
         BL      FF
 
-        [ LCDPowerCtrl :LAND: :LNOT: STB
+        [ {FALSE} ;;; LCDPowerCtrl :LAND: :LNOT: STB
+                  ;;; mjsHAL no LCD support
         ;Switch the LCD on if LCD mode
         Push    "r0"
         MOV     R1, #0
diff --git a/s/vdu/vduhint b/s/vdu/vduhint
index 6c3d8865..8e912a88 100644
--- a/s/vdu/vduhint
+++ b/s/vdu/vduhint
@@ -18,15 +18,15 @@
 ;
 ; part of Kernel/HAL division
 ;
-; Author M Stephens
+; Author Mike Stephens (mjs)
 ; Date   Sep 2000
 
 ;;;mjsHAL
 ;
 ; vduhint is currently also a repository for VIDC20/IOMD specific HAL
 ; code, as stage 1 of Kernel/HAL split for video code
-; eventually, vduhint should just be veneer for calls to defined HAL routines
-;
+; eventually, vduhint should either have any veneer code/defns or
+; should disappear altogether
 
 ; temp mjs versions of macros to call HAL routines
 ;
@@ -65,8 +65,10 @@
 
 ; -----------------------------------------------------------------------------------
 
+;
 ; TEMP defn for workspace while code still in kernel
 ; layout of workspace block anchored at mjs_tempHALworkspace
+;
 
                             ^    0
 mjs_thalwk_start            #    0
@@ -82,6 +84,8 @@ VIDC_FSynSoftCopy           #    4
 VIDC_ControlSoftCopy        #    4
 VIDC_HSWRSoftCopy           #    4   ; horizontal sync width
 VIDC_VSWRSoftCopy           #    4   ; vertical sync width
+IOMD_VInitSoftCopy          #    4
+IOMD_VEndSoftCopy           #    4
 mjs_thalwk_end              #    0
 
 mjs_thalwk_size * mjs_thalwk_end - mjs_thalwk_start
@@ -97,23 +101,6 @@ mjs_tempHALworkspace_init ROUT
     STR      lr, [r0, #VIDC_Interlace]
     Pull     "r0, pc"
 
-; -----------------------------------------------------------------------------------
-
-;;;mjsHAL - is the mode workspace really generic enough to pass to HAL?
-;;;
-
-; HAL routine
-;
-; int HAL_Video_VetMode(void *VIDClist, 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
 
 ; -------------------------------------------------------------------------
 
@@ -240,18 +227,6 @@ DCR_HDWRShift   *       0
 
 ; -------------------------------------------------------------------------
 
-;;;mjsHAL
-;;;
-;;;  HAL_Video_SetMode - routine for HAL to support VIDC20
-;;;
-;;;  mjs: adapted from ProcessVIDCListType3 in old kernel
-;;;
-;;;  this code still accesses kernel variable(s),
-;;;  also calls ComputeModuli
-;;;  also calls ProcessControlListItem
-;;;  so more work needed to fully divorce it
-;;;  put here for first stage of kernel/HAL split
-
 ;
 ;  void HAL_Video_SetMode(const void *VIDCList3)
 ;
@@ -259,6 +234,7 @@ DCR_HDWRShift   *       0
 ;
 ;  in: VIDClist -> video mode list (in VIDCList type 3 format)
 ;      (and sb (r9) -> HAL workspace)
+;
 
 HAL_Video_SetMode ROUT
         Push    "r4, r7,r8,r10,r11, lr"
@@ -416,6 +392,8 @@ FIFOLoadTable
         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
 
+  ! 0, "mjsHAL - using kernel variable IOSystemType"
+
  [ MorrisSupport
         MOV     R1, #0
         LDRB    R1, [R1, #IOSystemType]
@@ -464,20 +442,19 @@ FIFOLoadTable
         ADD     R0, r11, #(&80*4)           ; R0 -> VIDC20 table (remove offset for reg indices starting at &80)
         BL      ProgramVIDC20Regs
 
+        ; now make sure video DMA enabled
+        ;
+        MOV     r7, #IOMD_Base
+        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"
 
 ; -------------------------------------------------------------------------
 
-
-;;;
-;;; mjsHAL - code for hitting VIDC20 registers, taken from s.vdudriver
-;;;
-;;;    eventually, need to do *TV adjustment to VIDCList3 itself before calling HAL routine
-;;;    other adjustments in old code, remembering things in kernel variables etc.
-;;;    may have to stay for this first stage, but need sorting when candidate HAL
-;;;    routine is really moved out of kernel
-
 ; ProgramVIDC20Regs - program registers from table
 ;
 ;  entry: r0 -> VIDC table to program into registers
@@ -492,19 +469,6 @@ ProgramVIDC20Regs ROUT
         TST     R4, #1
         MOVNE   R4, #CR_Interlace
 
- [ STB
-;;;mjsHAL - unacceptable to call SWI from HAL code, needs sorting
-;;;
-        LDR     R1, [R0, #(PseudoRegister_HClockSpeed:SHR:22)-&80*4] ; are we using HCLK?
-        CMP     R1, #-1
-        Push    "r0-r1"
-        MOVEQ   R0, #1                  ; if not, pull the TV_Mode GPIO line low (if present)
-        MOVNE   R0, #3                  ; if we are, pull it high
-        ADR     R1, TV_Mode_string
-        SWI     XPortMan_AccessBit      ; (don't forget svc_PortMan below)
-        Pull    "r0-r1"
- ]
-
         MOV     R7, R0                  ; keep copy in R7 in case we go wrong
         MOV     R3, #VIDC               ; R3 -> VIDC20 h/w
 18
@@ -531,13 +495,12 @@ ProgramVIDC20Regs ROUT
         TEQ     R6, #VIDCExternal       ; check for external register (which contains syncs)
         BNE     %FT50
 
-;;;mjsHAL this calls a SWI - not acceptable eventually for HAL, see comments for ReadSyncType
-        Push    "r4"
-        BL      ReadSyncType
-        Pull    "r4"
-
-        BICNE   R2, R2, #(Ext_HSYNCbits :OR: Ext_VSYNCbits)     ; if composite sync then don't invert syncs
-        ORRNE   R2, R2, #Ext_InvertCompVSYNC :OR: Ext_InvertCompHSYNC ; and force both syncs to be composite (because of lack of
+   ! 0, "mjsHAL - currently assume vertical sync rather than find out (by HAL call to OS?)"
+;;;
+;;;mjsHAL old code that operated on NE if composite sync found from SWI OS_ReadSysInfo 1
+;;;
+;;;     BICNE   R2, R2, #(Ext_HSYNCbits :OR: Ext_VSYNCbits)     ; if composite sync then don't invert syncs
+;;;     ORRNE   R2, R2, #Ext_InvertCompVSYNC :OR: Ext_InvertCompHSYNC ; and force both syncs to be composite (because of lack of
                                                                 ; swap in A540 VIDC card)
         B       %FT75
 50
@@ -564,6 +527,8 @@ ProgramVIDC20Regs ROUT
         TEQ     r6, #VIDCDataControl
         BNE     %FT65
 
+   ! 0, "mjsHAL - using kernel variable VRAMWidth"
+
         BIC     r2, r2, #DCR_BusBits
         MOV     r14, #0
         LDRB    r14, [r14, #VRAMWidth]
@@ -631,31 +596,6 @@ ProgramVIDC20Regs ROUT
 
 ; -------------------------------------------------------------------------
 
-;;; mjsHAL - spliced here for now (called by code above)
-
-;;; note, we would _not_ want to call a SWI from HAL
-;;; eventually, either this info is passed in to routine above, or HAL must
-;;; make a call back to kernel
-;;; (such calls have similar ATPCS style API, but there is no r9=workspace)
-
-;
-;       ReadSyncType - Read sync type
-;
-; out:  R4 = sync type (0 or 1)
-;       Z set/clear on R4
-;       All other registers preserved
-;
-
-ReadSyncType Entry "r0-r2"
-        MOV     r0, #1
-        SWI     XOS_ReadSysInfo         ; out: r0 = mode, r1 = monitortype, r2 = sync
-        MOVS    r4, r2                  ; move into r4
-        EXIT
-
-; -------------------------------------------------------------------------
-
-;;; mjsHAL - ProcessControlListItem spliced here for now, not investigated deeply
-;;;
 ;
 ;       ProcessControlListItem
 ;
@@ -683,20 +623,14 @@ ProcessControlListItem Entry
         &       ProcessControlListDPMSState             ; 11 - DPMS state
         &       ProcessControlListNOP                   ; 12 - Interlaced mode
 
+  ! 0, "mjsHAL - no LCD support (VIDCList3 control list stuff)"
+
 ProcessControlListLCDMode
-        [ STB
-        MOV     r1, #Ext_LCDGrey
-        |
-        MOV     r0, #0
-        LDRB    r1, [r0, #LCD_Active]           ;Read the existing value
-        AND     r1, r1, #&80                    ;Clear all but the single/dual bit, 'cos this might have been set already
-        ORR     r1, r1, r2                      ;Bung our new lcdmode into the byte, and....
-        STRB    r1, [r0, #LCD_Active]           ;...store in the KernelWS which LCD mode we are in.
-        MOV     r1, #Ext_ECKOn                  ;Set the ECLK on
-
-        CMP     r2, #3                          ;Was (is) it active-matrix?
-        ORRNE   r1, r1, #Ext_LCDGrey            ;If not, set the LCD greyscaler 'on'
-        ]
+        ;;;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
@@ -709,14 +643,10 @@ ProcessControlListLCDMode
         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
 
-ProcessControlListHiResMode
-        MOV     r1, #Ext_HiResMono              ; bit of a misnomer, it's not nec. mono
-        B       %BT05
-
 ProcessControlListDACControl
         MOV     r1, #Ext_DACsOn
         B       %BT05
@@ -733,64 +663,16 @@ ProcessControlListExternalRegister
         B       %BT15
 
 ProcessControlListLCDDualPanelMode
-        [ STB
-        MOV     r0, #VIDCControl
-        MOV     r1, #CR_DualPanel
-        B       %BT10
-        |
-        MOV     r0, #0
-        LDRB    r1, [r0, #LCD_Active]
-        ORR     r1, r1, #&80                    ;Set the top bit & leave the rest as-is
-        STRB    r1, [r0, #LCD_Active]           ;Store in the KernelWS that we are in dual-panel LCD mode.
-        LDR     r0, [r11, #VIDCDataControl :SHR: 22]
-        MOV     r1, r0, LSL #(31-10)            ;Put HDWR bits to the top
-        BIC     r0, r0, r1, LSR #(31-10)        ;knock off bits
-        ORR     r0, r0, r1, LSR #(31-11)        ;Put back one bit further up (ie mul by 2)
-        STR     r0, [r11, #VIDCDataControl :SHR: 22]
-
-        LDR     r0, [r11, #VertiDisplayEnd :SHR: 22]
-        LDR     r1, [r11, #VertiDisplayStart :SHR: 22]
-        BIC     r0, r0, #VertiDisplayEnd
-        BIC     r1, r1, #VertiDisplayStart
-        SUB     r0, r0, r1                      ;R0 = Vres
-        ADD     r1, r1, r0, LSR #1              ;R1 = Vres/2 + VDSR
-        ORR     r1, r1, #VertiDisplayEnd
-        STR     r1, [r11, #VertiDisplayEnd :SHR: 22]
-
-        LDR     r1, [r11, #VertiCycle :SHR: 22]
-        BIC     r1, r1, #VertiCycle
-        SUB     r1, r1, r0, LSR #1
-        ORR     r1, r1, #VertiCycle
-        STR     r1, [r11, #VertiCycle :SHR: 22]
-
-        LDR     r1, [r11, #VertiBorderEnd :SHR: 22]
-        BIC     r1, r1, #VertiBorderEnd
-        SUB     r1, r1, r0, LSR #1
-        ORR     r1, r1, #VertiBorderEnd
-        STR     r1, [r11, #VertiBorderEnd :SHR: 22]
-
-        LDR     r1, [r11, #VIDCExternal :SHR: 22]
-        BIC     r1, r1, #Ext_ERegExt
-        ORR     r1, r1, #Ext_ERegGreen
-        STR     r1, [r11, #VIDCExternal :SHR: 22]
-
-        MOV     r0, #VIDCControl
-        MOV     r1, #CR_DualPanel
-        B       %BT10
-        ]
+        ;;;mjsHAL we have no support
+        EXIT
 
 ProcessControlListLCDOffsetRegister0
-        MOV     r0, #LCDOffsetRegister0
-20
-        ORR     r2, r2, r0                      ; put high bits of register at top
-        STR     r2, [r11, r0, LSR #22]           ; and store in array
-        MOV     r0, #VIDC                       ;ACTUALLY PROGRAM VIDC (I know I shouldn't but I don't care - I've got a cold)
-        STR     r2, [r0]
+        ;;;mjsHAL we have no support
         EXIT
 
 ProcessControlListLCDOffsetRegister1
-        MOV     r0, #LCDOffsetRegister1
-        B       %BT20
+        ;;;mjsHAL we have no support
+        EXIT
 
 ProcessControlListHClockSelect
         MOV     r0, #PseudoRegister_HClockSpeed ; pseudo-register holding HClock speed
@@ -804,9 +686,6 @@ ProcessControlListDPMSState
 
 ; -------------------------------------------------------------------------
 
-;;; mjsHAL - ComputeModuli spliced here for now, not investigated deeply
-;;;
-; *****************************************************************************
 ;
 ;       ComputeModuli - Work out VCO moduli for a given frequency
 ;
@@ -970,8 +849,6 @@ ComputeModuli Entry "r2-r12", ComputeModuliStack
 
 ; -------------------------------------------------------------------------
 
-;
-; HAL routine, implemented for VIDC20
 ;
 ; void HAL_Video_WritePaletteEntry(uint type, uint pcolour, uint index)
 ;
@@ -1045,8 +922,6 @@ HV_WritePalettEntry_type1
 
 ; -------------------------------------------------------------------------
 
-;
-; HAL routine, implemented for VIDC20
 ;
 ; void HAL_Video_WritePaletteEntries(uint type, const uint *pcolours, uint index, uint Nentries)
 ;
@@ -1123,8 +998,6 @@ HAL_Video_WritePaletteEntries ROUT
 
 ; -------------------------------------------------------------------------
 
-;
-; HAL routine, implemented for VIDC20
 ;
 ; uint HAL_Video_ReadPaletteEntry(uint type, uint pcolour, uint index)
 ;
@@ -1196,6 +1069,12 @@ HAL_Video_SetInterlace ROUT
 ; 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
 
         MOV     r3, #VIDC
@@ -1220,6 +1099,12 @@ HAL_Video_SetBlank ROUT
         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]
+
+        MOV     r0, #IOMD_Base
+        LDRB    r1, [r0, #IOMD_VIDCR]
+        BIC     r1, r1, #IOMD_VIDCR_Enable   ; disable video DMA
+        STRB    r1, [r0, #IOMD_VIDCR]
+
         MOV     pc, lr
 ;
 ; unblanking
@@ -1234,6 +1119,12 @@ HAL_Video_SetBlank ROUT
         TST     r1, #2                                         ; if vsyncs were turned off,
         LDRNE   r2, [R9, #VIDC_VSWRSoftCopy]                   ; then restore from soft copy
         STRNE   r2, [r3]
+
+        MOV     r0, #IOMD_Base
+        LDRB    r1, [r0, #IOMD_VIDCR]
+        ORR     r1, r1, #IOMD_VIDCR_Enable   ; enable video DMA
+        STRB    r1, [r0, #IOMD_VIDCR]
+
         MOV     pc, lr
 
 ; -------------------------------------------------------------------------
@@ -1405,6 +1296,94 @@ HAL_Video_UpdatePointer
 
         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
+;         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.
+
+HAL_Video_SetDAG ROUT
+
+        MOV     r12, #IOMD_Base
+
+        CMP     r0, #1
+        BEQ     %FT20
+        BHI     %FT40
+;
+; DAG=0 program VInit
+;
+        STR     r1, [r9, #IOMD_VInitSoftCopy]   ; save VInit so that writes to VEnd can check
+        LDR     r2, [r9, #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
+
+   ! 0, "mjsHAL - using kernel variable VRAMWidth"
+;
+; DAG=2 program VEnd
+;
+40      MOV     r2, #0                          ; we must adjust address to that of
+        LDRB    r2, [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, [r9, #IOMD_VEndSoftCopy]    ; remember VEnd value
+        LDR     r2, [r9, #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
+
+; -------------------------------------------------------------------------
+
+;;;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
diff --git a/s/vdu/vdupalxx b/s/vdu/vdupalxx
index e40621cd..43624820 100644
--- a/s/vdu/vdupalxx
+++ b/s/vdu/vdupalxx
@@ -930,13 +930,19 @@ PV_BlankScreen ROUT
         mjsCallHAL HAL_Video_SetBlank
         Pull    "r0, r12"
 
-;;;mjsHAL still h/w dependency here for IOMD, needs sorting?
-;;;
+        ; for backward compatibility, show video DMA state in
+        ; MEMC soft copy (DON'T call OS_UpdateMEMC, which would also
+        ; make redundant call to HAL)
+        ;
+        SavePSR r2
+        MOV     r9, #0
+        WritePSRc SVC_mode+I_bit+F_bit, r14
+        LDR     r1, [r9, #MEMC_CR_SoftCopy]
         TEQ     r0, #1
-        MOVEQ   r0, #(0 :SHL: 10) :OR: (3 :SHL: 8) ; blank:   video DMA off, continuous refresh
-        MOVNE   r0, #(1 :SHL: 10) :OR: (0 :SHL: 8) ; unblank: video DMA on, no refresh
-        MOV     r1, #(1 :SHL: 10) :OR: (3 :SHL: 8) ; bits to modify
-        SWI     XOS_UpdateMEMC
+        BICEQ   r1, r1, #(1 :SHL: 10)
+        ORRNE   r1, r1, #(1 :SHL: 10)
+        STR     r1, [r9, #MEMC_CR_SoftCopy]
+        RestPSR r2
 
         BL      UpdateAllPalette        ; update all palette, including border + pointer
 
@@ -1021,10 +1027,8 @@ PV_GammaCorrect ROUT
 ; out:  r4 = 0
 
 PV_LCDInvert ROUT
-        MOV     r4, #0
-        STRB    r0, [r4, #LCD_Inverted]
-
-        BL      UpdateAllPalette
+        ;;;mjsHAL not supported
+        ;;;
         MOV     r4, #0
         Pull    "pc"
  ]
diff --git a/s/vdu/vdupointer b/s/vdu/vdupointer
index 97313756..8ab1db42 100644
--- a/s/vdu/vdupointer
+++ b/s/vdu/vdupointer
@@ -355,7 +355,7 @@ UpdatePointer ROUT
         MOV     R0, #1                       ; R0 = flags, set pointer on (bit 0 = 1)
 
         LDR     R1, [WsPtr, #PointerShapeLA] ; last shape buffer given to HAL
-        LDRNE   R4, [R3, #PointerBuffLA]     ; shape buffer we're about to give
+        LDR     R4, [R3, #PointerBuffLA]     ; shape buffer we're about to give
         TEQ     R1, R4                       ; same as last time?
         STRNE   R4, [WsPtr, #PointerShapeLA] ; update
         ORRNE   R0, R0, #2                   ; flag new shape (bit 1 = 1)
diff --git a/s/vdu/vduwrch b/s/vdu/vduwrch
index 81a33614..07df50d2 100644
--- a/s/vdu/vduwrch
+++ b/s/vdu/vduwrch
@@ -1961,56 +1961,61 @@ ScrollLineDown
 
 ; *****************************************************************************
 ;
-;       SetVinit  - Program Vinit  with address in R0
-;       SetVstart - Program Vstart --------""--------
-;       SetVend   - Program Vend   --------""--------
+;       SetVinit       - Program Vinit with address in R0
+;       SetVstart      - Program Vstart with address in R0
+;       SetVendDefault - Program Vend with end address for TotalScreenSize
 ;
 ; out:  R0-R2 corrupted
 ;
 
+; mjs Oct 2000 kernel/HAL split
+; these routines now call HAL_Video_SetDAG
+
+; Note that the addresses provided are logical addresses for the software mapping
+; of the display, and this starts at (ScreenEndAdr - TotalScreenSize) for
+; wonderful historical reasons (h/w scroll, two mappings, blah, blah) - see eg. PRM 1-354
+;
+; To get physical address for the HAL, we subtract this software mapping start
+; address and add the physical address of the start of video memory.
+;
+
 SetVstart
-        MOV     R1, #MEMCDAG_VStart
-SetLag
-        SUB     R0, R0, #ScreenEndAdr
-        LDR     R2, [WsPtr, #TotalScreenSize]
-        ADD     R0, R0, R2                      ; make startofscreen 0
-        B       SetDAGOffset                    ; call generic interface
+        SUB     r1, r0, #ScreenEndAdr
+        LDR     r2, [WsPtr, #TotalScreenSize]
+        ADD     r1, r1, r2                      ; now we have offset of Vstart in video RAM
+        MOV     r2, #0
+        LDR     r2, [r2, #VideoPhysAddr]
+        ADD     r1, r1, r2                      ; now we have physical address of Vstart
+        MOV     r0, #HALDAG_VStart
+        B       Do_HALDAG
 
 SetVendDefault
- [ MEMC_Type = "IOMD"
-        MOV     R0, #0
-        LDRB    R0, [R0, #VRAMWidth]
-        CMP     R0, #1
-        MOVLO   R0, #16                         ; DRAM-only, subtract 16
-        MOVEQ   R0, #SAMLength/2                ; 1 bank of VRAM - 1/2 SAM
-        MOVHI   R0, #SAMLength                  ; 2 banks of VRAM - 1/2 SAM * 2
-        RSB     R0, R0, #ScreenEndAdr
- |
-        MOV     R0, #ScreenEndAdr
-        SUB     R0, R0, #16
- ]
-        MOV     R1, #MEMCDAG_VEnd
-        B       SetLag
+        MOV     r2, #0
+        LDR     r2, [r2, #VideoPhysAddr]
+        LDR     r1, [WsPtr, #TotalScreenSize]
+        ADD     r1, r1, r2                      ; physical address of Vend
+        MOV     r0, #HALDAG_VEnd
+        B       Do_HALDAG
 
 SetVinit
-        STR     R0, [WsPtr, #DisplayStart]
-        SUB     R0, R0, #ScreenEndAdr
-        LDR     R2, [WsPtr, #TotalScreenSize]
-        ADD     R0, R0, R2                      ; make start of screen 0
-        LDR     R1, [WsPtr, #TeletextOffset]
-        ADD     R0, R0, R1                      ; add on teletext bank offset
-        CMP     R0, R2                          ; if out of range
-        SUBCS   R0, R0, R2                      ; then subtract total size
-SetVinitPhys
-        STR     R0, [WsPtr, #VinitCopy]
-        MOV     R1, #MEMCDAG_VInit
-SetDAGOffset
- [ MEMC_Type = "IOMD"
-        MOV     R2, #0
-        LDR     R2, [R2, #VideoPhysAddr]        ; add on physical address of start of video RAM
-        ADD     R0, R0, R2
- ]
-        B       SetDAG                          ; call generic interface
+        STR     r0, [WsPtr, #DisplayStart]
+        SUB     r1, r0, #ScreenEndAdr
+        LDR     r2, [WsPtr, #TotalScreenSize]
+        ADD     r1, r1, r2                      ; now we have offset of Vinit in video RAM
+        LDR     r0, [WsPtr, #TeletextOffset]
+        ADD     r1, r1, r0                      ; add on teletext bank offset
+        CMP     r1, r2                          ; if out of range
+        SUBCS   r1, r1, r2                      ; then subtract total size
+        MOV     r2, #0
+        LDR     r2, [r2, #VideoPhysAddr]        ; now we have physical address
+        ADD     r1, r1, r2
+        MOV     r0, #HALDAG_VInit
+Do_HALDAG
+        Push    "r3, r9, r12, lr"               ; we can corrupt r0-r2
+        mjsAddressHAL
+        mjsCallHAL    HAL_Video_SetDAG
+        Pull    "r3, r9, r12, lr"
+        MOV     pc, lr
 
 ; *****************************************************************************
 ;
-- 
GitLab