1 /*-------------------------------------------------------------
3 arqueue.c -- ARAM task request queue implementation
6 Michael Wiedenbauer (shagkur)
7 Dave Murphy (WinterMute)
9 This software is provided 'as-is', without any express or implied
10 warranty. In no event will the authors be held liable for any
11 damages arising from the use of this software.
13 Permission is granted to anyone to use this software for any
14 purpose, including commercial applications, and to alter it and
15 redistribute it freely, subject to the following restrictions:
17 1. The origin of this software must not be misrepresented; you
18 must not claim that you wrote the original software. If you use
19 this software in a product, an acknowledgment in the product
20 documentation would be appreciated but is not required.
22 2. Altered source versions must be plainly marked as such, and
23 must not be misrepresented as being the original software.
25 3. This notice may not be removed or altered from any source
28 -------------------------------------------------------------*/
36 #include "processor.h"
41 static u32 __ARQChunkSize
;
42 static u32 __ARQInitFlag
= 0;
43 static lwpq_t __ARQSyncQueue
;
45 static lwp_queue __ARQReqQueueLo
;
46 static lwp_queue __ARQReqQueueHi
;
47 static ARQRequest
*__ARQReqPendingLo
;
48 static ARQRequest
*__ARQReqPendingHi
;
49 static ARQCallback __ARQCallbackLo
= NULL
;
50 static ARQCallback __ARQCallbackHi
= NULL
;
52 static __inline__
void __ARQPopTaskQueueHi()
56 req
= (ARQRequest
*)__lwp_queue_getI(&__ARQReqQueueHi
);
59 req
->state
= ARQ_TASK_RUNNING
;
61 printf("__ARQPopTaskQueueHi(%02x,%08x,%08x,%d)\n",req
->dir
,req
->aram_addr
,req
->mram_addr
,req
->len
);
63 AR_StartDMA(req
->dir
,req
->mram_addr
,req
->aram_addr
,req
->len
);
64 __ARQCallbackHi
= req
->callback
;
65 __ARQReqPendingHi
= req
;
68 static void __ARQCallbackDummy(ARQRequest
*req
)
72 static void __ARQCallbackSync(ARQRequest
*req
)
74 LWP_ThreadBroadcast(__ARQSyncQueue
);
77 static void __ARQServiceQueueLo()
81 if(!__ARQReqPendingLo
) {
82 req
= (ARQRequest
*)__lwp_queue_getI(&__ARQReqQueueLo
);
83 __ARQReqPendingLo
= req
;
86 req
= __ARQReqPendingLo
;
88 req
->state
= ARQ_TASK_RUNNING
;
90 printf("__ARQServiceQueueLo(%02x,%08x,%08x,%d,%d)\n",req
->dir
,req
->aram_addr
,req
->mram_addr
,req
->len
,__ARQChunkSize
);
92 if(req
->len
<=__ARQChunkSize
) {
93 AR_StartDMA(req
->dir
,req
->mram_addr
,req
->aram_addr
,req
->len
);
94 __ARQCallbackLo
= __ARQReqPendingLo
->callback
;
96 AR_StartDMA(req
->dir
,req
->mram_addr
,req
->aram_addr
,__ARQChunkSize
);
97 __ARQReqPendingLo
->len
-= __ARQChunkSize
;
98 __ARQReqPendingLo
->aram_addr
+= __ARQChunkSize
;
99 __ARQReqPendingLo
->mram_addr
+= __ARQChunkSize
;
104 static void __ARInterruptServiceRoutine()
106 if(__ARQCallbackHi
) {
107 __ARQReqPendingHi
->state
= ARQ_TASK_FINISHED
;
108 __ARQCallbackHi(__ARQReqPendingHi
);
109 __ARQReqPendingHi
= NULL
;
110 __ARQCallbackHi
= NULL
;
111 } else if(__ARQCallbackLo
) {
112 __ARQReqPendingLo
->state
= ARQ_TASK_FINISHED
;
113 __ARQCallbackLo(__ARQReqPendingLo
);
114 __ARQReqPendingLo
= NULL
;
115 __ARQCallbackLo
= NULL
;
117 __ARQPopTaskQueueHi();
118 if(!__ARQReqPendingHi
) __ARQServiceQueueLo();
125 printf("ARQ_Init(%02x)\n",__ARQInitFlag
);
127 if(__ARQInitFlag
) return;
129 _CPU_ISR_Disable(level
);
131 __ARQReqPendingLo
= NULL
;
132 __ARQReqPendingHi
= NULL
;
133 __ARQCallbackLo
= NULL
;
134 __ARQCallbackHi
= NULL
;
136 __ARQChunkSize
= ARQ_DEF_CHUNK_SIZE
;
138 LWP_InitQueue(&__ARQSyncQueue
);
140 __lwp_queue_init_empty(&__ARQReqQueueLo
);
141 __lwp_queue_init_empty(&__ARQReqQueueHi
);
143 AR_RegisterCallback(__ARInterruptServiceRoutine
);
146 _CPU_ISR_Restore(level
);
152 _CPU_ISR_Disable(level
);
154 _CPU_ISR_Restore(level
);
157 void ARQ_SetChunkSize(u32 size
)
160 _CPU_ISR_Disable(level
);
161 __ARQChunkSize
= (size
+31)&~31;
162 _CPU_ISR_Restore(level
);
165 u32
ARQ_GetChunkSize()
167 return __ARQChunkSize
;
170 void ARQ_FlushQueue()
174 _CPU_ISR_Disable(level
);
176 __lwp_queue_init_empty(&__ARQReqQueueLo
);
177 __lwp_queue_init_empty(&__ARQReqQueueHi
);
178 if(!__ARQCallbackLo
) __ARQReqPendingLo
= NULL
;
180 _CPU_ISR_Restore(level
);
183 void ARQ_PostRequestAsync(ARQRequest
*req
,u32 owner
,u32 dir
,u32 prio
,u32 aram_addr
,u32 mram_addr
,u32 len
,ARQCallback cb
)
188 req
->state
= ARQ_TASK_READY
;
191 req
->aram_addr
= aram_addr
;
192 req
->mram_addr
= mram_addr
;
195 req
->callback
= (cb
==NULL
) ? __ARQCallbackDummy
: cb
;
197 _CPU_ISR_Disable(level
);
199 if(prio
==ARQ_PRIO_LO
) __lwp_queue_appendI(&__ARQReqQueueLo
,&req
->node
);
200 else __lwp_queue_appendI(&__ARQReqQueueHi
,&req
->node
);
202 if(!__ARQReqPendingLo
&& !__ARQReqPendingHi
) {
203 p
= (ARQRequest
*)__lwp_queue_getI(&__ARQReqQueueHi
);
205 p
->state
= ARQ_TASK_RUNNING
;
207 printf("ARQ_PostRequest(%02x,%08x,%08x,%d)\n",p
->dir
,p
->aram_addr
,p
->mram_addr
,p
->len
);
209 AR_StartDMA(p
->dir
,p
->mram_addr
,p
->aram_addr
,p
->len
);
210 __ARQCallbackHi
= p
->callback
;
211 __ARQReqPendingHi
= p
;
213 if(!__ARQReqPendingHi
) __ARQServiceQueueLo();
215 _CPU_ISR_Restore(level
);
218 void ARQ_PostRequest(ARQRequest
*req
,u32 owner
,u32 dir
,u32 prio
,u32 aram_addr
,u32 mram_addr
,u32 len
)
222 ARQ_PostRequestAsync(req
,owner
,dir
,prio
,aram_addr
,mram_addr
,len
,__ARQCallbackSync
);
224 _CPU_ISR_Disable(level
);
225 while(req
->state
!=ARQ_TASK_FINISHED
) {
226 LWP_ThreadSleep(__ARQSyncQueue
);
228 _CPU_ISR_Restore(level
);
231 void ARQ_RemoveRequest(ARQRequest
*req
)
235 _CPU_ISR_Disable(level
);
236 __lwp_queue_extractI(&req
->node
);
237 if(__ARQReqPendingLo
&& __ARQReqPendingLo
==req
&& __ARQCallbackLo
==NULL
) __ARQReqPendingLo
= NULL
;
238 _CPU_ISR_Restore(level
);
241 u32
ARQ_RemoveOwnerRequest(u32 owner
)
246 _CPU_ISR_Disable(level
);
249 req
= (ARQRequest
*)__ARQReqQueueHi
.first
;
250 while(req
!=(ARQRequest
*)__lwp_queue_tail(&__ARQReqQueueHi
)) {
251 if(req
->owner
==owner
) {
252 __lwp_queue_extractI(&req
->node
);
255 req
= (ARQRequest
*)req
->node
.next
;
258 req
= (ARQRequest
*)__ARQReqQueueLo
.first
;
259 while(req
!=(ARQRequest
*)__lwp_queue_tail(&__ARQReqQueueLo
)) {
260 if(req
->owner
==owner
) {
261 __lwp_queue_extractI(&req
->node
);
264 req
= (ARQRequest
*)req
->node
.next
;
266 if(__ARQReqPendingLo
&& __ARQReqPendingLo
==req
&& __ARQCallbackLo
==NULL
) __ARQReqPendingLo
= NULL
;
267 _CPU_ISR_Restore(level
);