Commit 2851f2e3 authored by Jeffrey Lee's avatar Jeffrey Lee
Browse files

DMAManager fixes & improvements

Detail:
  DMA.s, in DMAForceActivate: Support for the NoInitIRQ flag for interrupt-driven buffer-type channels (API 1+)
  DMA.s, 'testloop': Fix handling of interrupt-driven buffer-type channels so DMAManager doesn't immediately crash or malfunction
  DMA.s, 'overrun', 'earlyoverrun', 'nooverrun': Fix handling of interrupt-driven buffer-type channels so IRQ state is cleared before the next stage of the transfer is programmed (to avoid missing IRQs)
  DMA.s, 'finished': Fix handling of interrupt-driven buffer-type channels so R8 is loaded with the logical channel block ptr, as expected by subsequent function calls.
  Front.s: Make dmaq_Trampoline larger to allow it to contain the HAL device ptr
  GetAll.s: Add Hdr:HALEntries to GET list, as required by 'ClaimVectors' fix in ModHead.s
  ModHead.s: Update controller handling code to cope with API versions 0.1 (TestIRQ2) & 1 ('Deallocate' passed channel device ptr)
  ModHead.s: Fix 'ClaimVectors' to call HAL_IRQEnable to enable IRQs for the detected channels/controllers.
  ModHead.s: Fix IRQ handler trampolines so that they call HALDevice_TestIRQ on the channel instead of branching to a random address in memory
  SWI.s: Support for controller API 1 (pass channel device ptr to 'Deallocate' in R2)
  hdr/DMADevice: Extra flags & entries for new DMA controller & buffer API versions
Admin:
  Tested on rev C2 beagleboard with the incoming HAL DMA driver. API revisions are documented in more detail on the ROOL wiki.


Version 0.18. Tagged as 'DMA-0_18'
parent f5a3895b
......@@ -11,13 +11,13 @@
GBLS Module_HelpVersion
GBLS Module_ComponentName
GBLS Module_ComponentPath
Module_MajorVersion SETS "0.17"
Module_Version SETA 17
Module_MajorVersion SETS "0.18"
Module_Version SETA 18
Module_MinorVersion SETS ""
Module_Date SETS "11 Jun 2009"
Module_ApplicationDate SETS "11-Jun-09"
Module_Date SETS "28 Nov 2009"
Module_ApplicationDate SETS "28-Nov-09"
Module_ComponentName SETS "DMA"
Module_ComponentPath SETS "castle/RiscOS/Sources/HWSupport/DMA"
Module_FullVersion SETS "0.17"
Module_HelpVersion SETS "0.17 (11 Jun 2009)"
Module_FullVersion SETS "0.18"
Module_HelpVersion SETS "0.18 (28 Nov 2009)"
END
/* (0.17)
/* (0.18)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.17
#define Module_MajorVersion_CMHG 0.18
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 11 Jun 2009
#define Module_Date_CMHG 28 Nov 2009
#define Module_MajorVersion "0.17"
#define Module_Version 17
#define Module_MajorVersion "0.18"
#define Module_Version 18
#define Module_MinorVersion ""
#define Module_Date "11 Jun 2009"
#define Module_Date "28 Nov 2009"
#define Module_ApplicationDate "11-Jun-09"
#define Module_ApplicationDate "28-Nov-09"
#define Module_ComponentName "DMA"
#define Module_ComponentPath "castle/RiscOS/Sources/HWSupport/DMA"
#define Module_FullVersion "0.17"
#define Module_HelpVersion "0.17 (11 Jun 2009)"
#define Module_LibraryVersionInfo "0:17"
#define Module_FullVersion "0.18"
#define Module_HelpVersion "0.18 (28 Nov 2009)"
#define Module_LibraryVersionInfo "0:18"
......@@ -33,6 +33,9 @@ HALDevice_DMACEnumerate # 4
HALDevice_DMACAllocate # 4
HALDevice_DMACDeallocate # 4
HALDevice_DMAC_Size * :INDEX: @
; Extra data for API 0.1
HALDevice_DMACTestIRQ2 # 4
HALDevice_DMAC_Size_0_1 * :INDEX: @
; Device for each physical DMA channel (buffer type)
......@@ -56,6 +59,7 @@ DMAFeaturesFlag_DualAddress * 1 :SHL: 0 ; reserved for i
DMAFeaturesFlag_NotCircular * 1 :SHL: 1 ; (list type only)
DMAFeaturesFlag_NotInfinite * 1 :SHL: 2 ; (list type only)
DMAFeaturesFlag_NoSyncIRQs * 1 :SHL: 3 ; (list type only)
DMAFeaturesFlag_NoInitIRQ * 1 :SHL: 4 ; Doesn't generate an IRQ if Activate is called with no pending transfers (buffer type only, API 1.0+)
DMASetOptionsFlag_Write * 1 :SHL: 0
DMASetOptionsShift_Width * 1
......
......@@ -941,8 +941,26 @@ DMAForceActivate
LDR r0, [r5, #HALDevice_Device] ; We only need to program the first transfer now
CMP r0, #-1 ; if the channel has no interrupt.
BNE %FT35 ; Otherwise we rely on the first interrupt to trigger programming.
BEQ %FT32 ; Otherwise we rely on the first interrupt to trigger programming.
MOV r0, r5 ; Except not all DMA controllers can (sensibly) be made to trigger
CallHAL DMAFeatures ; an interrupt when they've got no data, so we need to check the flags as well
TST r0, #DMAFeaturesFlag_NoInitIRQ
BEQ %FT35
; We have an IRQ, so we don't want to use the bounce buffer. Use 'program' to program the controller with the right data.
Push "r5-r10" ; Play it safe and store everything that 'program' might clobber (which hasn't already been stored on entry to DMAActivate)
LDR r0, [r10, #dmar_Length]
MOV r11, r5
LDR r3, [r9, #dmaq_LastBuff]
LDR r7, [r11, #HALDevice_DMASetCurrentTransfer]
ADD r5, r10, #dmar_CurrBuff
LDR r8, [r10, #dmar_Flags]
BL program
Pull "r0,r6-r10" ; Reload device ptr in R0 so we can call the device
CallHAL Activate
EXITS , f
32
ADD r3, r10, #dmar_CurrBuff ; Program current buffer with a single transfer to/from the bounce buffer.
ADD r0, r9, #dmaq_BounceBuff
MOV r1, #0
......@@ -2560,16 +2578,16 @@ testloop
LDR r4, [r10, #dmar_Length] ; (this needs to be unconditional - non-HAL code is broken!)
TEQEQ r4, #0 ; and length = 0
ORREQ r1, r1, #1 ; then take alternate action.
LDR pc, [pc, r1, LSL #2]
ADD pc, pc, r1, LSL #2
DCD 0
DCD nooverrun ; No overrun, more to program
DCD nooverrun_finished ; No overrun, no more to program
DCD overrun ; Overrun, more to program
DCD overrun_finished ; Overrun, no more to program
B nooverrun ; No overrun, more to program
B nooverrun_finished ; No overrun, no more to program
B overrun ; Overrun, more to program
B overrun_finished ; Overrun, no more to program
DCD 0
DCD 0
DCD earlyoverrun ; Early overrun, more to program
DCD finished ; Early overrun, no more to program
B earlyoverrun ; Early overrun, more to program
B finished ; Early overrun, no more to program
nooverrun_finished
ADD r3, r10, #dmar_CurrBuff
......@@ -2588,6 +2606,8 @@ nooverrun_finished
B %FT40
overrun
MOV r0, r11
CallHAL DMAIRQClear
LDR r3, [r9, #dmaq_LastBuff]
ADD r5, r10, #dmar_CurrBuff
MOV r0, r5
......@@ -2600,8 +2620,6 @@ overrun
STR r5, [r9, #dmaq_LastBuff]
MOV r0, #0
STR r0, [r10, #dmar_NextBuff + buff_Len] ; Mark next buffer as not programmed.
MOV r0, r11
CallHAL DMAIRQClear
B %FT40
overrun_finished
......@@ -2615,17 +2633,19 @@ overrun_finished
B finished
earlyoverrun
MOV r0, r11
CallHAL DMAIRQClear
ADD r3, r10, #dmar_CurrBuff
ADD r5, r10, #dmar_NextBuff
LDMIA r5, {r0-r2}
STMIA r3, {r0-r2} ; Copy next to current because we put it in the wrong place before.
STR r3, [r9, #dmaq_LastBuff]
BL reprogram
MOV r0, r11
CallHAL DMAIRQClear
B %FT40
nooverrun
MOV r0, r11
CallHAL DMAIRQClear
ADD r3, r10, #dmar_CurrBuff
LDR r5, [r9, #dmaq_LastBuff]
TEQ r5, r3
......@@ -2639,8 +2659,6 @@ nooverrun
MOV r0, r4
BL program ; Program next transfer.
STR r5, [r9, #dmaq_LastBuff]
MOV r0, r11
CallHAL DMAIRQClear
; drop through...
40
TST r8, #dmarf_Sync
......@@ -2849,7 +2867,9 @@ finished
; r8 = DMA request flags
; r9 = ptr to DMA queue
; r10 = ptr to DMA request block
; [ :LNOT: HAL
; r11 = IOMD base address
; ]
;
Debug int," finished"
DebugTab r3,r4,#&05
......@@ -2875,8 +2895,8 @@ finished_witherror
ORR r8, r8, #dmarf_Completed ; Flag transfer as completed.
STR r8, [r10, #dmar_Flags]
[ :LNOT: HAL
LDR r8, [r10, #dmar_LCB] ; r8->logical channel block
[ :LNOT: HAL
MOV r1, #1 ; Disable physical channel interrupt.
LDR r2, [r8, #lcb_Physical]
[ debugint
......
......@@ -87,7 +87,7 @@ dmaq_DescBlockLogical # 4 ; Transfer descriptors block (li
dmaq_DescBlockPhysical # 4 ; " " " " " physical address.
dmaq_DescBlockCount # 4 ; " " " " " number of entries used.
# (((:INDEX:@)+3):AND::NOT:15)+12-(:INDEX:@)
dmaq_Trampoline # 48 ; Qword-aligned device vector trampoline for physical channel.
dmaq_Trampoline # 52 ; Qword-aligned device vector trampoline for physical channel.
# (((:INDEX:@)+15):AND::NOT:15)-(:INDEX:@)
]
......
......@@ -45,6 +45,7 @@ Module_BaseAddr
GET Hdr:Variables
GET Hdr:DMADevice
GET Hdr:PCI
GET Hdr:HALEntries
]
GET VersionASM
......
......@@ -152,7 +152,7 @@ InitWS
SWI XOS_SetVarVal ; Delete the variable, we no longer need it.
ADR r3, CtrlrList - ctrlr_Next
LDR r0, =(0:SHL:16) + HALDeviceType_SysPeri + HALDeviceSysPeri_DMAC
LDR r0, =(1:SHL:16) + HALDeviceType_SysPeri + HALDeviceSysPeri_DMAC
MOV r1, #0
MOV r8, #4
05 SWI XOS_Hardware
......@@ -271,8 +271,8 @@ DeviceRemove
Push "r14"
LDR r14, [r2, #HALDevice_Version]
TST r14, #&FF:SHL:24
TSTEQ r14, #&FF:SHL:16
Pull "pc", NE ; We only understand major version 0 of any device type
TSTEQ r14, #&FE:SHL:16
Pull "pc", NE ; We only understand major versions 0 & 1 of any device type
Push "r3-r6"
LDR r14, [r2, #HALDevice_Type]
LDR r4, =(HALDeviceType_SysPeri + HALDeviceSysPeri_DMAC) :SHL: 16
......@@ -349,8 +349,8 @@ DeviceAdded
Push "r14"
LDR r14, [r2, #HALDevice_Version]
TST r14, #&FF:SHL:24
TSTEQ r14, #&FF:SHL:16
Pull "pc", NE ; We only understand major version 0
TSTEQ r14, #&FE:SHL:16
Pull "pc", NE ; We understand major versions 0 & 1
Push "r6"
LDR r14, [r2, #HALDevice_Type]
LDR r6, =(HALDeviceType_SysPeri + HALDeviceSysPeri_DMAC) :SHL: 16
......@@ -385,7 +385,7 @@ AddController
MOV r4, r2
MOV r0, r4
CallHAL DMACEnumerate
MOV r5, r0
ADD r5, r0, r1, LSL #2
ASSERT DMAQSize=112
MOV r0, #ModHandReason_Claim ; Create and initialise controller block.
......@@ -412,7 +412,7 @@ AddController
MOV r3, r1, LSL #7
SUB r3, r3, r1, LSL #4
SUB r3, r3, #DMAQSize - dmaq_DMADevice
15 LDR lr, [r5], #4
15 LDR lr, [r5, #-4]! ; Make sure that channel 0 is at the start of the block, for the TestIRQ2-based trampolines to work cleanly
STR lr, [r2, r3]
SUBS r3, r3, #DMAQSize
BPL %BT15
......@@ -463,6 +463,14 @@ InitController
ClaimVectors
[ HAL
Entry ; r0-r6 trashable
; For API version 0.0, only the channels can be used to detect the source of an IRQ. However for API version 0.1+, a new entry point was added to allow the controller to detect the IRQ source.
LDR r6, [r4, #ctrlr_Device]
LDR r1, [r6, #HALDevice_Version]
CMP r1, #0
LDRNE r1, [r6, #HALDevice_DMACTestIRQ2]
CMPNE r1, #0
BNE %FT10 ; Controller TestIRQ2 supported
ADD r1, r4, #ctrlr_DMAQueues + dmaq_Trampoline
LDR r4, [r4, #ctrlr_PhysicalChannels]
......@@ -476,6 +484,7 @@ ClaimVectors
ADREQ lr, TrampolineTemplate
ADRNE lr, TrampolineTemplate_Vectored
LDRB r0, [r6, #HALDevice_Type + 0]
STR r6, [r1, #12*4] ; Note: This is just outside the block we copy below
TEQ r0, #HALDeviceSysPeri_DMAL
LDMIA lr!, {r0,r2,r3,r6}
STMIA r1!, {r0,r2,r3,r6}
......@@ -499,6 +508,15 @@ ClaimVectors
SWI XOS_ClaimDeviceVector
BVS %FT09
; Enabling the IRQ is generally a good thing!
Push "r1-r3,r8,r9"
BIC r0, r5, #1:SHL:31
MOV r8, #0
MOV r9, #EntryNo_HAL_IRQEnable
SWI XOS_Hardware
Pull "r1-r3,r8,r9"
BVS %FT09
08 ADD r1, r1, #DMAQSize
SUBS r4, r4, #1
BNE %BT01
......@@ -506,9 +524,10 @@ ClaimVectors
09
EXIT
TrampolineTemplate
STMDB sp!, {r12, lr}
LDR a1, [pc, #28]
LDR a1, [pc, #36]
MOV lr, pc
LDR pc, [a1, #HALDevice_TestIRQ]
LDR r12, [sp], #4 ; retrieve module wsptr for the likely case that IRQ is genuine
......@@ -516,13 +535,14 @@ TrampolineTemplate
ADDNE a1, pc, #8 ; no flags if we're ever run in 26-bit mode
LDMNEIA a1, {a1, pc} ; interrupt handler now entered with return address on stack
LDR pc, [r13], #4 ; else return if bogus IRQ (can't pass on)
DCD 0 ; so next two words are at same position as in vectored case
DCD 0 ; so next three words are at same position as in vectored case
DCD 0 ; needs patching with address of DMA queue
DCD 0 ; needs patching with DMAInterruptCommon or DMAInterruptList
DCD 0 ; needs patching with address of DMA channel HAL device
TrampolineTemplate_Vectored
STMDB sp!, {r12, lr}
LDR a1, [pc, #28]
LDR a1, [pc, #36]
MOV lr, pc
LDR pc, [a1, #HALDevice_TestIRQ]
TEQ a1, #0
......@@ -533,6 +553,90 @@ TrampolineTemplate_Vectored
LDMIA a1, {a1, pc} ; interrupt handler now entered with return address on stack
DCD 0 ; needs patching with address of DMA queue
DCD 0 ; needs patching with DMAInterruptCommon or DMAInterruptList
DCD 0 ; needs patching with address of DMA channel HAL device
10
; Create one single trampoline to service all the channels for this controller
; The trampoline will be stored in the trampoline slot for the first channel
; On entry (via ClaimVectors):
; r4 = controller block
; r6 = controller device
; Return address on stack
; On exit:
; r0-r6 trashed
ADD r1, r4, #ctrlr_DMAQueues + dmaq_Trampoline
LDR r5, [r6, #HALDevice_Device]
TST r5, #1:SHL:31
ADREQ lr, TrampolineTemplate_Controller
ADRNE lr, TrampolineTemplate_Controller_Vectored
; The type of the first channel is the type of all the channels
LDR r0, [r1, #-dmaq_Trampoline + dmaq_DMADevice]
LDRB r0, [r0, #HALDevice_Type + 0]
STR r6, [r1, #12*4] ; Store controller device ptr
TEQ r0, #HALDeviceSysPeri_DMAL
; Copy 11 words of code for vectored case
LDMIA lr!, {r0,r2,r3,r6}
STMIA r1!, {r0,r2,r3,r6}
LDMIA lr!, {r0,r2,r3,r6}
STMIA r1!, {r0,r2,r3,r6}
LDMIA lr!, {r0,r2,r3}
STMIA r1!, {r0,r2,r3}
SUB r1, r1, #11*4
ADRNEL lr, DMAInterruptCommon
ADREQL lr, DMAInterruptList
STR lr, [r1, #11*4]
MOV r0, #1
ADD r2, r1, #12*4-4
SWI XOS_SynchroniseCodeAreas
MOV r0, r5
MOV r2, r12
SWI XOS_ClaimDeviceVector
BVS %FT19
; Enabling the IRQ is generally a good thing!
Push "r8,r9"
BIC r0, r5, #1:SHL:31
MOV r8, #0
MOV r9, #EntryNo_HAL_IRQEnable
SWI XOS_Hardware
Pull "r8,r9"
19
EXIT
TrampolineTemplate_Controller
STMDB sp!, {r12, lr}
LDR a1, [pc, #36]
MOV lr, pc
LDR pc, [a1, #HALDevice_DMACTestIRQ2]
LDR r12, [sp], #4 ; retrieve module wsptr for the likely case that IRQ is genuine
ASSERT DMAQSize=112
RSBS a1, a1, a1, LSL #3 ; a1=a1*7, so still negative if a1=-1
SUBPL a2, pc, #8*4+(:INDEX:dmaq_Trampoline) ; Get ptr to DMA queue 0. This relies on the trampolines being stored as part of the queue list!
ADDPL a1, a2, a1, LSL #4
LDRPL pc, [pc, #4] ; interrupt handler now entered with return address on stack
LDR pc, [r13], #4 ; else return if bogus IRQ (can't pass on)
DCD 0 ; Empty, so next two words words are at same position as in vectored case
DCD 0 ; needs patching with DMAInterruptCommon or DMAInterruptList
DCD 0 ; needs patching with address of DMA controller HAL device
TrampolineTemplate_Controller_Vectored
STMDB sp!, {r12, lr}
LDR a1, [pc, #36]
MOV lr, pc
LDR pc, [a1, #HALDevice_DMACTestIRQ2]
ASSERT DMAQSize=112
RSBS a1, a1, a1, LSL #3
ADDMI sp, sp, #4 ; junk module wsptr and
LDRMI pc, [sp], #4 ; pass on if not claimed
LDR r12, [sp], #8 ; else retrieve module wsptr and junk pass-on address
SUB a2, pc, #10*4+(:INDEX:dmaq_Trampoline) ; Get ptr to DMA queue 0. This relies on the trampolines being stored as part of the queue list!
ADD a1, a2, a1, LSL #4
LDR pc, [pc, #-4] ; interrupt handler now entered with return
DCD 0 ; needs patching with DMAInterruptCommon or DMAInterruptList
DCD 0 ; needs patching with address of DMA controller HAL device
|
Entry "r1,r2"
......@@ -605,11 +709,18 @@ ReleaseVectors
[ HAL
Entry ; r0-r6 trashable
ADD r1, r4, #ctrlr_DMAQueues + dmaq_Trampoline
LDR r3, [r4, #ctrlr_PhysicalChannels]
LDR r0, [r4, #ctrlr_Device]
LDR r3, [r0, #HALDevice_Version]
CMP r3, #0
LDRNE r3, [r6, #HALDevice_DMACTestIRQ2]
CMPNE r3, #0
LDREQ r3, [r4, #ctrlr_PhysicalChannels] ; Controller doesn't support TestIRQ2, so has full compliment of trampolines
MOVNE r3, #1 ; Controller does support TestIRQ2, so only has 1 trampoline
MOV r2, r12
BNE %FT02 ; Skip device lookup, we want to deregister the nonshared controller IRQ, not the shared channel IRQ (which devices retain for backwards compatability)
01 LDR r0, [r1, #-dmaq_Trampoline + dmaq_DMADevice]
LDR r0, [r0, #HALDevice_Device]
02 LDR r0, [r0, #HALDevice_Device]
CMP r0, #-1 ; no interrupt for this channel?
SWINE XOS_ReleaseDeviceVector
......
......@@ -440,8 +440,8 @@ SWIDeregisterChannel
[ HAL
LDR r9, [r8, #lcb_Queue]
LDR r0, [r9, #dmaq_DMADevice]
LDR r0, [r0, #HALDevice_DMAController]
LDR r2, [r9, #dmaq_DMADevice] ; API 1.x requires r2 to be channel device ptr
LDR r0, [r2, #HALDevice_DMAController]
LDR r1, [r8, #lcb_ChannelNo]
CallHAL DMACDeallocate
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment