xref: /illumos-gate/usr/src/uts/sparc/ml/sparc_ddi.s (revision 9b0bb795)
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
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate/*
237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
26*cd21e7c5SGarrett D'Amore/*
27*cd21e7c5SGarrett D'Amore * Copyright 2012  Garrett D'Amore <garrett@damore.org>.  All rights reserved.
28*cd21e7c5SGarrett D'Amore */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate/*
317c478bd9Sstevel@tonic-gate * Assembler routines to make some DDI routines go faster.
327c478bd9Sstevel@tonic-gate * These routines should ONLY be ISA-dependent.
337c478bd9Sstevel@tonic-gate */
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
367c478bd9Sstevel@tonic-gate#include <sys/clock.h>
377c478bd9Sstevel@tonic-gate#include <sys/intreg.h>
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate#include "assym.h"		/* for FKIOCTL etc. */
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate/*
437c478bd9Sstevel@tonic-gate * Layered driver routines.
447c478bd9Sstevel@tonic-gate *
457c478bd9Sstevel@tonic-gate * At the time of writing, the compiler converts
467c478bd9Sstevel@tonic-gate *
477c478bd9Sstevel@tonic-gate * a() { return (b()); }
487c478bd9Sstevel@tonic-gate *
497c478bd9Sstevel@tonic-gate * into
507c478bd9Sstevel@tonic-gate *	save, call b, restore
517c478bd9Sstevel@tonic-gate *
527c478bd9Sstevel@tonic-gate * Though this is sort of ok, if the called routine is leaf routine,
537c478bd9Sstevel@tonic-gate * then we just burnt a register window.
547c478bd9Sstevel@tonic-gate *
557c478bd9Sstevel@tonic-gate * When the compiler understands this optimization, many
567c478bd9Sstevel@tonic-gate * of these routines can go back to C again.
577c478bd9Sstevel@tonic-gate */
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate#define	FLATCALL(routine)	\
607c478bd9Sstevel@tonic-gate	mov	%o7, %g1;	\
617c478bd9Sstevel@tonic-gate	call	routine;	\
627c478bd9Sstevel@tonic-gate	mov	%g1, %o7
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate	ENTRY(ddi_copyin)
657c478bd9Sstevel@tonic-gate	set	FKIOCTL, %o4
667c478bd9Sstevel@tonic-gate	andcc	%o3, %o4, %g0
677c478bd9Sstevel@tonic-gate	bne	.do_kcopy	! share code with ddi_copyout
687c478bd9Sstevel@tonic-gate	FLATCALL(copyin)
697c478bd9Sstevel@tonic-gate	/*NOTREACHED*/
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate.do_kcopy:
727c478bd9Sstevel@tonic-gate	save	%sp, -SA(MINFRAME), %sp
737c478bd9Sstevel@tonic-gate	mov	%i2, %o2
747c478bd9Sstevel@tonic-gate	mov	%i1, %o1
757c478bd9Sstevel@tonic-gate	call	kcopy
767c478bd9Sstevel@tonic-gate	mov	%i0, %o0
777c478bd9Sstevel@tonic-gate	orcc	%g0, %o0, %i0	! if kcopy returns EFAULT ..
787c478bd9Sstevel@tonic-gate	bne,a	1f
797c478bd9Sstevel@tonic-gate	mov	-1, %i0		! .. we return -1
807c478bd9Sstevel@tonic-gate1:	ret
817c478bd9Sstevel@tonic-gate	restore
827c478bd9Sstevel@tonic-gate	SET_SIZE(ddi_copyin)
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate	ENTRY(ddi_copyout)
857c478bd9Sstevel@tonic-gate	set	FKIOCTL, %o4
867c478bd9Sstevel@tonic-gate	andcc	%o3, %o4, %g0
877c478bd9Sstevel@tonic-gate	bne	.do_kcopy	! share code with ddi_copyin
887c478bd9Sstevel@tonic-gate	FLATCALL(copyout)
897c478bd9Sstevel@tonic-gate	/*NOTREACHED*/
907c478bd9Sstevel@tonic-gate	SET_SIZE(ddi_copyout)
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate/*
937c478bd9Sstevel@tonic-gate * DDI spine wrapper routines - here so as to not have to
947c478bd9Sstevel@tonic-gate * buy register windows when climbing the device tree (which cost!)
957c478bd9Sstevel@tonic-gate */
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate	ENTRY(ddi_ctlops)
987c478bd9Sstevel@tonic-gate	tst	%o0		! dip != 0?
997c478bd9Sstevel@tonic-gate	be,pn	%ncc, 2f	! nope
1007c478bd9Sstevel@tonic-gate	tst	%o1		! rdip != 0?
1017c478bd9Sstevel@tonic-gate	be,pn	%ncc, 2f	! nope
1027c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_BUS_CTL], %o0
1037c478bd9Sstevel@tonic-gate				! dip = (dev_info_t *)DEVI(dip)->devi_bus_ctl;
1047c478bd9Sstevel@tonic-gate	brz,pn	%o0, 2f
1057c478bd9Sstevel@tonic-gate	nop			! Delay slot
1067c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
1077c478bd9Sstevel@tonic-gate	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
1087c478bd9Sstevel@tonic-gate	ldn	[%g1 + OPS_CTL], %g1	! dip->dev_ops->devo_bus_ops->bus_ctl
1097c478bd9Sstevel@tonic-gate	jmpl	%g1, %g0	! bop off to new routine
1107c478bd9Sstevel@tonic-gate	nop			! as if we had never been here
1117c478bd9Sstevel@tonic-gate2:	retl
1127c478bd9Sstevel@tonic-gate	sub	%g0, 1, %o0	! return (DDI_FAILURE);
1137c478bd9Sstevel@tonic-gate	SET_SIZE(ddi_ctlops)
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate	ENTRY(ddi_dma_allochdl)
1167c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_BUS_DMA_ALLOCHDL], %o0
1177c478bd9Sstevel@tonic-gate			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
1187c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
1197c478bd9Sstevel@tonic-gate	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
1207c478bd9Sstevel@tonic-gate	ldn	[%g1 + OPS_ALLOCHDL], %g1
1217c478bd9Sstevel@tonic-gate			! dip->dev_ops->devo_bus_ops->bus_dma_allochdl
1227c478bd9Sstevel@tonic-gate	jmpl	%g1, %g0	! bop off to new routine
1237c478bd9Sstevel@tonic-gate	nop			! as if we had never been here
1247c478bd9Sstevel@tonic-gate	SET_SIZE(ddi_dma_allochdl)
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate	ENTRY(ddi_dma_freehdl)
1277c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_BUS_DMA_FREEHDL], %o0
1287c478bd9Sstevel@tonic-gate			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_freehdl;
1297c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
1307c478bd9Sstevel@tonic-gate	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
1317c478bd9Sstevel@tonic-gate	ldn	[%g1 + OPS_FREEHDL], %g1
1327c478bd9Sstevel@tonic-gate			! dip->dev_ops->devo_bus_ops->bus_dma_freehdl
1337c478bd9Sstevel@tonic-gate	jmpl	%g1, %g0	! bop off to new routine
1347c478bd9Sstevel@tonic-gate	nop			! as if we had never been here
1357c478bd9Sstevel@tonic-gate	SET_SIZE(ddi_dma_freehdl)
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate	ENTRY(ddi_dma_bindhdl)
1387c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_BUS_DMA_BINDHDL], %o0
1397c478bd9Sstevel@tonic-gate			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl;
1407c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
1417c478bd9Sstevel@tonic-gate	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
1427c478bd9Sstevel@tonic-gate	ldn	[%g1 + OPS_BINDHDL], %g1
1437c478bd9Sstevel@tonic-gate			! dip->dev_ops->devo_bus_ops->bus_dma_bindhdl
1447c478bd9Sstevel@tonic-gate	jmpl	%g1, %g0	! bop off to new routine
1457c478bd9Sstevel@tonic-gate	nop			! as if we had never been here
1467c478bd9Sstevel@tonic-gate	SET_SIZE(ddi_dma_bindhdl)
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate	ENTRY(ddi_dma_unbindhdl)
1497c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_BUS_DMA_UNBINDHDL], %o0
1507c478bd9Sstevel@tonic-gate			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
1517c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
1527c478bd9Sstevel@tonic-gate	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
1537c478bd9Sstevel@tonic-gate	ldn	[%g1 + OPS_UNBINDHDL], %g1
1547c478bd9Sstevel@tonic-gate			! dip->dev_ops->devo_bus_ops->bus_dma_unbindhdl
1557c478bd9Sstevel@tonic-gate	jmpl	%g1, %g0	! bop off to new routine
1567c478bd9Sstevel@tonic-gate	nop			! as if we had never been here
1577c478bd9Sstevel@tonic-gate	SET_SIZE(ddi_dma_unbindhdl)
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate	ENTRY(ddi_dma_flush)
1607c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_BUS_DMA_FLUSH], %o0
1617c478bd9Sstevel@tonic-gate			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
1627c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
1637c478bd9Sstevel@tonic-gate	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
1647c478bd9Sstevel@tonic-gate	ldn	[%g1 + OPS_FLUSH], %g1
1657c478bd9Sstevel@tonic-gate			! dip->dev_ops->devo_bus_ops->bus_dma_flush
1667c478bd9Sstevel@tonic-gate	jmpl	%g1, %g0	! bop off to new routine
1677c478bd9Sstevel@tonic-gate	nop			! as if we had never been here
1687c478bd9Sstevel@tonic-gate	SET_SIZE(ddi_dma_flush)
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate	ENTRY(ddi_dma_win)
1717c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_BUS_DMA_WIN], %o0
1727c478bd9Sstevel@tonic-gate			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_win;
1737c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
1747c478bd9Sstevel@tonic-gate	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
1757c478bd9Sstevel@tonic-gate	ldn	[%g1 + OPS_WIN], %g1
1767c478bd9Sstevel@tonic-gate			! dip->dev_ops->devo_bus_ops->bus_dma_win
1777c478bd9Sstevel@tonic-gate	jmpl	%g1, %g0	! bop off to new routine
1787c478bd9Sstevel@tonic-gate	nop			! as if we had never been here
1797c478bd9Sstevel@tonic-gate	SET_SIZE(ddi_dma_win)
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate	ENTRY(ddi_dma_sync)
1827c478bd9Sstevel@tonic-gate	ld	[%o0 + DMA_HANDLE_RFLAGS], %o4	! hp->dmai_rflags;
1837c478bd9Sstevel@tonic-gate	sethi	%hi(DMP_NOSYNC), %o5
1847c478bd9Sstevel@tonic-gate	and	%o4, %o5, %o4
1857c478bd9Sstevel@tonic-gate	cmp	%o4, %o5
1867c478bd9Sstevel@tonic-gate	bne	1f
1877c478bd9Sstevel@tonic-gate	mov	%o3, %o5
1887c478bd9Sstevel@tonic-gate	retl
1897c478bd9Sstevel@tonic-gate	clr	%o0
1907c478bd9Sstevel@tonic-gate1:	mov	%o1, %o3
1917c478bd9Sstevel@tonic-gate	ldn	[%o0 + DMA_HANDLE_RDIP], %o1	! dip = hp->dmai_rdip;
1927c478bd9Sstevel@tonic-gate	mov	%o0, %g2
1937c478bd9Sstevel@tonic-gate	ldn	[%o1 + DEVI_BUS_DMA_FLUSH], %o0
1947c478bd9Sstevel@tonic-gate			! dip = DEVI(dip)->devi_bus_dma_flush;
1957c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
1967c478bd9Sstevel@tonic-gate	mov	%o2, %o4
1977c478bd9Sstevel@tonic-gate	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
1987c478bd9Sstevel@tonic-gate	mov	%g2, %o2
1997c478bd9Sstevel@tonic-gate	ldn	[%g1 + OPS_FLUSH], %g1
2007c478bd9Sstevel@tonic-gate			! dip->dev_ops->devo_bus_ops->bus_dma_flush
2017c478bd9Sstevel@tonic-gate	jmpl	%g1, %g0	! bop off to new routine
2027c478bd9Sstevel@tonic-gate	nop			! as if we had never been here
2037c478bd9Sstevel@tonic-gate	SET_SIZE(ddi_dma_sync)
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate	ENTRY(ddi_dma_unbind_handle)
2067c478bd9Sstevel@tonic-gate	ldn	[%o0 + DMA_HANDLE_RDIP], %o1	! dip = hp->dmai_rdip;
2077c478bd9Sstevel@tonic-gate	mov	%o0, %o2
2087c478bd9Sstevel@tonic-gate	ldn	[%o1 + DEVI_BUS_DMA_UNBINDFUNC ], %g1
2097c478bd9Sstevel@tonic-gate		    ! funcp = DEVI(dip)->devi_bus_dma_unbindfunc;
2107c478bd9Sstevel@tonic-gate	jmpl	%g1, %g0	! bop off to new routine
2117c478bd9Sstevel@tonic-gate	ldn	[%o1 + DEVI_BUS_DMA_UNBINDHDL], %o0
2127c478bd9Sstevel@tonic-gate		    ! hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
2137c478bd9Sstevel@tonic-gate	SET_SIZE(ddi_dma_unbind_handle)
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate	ENTRY(ddi_dma_mctl)
2177c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_BUS_DMA_CTL], %o0
2187c478bd9Sstevel@tonic-gate			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_ctl;
2197c478bd9Sstevel@tonic-gate	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
2207c478bd9Sstevel@tonic-gate	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
2217c478bd9Sstevel@tonic-gate	ldn	[%g1 + OPS_MCTL], %g1 ! dip->dev_ops->devo_bus_ops->bus_dma_ctl
2227c478bd9Sstevel@tonic-gate	jmpl	%g1, %g0	! bop off to new routine
2237c478bd9Sstevel@tonic-gate	nop			! as if we had never been here
2247c478bd9Sstevel@tonic-gate	SET_SIZE(ddi_dma_mctl)
2257c478bd9Sstevel@tonic-gate
226