summaryrefslogtreecommitdiff
path: root/cpu/amd/geode_lx/gplvsa_ii/sysmgr/message.asm
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/amd/geode_lx/gplvsa_ii/sysmgr/message.asm')
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/message.asm393
1 files changed, 393 insertions, 0 deletions
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/message.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/message.asm
new file mode 100755
index 0000000..10fe571
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/message.asm
@@ -0,0 +1,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
+
+
+