* ========== Copyright Header Begin ==========================================
* Hypervisor Software File: svcinternal.s
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* - Do no alter or remove copyright notices
* - Redistribution and use of this software in source and binary forms, with
* or without modification, are permitted provided that the following
* - Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistribution in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of Sun Microsystems, Inc. or the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* You acknowledge that this software is not designed, licensed or
* intended for use in the design, construction, operation or maintenance of
* ========== Copyright Header End ============================================
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
.ident "@(#)svcinternal.s 1.15 07/06/07 SMI"
#include <sys/asm_linkage.h>
#include <sparcv9/misc.h>
#include <devices/pc16550.h>
#define CHECKSUM_PKT(addr, len, retval, sum, tmp0) \
ldub [addr + len], sum ;\
* This is the internal access to the svc driver.
* svc_internal_send - Use this to send a packet from inside
* You had better be sure *you* are not holding the SVC_CTRL_LOCK..
* %g1 = is the handle given to you by svc_register
LOCK(r_svc, SVC_CTRL_LOCK, r_tmp0, r_tmp1)
ld [r_svc + SVC_CTRL_CONFIG], r_tmp0 ! get status
bnz,pt %xcc, 1f ! cant TX on this SVC
ld [r_svc + SVC_CTRL_STATE], r_tmp0
mov -1, %g2 ! return FAILED.
2: UNLOCK(r_svc, SVC_CTRL_LOCK)
1: btst SVC_FLAGS_TP, r_tmp0 ! TX pending?
bnz,a,pn %xcc, .svc_internal_send_fail
ld [r_svc + SVC_CTRL_MTU], r_tmp0 ! size
dec SVC_PKT_SIZE, r_tmp0 ! mtu -= hdr
bgu,a,pn %xcc, .svc_internal_send_fail ! failed - too big!!
ld [r_svc + SVC_CTRL_STATE], r_tmp0 ! get state flags
or r_tmp0, SVC_FLAGS_TP, r_tmp0
st r_tmp0, [r_svc SVC_CTRL_STATE]
UNLOCK(r_svc, SVC_CTRL_LOCK) ! set state
ldx [r_svc + SVC_CTRL_SEND + SVC_LINK_PA], r_svcbuf
ld [r_svc + SVC_CTRL_XID], r_tmp0
st r_tmp0, [r_svcbuf + SVC_PKT_XID] ! xpid
sth %g0, [r_svcbuf + SVC_PKT_SUM] ! checksum=0
ld [r_svc + SVC_CTRL_SID], r_tmp0
sth r_tmp0, [r_svcbuf + SVC_PKT_SID] ! svcid
add r_len, SVC_PKT_SIZE, r_tmp0
stx r_tmp0, [r_svc + SVC_CTRL_SEND + SVC_LINK_SIZE] ! total size
add r_svcbuf, SVC_PKT_SIZE, r_tmp0 ! dest
SMALL_COPY_MACRO(r_buf, r_len, r_tmp0, r_tmp1)
ldx [r_svc + SVC_CTRL_SEND + SVC_LINK_SIZE], r_len
CHECKSUM_PKT(r_svcbuf, r_len, r_buf, r_tmp0, r_tmp1) !
ldx [r_svc + SVC_CTRL_SEND + SVC_LINK_PA], r_svcbuf
sth r_buf, [r_svcbuf + SVC_PKT_SUM] ! checksum
1: ROOT_STRUCT(r_root) ! date root
ldx [r_root + CONFIG_SVCS], r_root ! svc root
brz,a,pn r_root, .svc_internal_send_return ! failed!
LOCK(r_root, HV_SVC_DATA_LOCK, r_tmp0, r_tmp1)
ldx [r_root + HV_SVC_DATA_SENDT], r_tmp0 ! Tail
stx %g0, [r_svc + SVC_CTRL_SEND + SVC_LINK_NEXT] ! svc->next = 0
stx r_svc, [r_tmp0 + SVC_CTRL_SEND + SVC_LINK_NEXT]
1: ldx [r_root + HV_SVC_DATA_SENDH], r_tmp0 ! Head
stx r_svc, [r_root + HV_SVC_DATA_SENDT] ! set Tail
stx r_svc, [r_root + HV_SVC_DATA_SENDH]
/* If fpga is busy, don't send */
lduw [r_root + HV_SVC_DATA_SENDBUSY], r_tmp3
/* Head == NULL.. copy to SRAM, hit TX, enable SSI interrupts.. */
SEND_SVC_PACKET(r_root, r_svc, r_tmp0, r_tmp1, r_tmp2, r_tmp3)
UNLOCK(r_root, HV_SVC_DATA_LOCK)
.svc_internal_send_return:
SET_SIZE(svc_internal_send)
* svc_internal_send_nolock - Use this to send a packet from inside
* the hypervisor. Caller is responsible for managing the sevices locks
* %g1 = is the handle given to you by svc_register
ENTRY(svc_internal_send_nolock)
ld [r_svc + SVC_CTRL_MTU], r_tmp0 ! size
dec SVC_PKT_SIZE, r_tmp0 ! mtu -= hdr
bgu,a,pn %xcc, .svc_internal_send_fail_nolock ! failed - too big!!
ld [r_svc + SVC_CTRL_STATE], r_tmp0 ! get state flags
or r_tmp0, SVC_FLAGS_TP, r_tmp0
st r_tmp0, [r_svc SVC_CTRL_STATE]
ldx [r_svc + SVC_CTRL_SEND + SVC_LINK_PA], r_svcbuf
ld [r_svc + SVC_CTRL_XID], r_tmp0
st r_tmp0, [r_svcbuf + SVC_PKT_XID] ! xpid
sth %g0, [r_svcbuf + SVC_PKT_SUM] ! checksum=0
ld [r_svc + SVC_CTRL_SID], r_tmp0
sth r_tmp0, [r_svcbuf + SVC_PKT_SID] ! svcid
add r_len, SVC_PKT_SIZE, r_tmp0
stx r_tmp0, [r_svc + SVC_CTRL_SEND + SVC_LINK_SIZE] ! total size
add r_svcbuf, SVC_PKT_SIZE, r_tmp0 ! dest
SMALL_COPY_MACRO(r_buf, r_len, r_tmp0, r_tmp1)
ldx [r_svc + SVC_CTRL_SEND + SVC_LINK_SIZE], r_len
CHECKSUM_PKT(r_svcbuf, r_len, r_buf, r_tmp0, r_tmp1) !
ldx [r_svc + SVC_CTRL_SEND + SVC_LINK_PA], r_svcbuf
sth r_buf, [r_svcbuf + SVC_PKT_SUM] ! checksum
1: ROOT_STRUCT(r_root) ! data root
ldx [r_root + CONFIG_SVCS], r_root ! svc root
brz,a,pn r_root, .svc_internal_send_return ! failed!
ldx [r_root + HV_SVC_DATA_SENDT], r_tmp0 ! Tail
stx %g0, [r_svc + SVC_CTRL_SEND + SVC_LINK_NEXT] ! svc->next = 0
stx r_svc, [r_tmp0 + SVC_CTRL_SEND + SVC_LINK_NEXT]
1: ldx [r_root + HV_SVC_DATA_SENDH], r_tmp0 ! Head
stx r_svc, [r_root + HV_SVC_DATA_SENDT] ! set Tail
/* Head == NULL.. copy to SRAM, hit TX, enable SSI interrupts.. */
SEND_SVC_PACKET(r_root, r_svc, r_tmp0, r_tmp1, r_tmp2, r_tmp3)
stx r_svc, [r_root + HV_SVC_DATA_SENDH]
.svc_internal_send_return_nolock:
.svc_internal_send_fail_nolock:
SET_SIZE(svc_internal_send_nolock)
#if 0 /* XXX unused? need to wire up for virtual interrupts */
* svc_internal_getstate - check state of a channel
* %g1 is the handle given to you by svc_register
* %g1 is the service state value (SVC_CTRL_STATE)
ENTRY(svc_internal_getstate)
ld [%g1 + SVC_CTRL_STATE], %g1
SET_SIZE(svc_internal_getstate)