xref: /titanic_52/usr/src/uts/sun4u/starfire/ml/idn_asm.s (revision b0fc0e77220f1fa4c933fd58a4e1dedcd650b0f1)
17c478bd9Sstevel@tonic-gate/*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*b0fc0e77Sgovinda * Common Development and Distribution License (the "License").
6*b0fc0e77Sgovinda * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate/*
22*b0fc0e77Sgovinda * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate/*
297c478bd9Sstevel@tonic-gate * This file contains the low-level DMV interrupt
307c478bd9Sstevel@tonic-gate * handler for IDN cross-domain interrupts.
317c478bd9Sstevel@tonic-gate */
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate#if defined(lint)
347c478bd9Sstevel@tonic-gate#include <sys/types.h>
357c478bd9Sstevel@tonic-gate#endif /* lint */
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
387c478bd9Sstevel@tonic-gate#include <sys/machasi.h>
397c478bd9Sstevel@tonic-gate#include <sys/privregs.h>
407c478bd9Sstevel@tonic-gate#include <sys/intreg.h>
417c478bd9Sstevel@tonic-gate#include <sys/machthread.h>
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate#include <sys/idn.h>
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate#if !defined(lint)
467c478bd9Sstevel@tonic-gate#include "idn_offsets.h"
477c478bd9Sstevel@tonic-gate#endif /* !lint */
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate#define	IDN_MONDO
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate/*
527c478bd9Sstevel@tonic-gate * The IDN_DMV_CPU_SHIFT is based on the sizeof (idn_dmv_cpu_t)
537c478bd9Sstevel@tonic-gate * which must be a power of 2 to optimize calculating our
547c478bd9Sstevel@tonic-gate * entry into idn_dmv_cpu[].
557c478bd9Sstevel@tonic-gate */
567c478bd9Sstevel@tonic-gate#define	IDN_DMV_CPU_SHIFT	4
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate/*
597c478bd9Sstevel@tonic-gate *--------------------------------------------------------
607c478bd9Sstevel@tonic-gate */
617c478bd9Sstevel@tonic-gate#if defined(lint)
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate/*
647c478bd9Sstevel@tonic-gate * Would be nice to use init_mondo, but unforunately
657c478bd9Sstevel@tonic-gate * it assumes the first arg is 32-bits.
667c478bd9Sstevel@tonic-gate */
677c478bd9Sstevel@tonic-gate/*ARGSUSED*/
687c478bd9Sstevel@tonic-gatevoid
697c478bd9Sstevel@tonic-gateidnxf_init_mondo(uint64_t arg0, uint64_t arg1, uint64_t arg2)
707c478bd9Sstevel@tonic-gate{}
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate#else /* lint */
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate	.global _idn_dispatch_status_busy
757c478bd9Sstevel@tonic-gate_idn_dispatch_status_busy:
767c478bd9Sstevel@tonic-gate	.asciz	"ASI_INTR_DISPATCH_STATUS error: busy"
777c478bd9Sstevel@tonic-gate	.align	4
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate	ENTRY_NP(idnxf_init_mondo)
807c478bd9Sstevel@tonic-gate#ifdef DEBUG
817c478bd9Sstevel@tonic-gate	!
827c478bd9Sstevel@tonic-gate	! IDSR should not be busy at the moment - borrowed from init_mondo
837c478bd9Sstevel@tonic-gate	!
847c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_INTR_DISPATCH_STATUS, %g1
857c478bd9Sstevel@tonic-gate	btst	IDSR_BUSY, %g1
867c478bd9Sstevel@tonic-gate	bz,pt	%xcc, 1f
877c478bd9Sstevel@tonic-gate	mov	ASI_INTR_DISPATCH, %asi
887c478bd9Sstevel@tonic-gate	sethi	%hi(_idn_dispatch_status_busy), %o0
897c478bd9Sstevel@tonic-gate	call	panic
907c478bd9Sstevel@tonic-gate	or	%o0, %lo(_idn_dispatch_status_busy), %o0
917c478bd9Sstevel@tonic-gate#endif /* DEBUG */
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate	mov	ASI_INTR_DISPATCH, %asi
947c478bd9Sstevel@tonic-gate1:
957c478bd9Sstevel@tonic-gate	stxa	%o0, [IDDR_0]%asi	! dmv_word0
967c478bd9Sstevel@tonic-gate	stxa	%o1, [IDDR_1]%asi	! dmv_word1
977c478bd9Sstevel@tonic-gate	stxa	%o2, [IDDR_2]%asi	! dmv_word2
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate	retl
1007c478bd9Sstevel@tonic-gate	membar	#Sync
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate	SET_SIZE(idnxf_init_mondo)
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate#endif /* lint */
1057c478bd9Sstevel@tonic-gate/*
1067c478bd9Sstevel@tonic-gate *--------------------------------------------------------
1077c478bd9Sstevel@tonic-gate */
1087c478bd9Sstevel@tonic-gate#if defined(lint)
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate/*
1117c478bd9Sstevel@tonic-gate * Unfortunately, send_mondo is rather picky about getting
1127c478bd9Sstevel@tonic-gate * a result from the cpu it sends an interrupt to.  If it
1137c478bd9Sstevel@tonic-gate * doesn't get a result within a specific timeframe it
1147c478bd9Sstevel@tonic-gate * will panic!  For IDN that's not cool since a cpu hungup
1157c478bd9Sstevel@tonic-gate * in one could ultimately result in the demise of a cpu
1167c478bd9Sstevel@tonic-gate * in another domain.  Instead of getting our panties in
1177c478bd9Sstevel@tonic-gate * a bind, we simply bail out.
1187c478bd9Sstevel@tonic-gate */
1197c478bd9Sstevel@tonic-gate/*ARGSUSED*/
1207c478bd9Sstevel@tonic-gateint
1217c478bd9Sstevel@tonic-gateidnxf_send_mondo(int upaid)
1227c478bd9Sstevel@tonic-gate{ return (0); }
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate#else /* lint */
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate	.seg	".data"
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate	.global _idn_send_mondo_failure
1297c478bd9Sstevel@tonic-gate_idn_send_mondo_failure:
1307c478bd9Sstevel@tonic-gate	.word	0
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate	.seg	".text"
1337c478bd9Sstevel@tonic-gate	ENTRY(idnxf_send_mondo)
1347c478bd9Sstevel@tonic-gate	!
1357c478bd9Sstevel@tonic-gate	! NOTE:
1367c478bd9Sstevel@tonic-gate	!	This is stolen from send_mondo.  The changes
1377c478bd9Sstevel@tonic-gate	!	are those ifdef'd with IDN_MONDO
1387c478bd9Sstevel@tonic-gate	!
1397c478bd9Sstevel@tonic-gate	! construct the interrupt dispatch command register in %g1
1407c478bd9Sstevel@tonic-gate	! also, get the dispatch out as SOON as possible
1417c478bd9Sstevel@tonic-gate	! (initial analysis puts the minimum dispatch time at around
1427c478bd9Sstevel@tonic-gate	!  30-60 cycles.  hence, we try to get the dispatch out quickly
1437c478bd9Sstevel@tonic-gate	!  and then start the rapid check loop).
1447c478bd9Sstevel@tonic-gate	!
1457c478bd9Sstevel@tonic-gate	rd	%tick, %o4			! baseline tick
1467c478bd9Sstevel@tonic-gate	sll	%o0, IDCR_PID_SHIFT, %g1	! IDCR<18:14> = upa port id
1477c478bd9Sstevel@tonic-gate	or	%g1, IDCR_OFFSET, %g1		! IDCR<13:0> = 0x70
1487c478bd9Sstevel@tonic-gate	stxa	%g0, [%g1]ASI_INTR_DISPATCH	! interrupt vector dispatch
1497c478bd9Sstevel@tonic-gate#if defined(SF_ERRATA_54)
1507c478bd9Sstevel@tonic-gate	membar	#Sync				! store must occur before load
1517c478bd9Sstevel@tonic-gate	mov	0x20, %g3			! UDBH Control Register Read
1527c478bd9Sstevel@tonic-gate	ldxa	[%g3]ASI_SDB_INTR_R, %g0
1537c478bd9Sstevel@tonic-gate#endif
1547c478bd9Sstevel@tonic-gate	membar	#Sync
1557c478bd9Sstevel@tonic-gate	clr	%o2				! clear NACK counter
1567c478bd9Sstevel@tonic-gate	clr	%o3				! clear BUSY counter
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate	!
1597c478bd9Sstevel@tonic-gate	! how long, in ticks, are we willing to wait completely
1607c478bd9Sstevel@tonic-gate	!
1617c478bd9Sstevel@tonic-gate	sethi	%hi(xc_tick_limit), %g2
1627c478bd9Sstevel@tonic-gate	ldx	[%g2 + %lo(xc_tick_limit)], %g2
1637c478bd9Sstevel@tonic-gate	add	%g2, %o4, %o5			! compute the limit value
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gate	!
1667c478bd9Sstevel@tonic-gate	! check the dispatch status
1677c478bd9Sstevel@tonic-gate	!
1687c478bd9Sstevel@tonic-gate.check_dispatch:
1697c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_INTR_DISPATCH_STATUS, %o1
1707c478bd9Sstevel@tonic-gate	brz,pn	%o1, .dispatch_complete
1717c478bd9Sstevel@tonic-gate	  rd	%tick, %g5
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate	!
1747c478bd9Sstevel@tonic-gate	! see if we've gone beyond the limit
1757c478bd9Sstevel@tonic-gate	! (can tick ever overflow?)
1767c478bd9Sstevel@tonic-gate	!
1777c478bd9Sstevel@tonic-gate.timeout_primed:
1787c478bd9Sstevel@tonic-gate	sub	%o5, %g5, %g2			! limit - tick < 0 if timeout
1797c478bd9Sstevel@tonic-gate	brgez,pt %g2, .check_busy
1807c478bd9Sstevel@tonic-gate	  inc	%o3				! bump the BUSY counter
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate#ifdef IDN_MONDO
1837c478bd9Sstevel@tonic-gate	!
1847c478bd9Sstevel@tonic-gate	! Within the context of IDN we don't want
1857c478bd9Sstevel@tonic-gate	! to panic just because we can't send_mondo.
1867c478bd9Sstevel@tonic-gate	! Clear the dispatch register and increment
1877c478bd9Sstevel@tonic-gate	! our count of failures.
1887c478bd9Sstevel@tonic-gate	!
1897c478bd9Sstevel@tonic-gate	stxa	%g0, [%g1]ASI_INTR_DISPATCH
1907c478bd9Sstevel@tonic-gate	sethi	%hi(_idn_send_mondo_failure), %o0
1917c478bd9Sstevel@tonic-gate	ld	[%o0 + %lo(_idn_send_mondo_failure)], %o1
1927c478bd9Sstevel@tonic-gate	inc	%o1
1937c478bd9Sstevel@tonic-gate	st	%o1, [%o0 + %lo(_idn_send_mondo_failure)]
1947c478bd9Sstevel@tonic-gate	retl
1957c478bd9Sstevel@tonic-gate	  mov	-1, %o0				! return (-1)
1967c478bd9Sstevel@tonic-gate#else /* IDN_MONDO */
1977c478bd9Sstevel@tonic-gate	!
1987c478bd9Sstevel@tonic-gate	! time to die, see if we are already panicing
1997c478bd9Sstevel@tonic-gate	!
2007c478bd9Sstevel@tonic-gate	mov	%o0, %o1			! save target
2017c478bd9Sstevel@tonic-gate	sethi	%hi(_send_mondo_nack), %o0
2027c478bd9Sstevel@tonic-gate	or	%o0, %lo(_send_mondo_nack), %o0
2037c478bd9Sstevel@tonic-gate	sethi	%hi(panicstr), %g2
2047c478bd9Sstevel@tonic-gate	ldn	[%g2 + %lo(panicstr)], %g2
2057c478bd9Sstevel@tonic-gate	brnz	%g2, .dispatch_complete		! skip if already in panic
2067c478bd9Sstevel@tonic-gate	  nop
2077c478bd9Sstevel@tonic-gate	call	panic
2087c478bd9Sstevel@tonic-gate	  nop
2097c478bd9Sstevel@tonic-gate#endif /* IDN_MONDO */
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate.check_busy:
2127c478bd9Sstevel@tonic-gate	btst	IDSR_BUSY, %o1			! was it BUSY?
2137c478bd9Sstevel@tonic-gate	bnz,pt	%xcc, .check_dispatch
2147c478bd9Sstevel@tonic-gate	  nop
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate	!
2177c478bd9Sstevel@tonic-gate	! we weren't busy, we must have been NACK'd
2187c478bd9Sstevel@tonic-gate	! wait a while and send again
2197c478bd9Sstevel@tonic-gate	! (this might need jitter)
2207c478bd9Sstevel@tonic-gate	!
2217c478bd9Sstevel@tonic-gate	sethi	%hi(sys_clock_mhz), %g2
2227c478bd9Sstevel@tonic-gate	lduw	[%g2 + %lo(sys_clock_mhz)], %g2
2237c478bd9Sstevel@tonic-gate	rd	%tick, %g4
2247c478bd9Sstevel@tonic-gate	add	%g2, %g4, %g2
2257c478bd9Sstevel@tonic-gate.delay:
2267c478bd9Sstevel@tonic-gate	cmp	%g2, %g4
2277c478bd9Sstevel@tonic-gate	bgu,pt	%xcc, .delay
2287c478bd9Sstevel@tonic-gate	rd	%tick, %g4
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate	stxa	%g0, [%g1]ASI_INTR_DISPATCH	! interrupt vector dispatch
2317c478bd9Sstevel@tonic-gate#if defined(SF_ERRATA_54)
2327c478bd9Sstevel@tonic-gate	membar	#Sync				! store must occur before load
2337c478bd9Sstevel@tonic-gate	ldxa	[%g3]ASI_SDB_INTR_R, %g0
2347c478bd9Sstevel@tonic-gate#endif
2357c478bd9Sstevel@tonic-gate	membar	#Sync
2367c478bd9Sstevel@tonic-gate	clr	%o3				! reset BUSY counter
2377c478bd9Sstevel@tonic-gate	ba	.check_dispatch
2387c478bd9Sstevel@tonic-gate	  inc	%o2				! bump the NACK counter
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate.dispatch_complete:
2417c478bd9Sstevel@tonic-gate#ifndef IDN_MONDO
2427c478bd9Sstevel@tonic-gate#ifdef SEND_MONDO_STATS
2437c478bd9Sstevel@tonic-gate	!
2447c478bd9Sstevel@tonic-gate	! Increment the appropriate entry in a send_mondo timeout array
2457c478bd9Sstevel@tonic-gate	! x_entry[CPU][MSB]++;
2467c478bd9Sstevel@tonic-gate	sub	%g5, %o4, %g5			! how long did we wait?
2477c478bd9Sstevel@tonic-gate	clr	%o1				! o1 is now bit counter
2487c478bd9Sstevel@tonic-gate1:	orcc	%g5, %g0, %g0			! any bits left?
2497c478bd9Sstevel@tonic-gate	srlx	%g5, 1, %g5			! bits to the right
2507c478bd9Sstevel@tonic-gate	bne,a,pt %xcc, 1b
2517c478bd9Sstevel@tonic-gate	  add	%o1, 4, %o1			! pointer increment
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate	!
2547c478bd9Sstevel@tonic-gate	! now compute the base of the x_early entry for our cpu
2557c478bd9Sstevel@tonic-gate	!
2567c478bd9Sstevel@tonic-gate	CPU_INDEX(%o0, %g5)
2577c478bd9Sstevel@tonic-gate	sll	%o0, 8, %o0			! 64 * 4
2587c478bd9Sstevel@tonic-gate	add	%o0, %o1, %o1			! %o0 = &[CPU][delay]
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate	!
2617c478bd9Sstevel@tonic-gate	! and increment the appropriate value
2627c478bd9Sstevel@tonic-gate	!
2637c478bd9Sstevel@tonic-gate	sethi	%hi(x_early), %o0
2647c478bd9Sstevel@tonic-gate	or	%o0, %lo(x_early), %o0
2657c478bd9Sstevel@tonic-gate	ld	[%o0 + %o1], %g5
2667c478bd9Sstevel@tonic-gate	inc	%g5
2677c478bd9Sstevel@tonic-gate	st	%g5, [%o0 + %o1]
2687c478bd9Sstevel@tonic-gate#endif	/* SEND_MONDO_STATS */
2697c478bd9Sstevel@tonic-gate#endif /* !IDN_MONDO */
2707c478bd9Sstevel@tonic-gate	retl
2717c478bd9Sstevel@tonic-gate#ifdef IDN_MONDO
2727c478bd9Sstevel@tonic-gate	  mov	%g0, %o0			! return (0)
2737c478bd9Sstevel@tonic-gate#else /* IDN_MONDO */
2747c478bd9Sstevel@tonic-gate	  nop
2757c478bd9Sstevel@tonic-gate#endif /* IDN_MONDO */
2767c478bd9Sstevel@tonic-gate	SET_SIZE(idnxf_send_mondo)
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate#endif /* lint */
2797c478bd9Sstevel@tonic-gate/*
2807c478bd9Sstevel@tonic-gate *--------------------------------------------------------
2817c478bd9Sstevel@tonic-gate */
2827c478bd9Sstevel@tonic-gate#if defined(lint)
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate/*ARGSUSED*/
2857c478bd9Sstevel@tonic-gatevoid
2867c478bd9Sstevel@tonic-gateidn_dmv_handler(void *arg)
2877c478bd9Sstevel@tonic-gate{}
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate#else /* lint */
2907c478bd9Sstevel@tonic-gate
2917c478bd9Sstevel@tonic-gate	ENTRY_NP(idn_dmv_handler)
2927c478bd9Sstevel@tonic-gate	!
2937c478bd9Sstevel@tonic-gate	! On entry:
2947c478bd9Sstevel@tonic-gate	!	g1 = idn_dmv_data
2957c478bd9Sstevel@tonic-gate	!	g2 = word 0
2967c478bd9Sstevel@tonic-gate	!
2977c478bd9Sstevel@tonic-gate	ldx	[%g1 + IDN_DMV_QBASE], %g4	! g4 = idn_dmv_qbase
2987c478bd9Sstevel@tonic-gate	add	%g1, IDN_DMV_CPU, %g3		! g3 = &idn_dmv_cpu[0]
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate	CPU_INDEX(%g6, %g5)		! g6 = cpuid
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate	!
3037c478bd9Sstevel@tonic-gate	! g5 = cur = idn_dmv_cpu[cpuid]
3047c478bd9Sstevel@tonic-gate	!
3057c478bd9Sstevel@tonic-gate	sll	%g6, IDN_DMV_CPU_SHIFT, %g6	! g6 = cpuid * 8
3067c478bd9Sstevel@tonic-gate	add	%g3, IDN_DMV_CURRENT, %g3
3077c478bd9Sstevel@tonic-gate	ld	[%g6 + %g3], %g5
3087c478bd9Sstevel@tonic-gate	!
3097c478bd9Sstevel@tonic-gate	! g5 = idn_dmv_cpu[cpuid].idn_dmv_current
3107c478bd9Sstevel@tonic-gate	!      offset from idn_dmv_qbase
3117c478bd9Sstevel@tonic-gate	!
3127c478bd9Sstevel@tonic-gate	or	%g5, %g0, %g5		! get to 64-bits
3137c478bd9Sstevel@tonic-gate	add	%g5, %g4, %g5		! g5 = idn_dmv_current
3147c478bd9Sstevel@tonic-gate					!      actual address
3157c478bd9Sstevel@tonic-gate	ldstub	[%g5 + IV_INUSE], %g7	! cur->iv_inuse = 0xff
3167c478bd9Sstevel@tonic-gate	brz,pt	%g7, 1f			! did we get it?
3177c478bd9Sstevel@tonic-gate	sub	%g3, IDN_DMV_CURRENT, %g4
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate	!
3207c478bd9Sstevel@tonic-gate	! Queue is FULL.  Drop interrupt.
3217c478bd9Sstevel@tonic-gate	!
3227c478bd9Sstevel@tonic-gate	add	%g4, IDN_DMV_LOSTINTR, %g3
3237c478bd9Sstevel@tonic-gate	ld	[%g6 + %g3], %g2
3247c478bd9Sstevel@tonic-gate	!
3257c478bd9Sstevel@tonic-gate	! g2 = idn_dmv_cpu[cpuid].idn_iv_lostintr++
3267c478bd9Sstevel@tonic-gate	!
3277c478bd9Sstevel@tonic-gate	inc	%g2
3287c478bd9Sstevel@tonic-gate	set	dmv_finish_intr, %g4
3297c478bd9Sstevel@tonic-gate	st	%g2, [%g3 + %g6]
3307c478bd9Sstevel@tonic-gate	jmp	%g4
3317c478bd9Sstevel@tonic-gate	mov	-1, %g1
3327c478bd9Sstevel@tonic-gate	!
3337c478bd9Sstevel@tonic-gate	! not reached
3347c478bd9Sstevel@tonic-gate	!
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate1:
3377c478bd9Sstevel@tonic-gate	add	%g4, IDN_DMV_ACTIVE, %g7
3387c478bd9Sstevel@tonic-gate	!
3397c478bd9Sstevel@tonic-gate	! Move current pointer to next one.
3407c478bd9Sstevel@tonic-gate	! idn_dmv_current[cpuid] = cur->iv_next
3417c478bd9Sstevel@tonic-gate	!
3427c478bd9Sstevel@tonic-gate	ld	[%g5 + IV_NEXT], %g4
3437c478bd9Sstevel@tonic-gate	st	%g4, [%g3 + %g6]
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate	!
3467c478bd9Sstevel@tonic-gate	! Start filling in structure with data.
3477c478bd9Sstevel@tonic-gate	!
3487c478bd9Sstevel@tonic-gate	stx	%g2, [%g5 + IV_HEAD]
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate	mov	IRDR_1, %g2
3517c478bd9Sstevel@tonic-gate	mov	IRDR_2, %g4
3527c478bd9Sstevel@tonic-gate	ldxa	[%g2]ASI_INTR_RECEIVE, %g2	! g2 = xargs[0,1]
3537c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_INTR_RECEIVE, %g4	! g4 = xargs[2,3]
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate	stx	%g2, [%g5 + IV_XARGS0]
3567c478bd9Sstevel@tonic-gate	stx	%g4, [%g5 + IV_XARGS2]
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate	membar	#StoreLoad|#StoreStore
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate	clrb	[%g5 + IV_READY]	! cur->iv_ready = 0 (unlocked)
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate	!
3637c478bd9Sstevel@tonic-gate	! See if we're already active, i.e. have things
3647c478bd9Sstevel@tonic-gate	! queued.  If so, don't bother generating a soft
3657c478bd9Sstevel@tonic-gate	! interrupt.  IDN interrupts could exhaust the
366*b0fc0e77Sgovinda	! intr_vec structs for the given cpu and that code
367*b0fc0e77Sgovinda	! doesn't know how to survive with intr_vec structs!
3687c478bd9Sstevel@tonic-gate	!
3697c478bd9Sstevel@tonic-gate	ldstub	[%g6 + %g7], %g7	! idn_dmv_active = 0xff
3707c478bd9Sstevel@tonic-gate	brz,a,pt %g7, 2f
371*b0fc0e77Sgovinda	ldx	[%g1 + IDN_SOFT_INUM], %g7	! g7 = idn_soft_inum
3727c478bd9Sstevel@tonic-gate	mov	-1, %g7
3737c478bd9Sstevel@tonic-gate2:
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate	!
3767c478bd9Sstevel@tonic-gate	! Setup to cause an IDN soft interrupt to occur,
3777c478bd9Sstevel@tonic-gate	! (if necessary).
3787c478bd9Sstevel@tonic-gate	!
3797c478bd9Sstevel@tonic-gate	set	dmv_finish_intr, %g3
3807c478bd9Sstevel@tonic-gate	jmp	%g3
3817c478bd9Sstevel@tonic-gate	mov	%g7, %g1
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate	SET_SIZE(idn_dmv_handler)
3847c478bd9Sstevel@tonic-gate
3857c478bd9Sstevel@tonic-gate#endif /* lint */
386