summaryrefslogtreecommitdiff
path: root/cpu/amd/geode_lx/gplvsa_ii/sysmgr/message.asm
blob: 10fe5710fa2b1c05c362c0b2c80435adb4506213 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
; 
; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
; 
; This library is free software; you can redistribute it and/or modify
; it under the terms of the GNU Lesser General Public License as
; published by the Free Software Foundation; either version 2.1 of the
; License, or (at your option) any later version.
; 
; This code is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
; Lesser General Public License for more details.
; 
; You should have received a copy of the GNU Lesser General
; Public License along with this library; if not, write to the
; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
; Boston, MA 02111-1307 USA 
; 
;*   Function:                                                         *
;*     Implements message handling routines 

include SYSMGR.INC
include VSA2.INC



.model tiny,c
.586p
.CODE

externdef SysMgr_VSM:            dword
externdef MsgPacket:             dword
externdef VSM_ListHead:          dword
externdef Current_VSM:           dword

externdef Events:                EVENT_ENTRY
externdef Sys_Exit:              proc
externdef pascal Schedule_VSM:   proc



;***********************************************************************
; This routine is called from the System Manager to enter a message
; packet into a VSM's message queue.
;
; Input:
;   To_VSM   = Flat ptr to VSM to which message is to be sent
;   MsgCode  = Priority::Message
;   From_VSM = value to be put in Async_VSM field
;   MsgPacket contains the message parameters
;***********************************************************************
Send_Message proc pascal uses di si \
	From_VSM:   dword, \
	To_VSM:     dword, \
	MsgCode:    dword

	mov     edi, [To_VSM]
	cmp     edi, [SysMgr_VSM]	; Don't send messages to SysMgr
	je      short Exit

	mov     eax, [MsgCode]
	lea     si, [MsgPacket]
	mov     ebx, [From_VSM]
	call    Insert_Msg
Exit:	ret

Send_Message endp








;***********************************************************************
; This routine enters a message packet into a VSM's message queue.
;
; Input:
;   EAX = Priority::Message
;   EBX = From_VSM
;   EDI = To_VSM
;    SI = Ptr to message packet
;***********************************************************************
Insert_Msg proc 

	cld

	push    ebx			; Save From_VSM

	; Get ptr to the head of the message queue
	movzx   ebx, fs:(VSM_Header PTR [edi]).SysStuff.Qhead

	; Compute ptr to the next available message queue entry
	lea     dx, [bx+sizeof(Message)]
	cmp     dx, fs:(VSM_Header PTR [edi]).SysStuff.EndMsgQ
	jb      short Check_Q_Overflow
	mov     dx, OFFSET VSM_Header.SysStuff.MsgQueue
Check_Q_Overflow:

	; Is Qhead == Qtail ?
	cmp     dx, fs:(VSM_Header PTR [edi]).SysStuff.Qtail
	jne     short UpdateQueueHead

	; Yes, then message queue has overflowed	
	mov     [si+8], eax		; Store previous message into Param2
	mov     ax, MSG_QUEUE_OVERFLOW	; Replace previous message
	mov     dx, bx			; Qhead = old Qhead
UpdateQueueHead:
	mov     fs:(VSM_Header PTR [edi]).SysStuff.Qhead, dx

	pop     edx			; From_VSM
	push    edi			; Parameter to Schedule_VSM() below

	; Store the message into the VSM's message queue.
	; NOTE: This code is dependent on "#typedef Message"
	add     edi, ebx
	stosd   [edi]			; Priority::Message

	mov     eax, edx		; From_VSM
	stosd   [edi]

REPEAT MAX_MSG_PARAM
	lodsd				; Copy parameters to message queue
	stosd   [edi]
ENDM
	
	
	
	; Sort messages by Priority
if SUPPORT_PRIORITY

	pop     ebx			; To_VSM
	push    ebx
	
	push    fs:(VSM_Header PTR [ebx]).SysStuff.Qhead
BubbleSort:	

	; Get ptr to latest queue entry
	movzx   esi, fs:(VSM_Header PTR [ebx]).SysStuff.Qhead
	sub     esi, sizeof(Message)
	cmp     si, OFFSET VSM_Header.SysStuff.MsgQueue
	jae     short @f
	mov     si, fs:(VSM_Header PTR [ebx]).SysStuff.EndMsgQ
	sub     si, sizeof(Message)
@@:
	cmp	si, fs:(VSM_Header PTR [ebx]).SysStuff.Qtail
	je	Bail

	; Get ptr to previous queue entry
	lea     edi, [esi-sizeof(Message)]
	cmp     di, OFFSET VSM_Header.SysStuff.MsgQueue
	jae     short @f
	mov     di, fs:(VSM_Header PTR [ebx]).SysStuff.EndMsgQ
	sub     di, sizeof(Message)
@@:
	
	mov     fs:(VSM_Header PTR [ebx]).SysStuff.Qhead, di

	; Add VSM base to ptrs
	add     edi, ebx
	add     esi, ebx
	
	; Compare their priorities	
	mov     ax, fs:(Message PTR [esi]).Priority
	cmp     ax, fs:(Message PTR [edi]).Priority
	jbe     short Bail
	
	
	
	; Swap the entries in the message queue
	mov     cx, sizeof(Message)/4	; Assumes entry is multiple of dword
Interchange:
	mov     eax, fs:[edi]
	xchg    fs:[esi], eax
	stosd	[edi]
	add     esi, 4
	loop    Interchange

	jmp	BubbleSort


Bail:
	pop     fs:(VSM_Header PTR [ebx]).SysStuff.Qhead

endif
	
       
	; Schedule the VSM to execute
	pop	eax
	cmp	eax, [SysMgr_VSM]
	je	short Exit
	push	eax
	call    Schedule_VSM
Exit:
	ret
	

Insert_Msg endp










;************************************************************************
;
; Sends a message to each VSM of type VSM_Type (or all if VSM_ANY).
; Called from HANDLERS.C
;
;************************************************************************
Broadcast_Message proc  pascal uses si di \
	MsgCode:     word,	\
	VSM_Type:    word,      \
	From_VSM:    dword

	mov     edi, [VSM_ListHead]	; Get ptr to list of VSMs
VSM_Loop:
	or      edi, edi		; End of VSM list ?
	jz      Exit_Broadcast

	mov     dx,  [VSM_Type]
	mov     ah, fs:(VSM_Header PTR [edi]).VSM_Type

	cmp     dl, VSM_ANY		; Schedule all VSMs ? 
	je      Schedule_It

	test    dh, (VSM_ALL_EXCEPT SHR 8)
	jz      CheckType

	cmp     dl, ah			; Skip the one that matches
	je      Skip_VSM
	jmp     Schedule_It

CheckType:
	cmp     dl, ah			; Is it the correct VSM ?
	jne     Skip_VSM

Schedule_It:

	cmp     edi, [From_VSM]		; Is it the requesting VSM ?
	je      Skip_VSM		; Yes, don't send to sender

	push    edi

	movzx   eax, [MsgCode]		; Send the message
	xor     ebx, ebx
	lea     si, [MsgPacket]

;   EAX = Priority::Message
;   EBX = 00000000h (a broadcast is not a synchronous event)
;    SI = Ptr to message packet
;   EDI = Ptr to VSM header where message is to be sent
	call    Insert_Msg
	pop     edi


Skip_VSM:
	mov     edi, fs:(VSM_Header PTR [edi]).SysStuff.Flink
	jmp     VSM_Loop

Exit_Broadcast:
	ret

Broadcast_Message endp



;************************************************************************
; Broadcasts a message to one or more VSMs.
;
; Input:
;   EBX = message code (16 MSBs)
;    BH = Flags
;    BL = VSM_Type
;   ECX = Param1
;   ESI = Param2
;   EDI = Param3
;************************************************************************
Sys_Broadcast proc

	mov	dx, bx			; Put VSM_Type::Flags into DX
	shr	ebx, 16			; Put message into BX

	mov     eax, esi
	lea     si, [MsgPacket]
	mov	[si+0], ecx
	mov	[si+4], eax
	mov	[si+8], edi

	; Re-schedule the broadcasting VSM
	; RunFlag will be changed from RUN_FLAG_ACTIVE to RUN_FLAG_READY
	mov     edi, [Current_VSM]
	push    edi
	call    Schedule_VSM
	; If RunFlag == RUN_FLAG_READY, Insert_Msg() won't schedule it again
	mov	fs:(VSM_Header PTR [edi]).SysStuff.RunFlag, RUN_FLAG_BLOCKED

	; Push parameters for call to Broadcast_Message()
	push    bx			; Message code
	push    dx			; VSM type
	push    edi			; From_VSM
	
	; Normally, the message is sent to the broadcasting VSM 
	; after all VSMs have handled the broadcasted message.
	; There are two exceptions to this rule:
	; 1) VSM_NOT_SELF   | <VSM type>
	; 2) VSM_ALL_EXCEPT | <self>
	test    dh, (VSM_NOT_SELF SHR 8)
	jnz     short Broadcast

	test    dh, (VSM_ALL_EXCEPT SHR 8)
	jz      short SendToSelf
	cmp     dl, fs:(VSM_Header PTR [edi]).VSM_Type
	je      short Broadcast

SendToSelf:
	; Put callback address onto the scheduler stack
	mov	eax, OFFSET BroadcastCallback
	push	eax
	call    Schedule_VSM

	mov	ax, BROADCAST_PRIORITY	; EAX = Priority::Message 
	shl	eax, 16
	mov	ax, bx

	mov     edi, [SysMgr_VSM]	; EDI = To_VSM
	mov     ebx, [Current_VSM]	; EBX = From_VSM
	call    Insert_Msg

Broadcast:
	call    Broadcast_Message

	jmp     Sys_Exit		; Exit w/o scheduling current VSM

Sys_Broadcast endp


;************************************************************************
; Control comes here when all VSMs have processed the broadcasted message.
; Copies the broadcasted message from SysMgr's message queue to the
; broadcasting VSM's message queue.
;************************************************************************
BroadcastCallback proc
	ASSUME  DI: PTR VSM_Header
	ASSUME  BX: PTR Message

	; Point BX to parameters in SysMgr's message queue head
	xor     di, di
	mov     bx, [di].SysStuff.Qhead
	sub     bx, sizeof(Message)
	cmp     bx, OFFSET VSM_Header.SysStuff.MsgQueue
	jb      short BadMsgStack
	mov     [di].SysStuff.Qhead, bx
	
	mov     eax, dword ptr [bx].Msg	; Get Priority::Message
	mov	edi, [bx].From_VSM	; To_VSM (the VSM it was originally from)

	lea	si, [bx].Param
	xor     ebx, ebx		; From_VSM (asynchronous)
	call    Insert_Msg
BadMsgStack:	
	ret
	
	ASSUME  BX: NOTHING
	ASSUME  DI: NOTHING

BroadcastCallback endp



;***********************************************************************
; Passes an event to the next VSM registered for this event
; NOTE: This system call is now obsolete.
;***********************************************************************
Sys_PassEvent proc 

	jmp     Sys_Exit		; Exit to VSM dispatcher
	
Sys_PassEvent endp





	END