/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This file contains the low-level DMV interrupt
* handler for IDN cross-domain interrupts.
*/
#if defined(lint)
#endif /* lint */
#include <sys/asm_linkage.h>
#include <sys/privregs.h>
#include <sys/machthread.h>
#if !defined(lint)
#include "idn_offsets.h"
#endif /* !lint */
#define IDN_MONDO
/*
* The IDN_DMV_CPU_SHIFT is based on the sizeof (idn_dmv_cpu_t)
* which must be a power of 2 to optimize calculating our
* entry into idn_dmv_cpu[].
*/
/*
*--------------------------------------------------------
*/
#if defined(lint)
/*
* Would be nice to use init_mondo, but unforunately
* it assumes the first arg is 32-bits.
*/
/*ARGSUSED*/
void
{}
#else /* lint */
.asciz "ASI_INTR_DISPATCH_STATUS error: busy"
.align 4
#ifdef DEBUG
!
!
#endif /* DEBUG */
1:
#endif /* lint */
/*
*--------------------------------------------------------
*/
#if defined(lint)
/*
* Unfortunately, send_mondo is rather picky about getting
* a result from the cpu it sends an interrupt to. If it
* doesn't get a result within a specific timeframe it
* will panic! For IDN that's not cool since a cpu hungup
* in one could ultimately result in the demise of a cpu
* in another domain. Instead of getting our panties in
* a bind, we simply bail out.
*/
/*ARGSUSED*/
int
idnxf_send_mondo(int upaid)
{ return (0); }
#else /* lint */
.seg ".data"
.word 0
.seg ".text"
!
! NOTE:
!
! construct the interrupt dispatch command register in %g1
! also, get the dispatch out as SOON as possible
! (initial analysis puts the minimum dispatch time at around
! 30-60 cycles. hence, we try to get the dispatch out quickly
! and then start the rapid check loop).
!
rd %tick, %o4 ! baseline tick
sll %o0, IDCR_PID_SHIFT, %g1 ! IDCR<18:14> = upa port id
or %g1, IDCR_OFFSET, %g1 ! IDCR<13:0> = 0x70
stxa %g0, [%g1]ASI_INTR_DISPATCH ! interrupt vector dispatch
#if defined(SF_ERRATA_54)
membar #Sync ! store must occur before load
mov 0x20, %g3 ! UDBH Control Register Read
ldxa [%g3]ASI_SDB_INTR_R, %g0
#endif
membar #Sync
clr %o2 ! clear NACK counter
clr %o3 ! clear BUSY counter
!
! how long, in ticks, are we willing to wait completely
!
sethi %hi(xc_tick_limit), %g2
ldx [%g2 + %lo(xc_tick_limit)], %g2
add %g2, %o4, %o5 ! compute the limit value
!
! check the dispatch status
!
.check_dispatch:
ldxa [%g0]ASI_INTR_DISPATCH_STATUS, %o1
brz,pn %o1, .dispatch_complete
rd %tick, %g5
!
!
#ifdef IDN_MONDO
!
! to panic just because we can't send_mondo.
!
#else /* IDN_MONDO */
!
!
#endif /* IDN_MONDO */
!
!
.delay:
#if defined(SF_ERRATA_54)
#endif
#ifndef IDN_MONDO
#ifdef SEND_MONDO_STATS
!
!
!
!
!
#endif /* SEND_MONDO_STATS */
#endif /* !IDN_MONDO */
#ifdef IDN_MONDO
#else /* IDN_MONDO */
#endif /* IDN_MONDO */
#endif /* lint */
/*
*--------------------------------------------------------
*/
#if defined(lint)
/*ARGSUSED*/
void
idn_dmv_handler(void *arg)
{}
#else /* lint */
!
! g1 = idn_dmv_data
!
!
!
!
!
!
!
!
!
!
!
1:
!
!
!
!
!
! doesn't know how to survive with intr_vec structs!
!
ldstub [%g6 + %g7], %g7 ! idn_dmv_active = 0xff
brz,a,pt %g7, 2f
ldx [%g1 + IDN_SOFT_INUM], %g7 ! g7 = idn_soft_inum
mov -1, %g7
2:
!
! Setup to cause an IDN soft interrupt to occur,
! (if necessary).
!
set dmv_finish_intr, %g3
jmp %g3
mov %g7, %g1
SET_SIZE(idn_dmv_handler)
#endif /* lint */