xref: /illumos-gate/usr/src/uts/sparc/ml/sparc_ddi.S (revision 5d9d9091)
1*5d9d9091SRichard Lowe/*
2*5d9d9091SRichard Lowe * CDDL HEADER START
3*5d9d9091SRichard Lowe *
4*5d9d9091SRichard Lowe * The contents of this file are subject to the terms of the
5*5d9d9091SRichard Lowe * Common Development and Distribution License, Version 1.0 only
6*5d9d9091SRichard Lowe * (the "License").  You may not use this file except in compliance
7*5d9d9091SRichard Lowe * with the License.
8*5d9d9091SRichard Lowe *
9*5d9d9091SRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*5d9d9091SRichard Lowe * or http://www.opensolaris.org/os/licensing.
11*5d9d9091SRichard Lowe * See the License for the specific language governing permissions
12*5d9d9091SRichard Lowe * and limitations under the License.
13*5d9d9091SRichard Lowe *
14*5d9d9091SRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each
15*5d9d9091SRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*5d9d9091SRichard Lowe * If applicable, add the following below this CDDL HEADER, with the
17*5d9d9091SRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
18*5d9d9091SRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
19*5d9d9091SRichard Lowe *
20*5d9d9091SRichard Lowe * CDDL HEADER END
21*5d9d9091SRichard Lowe */
22*5d9d9091SRichard Lowe/*
23*5d9d9091SRichard Lowe * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*5d9d9091SRichard Lowe * Use is subject to license terms.
25*5d9d9091SRichard Lowe */
26*5d9d9091SRichard Lowe/*
27*5d9d9091SRichard Lowe * Copyright 2012  Garrett D'Amore <garrett@damore.org>.  All rights reserved.
28*5d9d9091SRichard Lowe */
29*5d9d9091SRichard Lowe
30*5d9d9091SRichard Lowe/*
31*5d9d9091SRichard Lowe * Assembler routines to make some DDI routines go faster.
32*5d9d9091SRichard Lowe * These routines should ONLY be ISA-dependent.
33*5d9d9091SRichard Lowe */
34*5d9d9091SRichard Lowe
35*5d9d9091SRichard Lowe#include <sys/asm_linkage.h>
36*5d9d9091SRichard Lowe#include <sys/clock.h>
37*5d9d9091SRichard Lowe#include <sys/intreg.h>
38*5d9d9091SRichard Lowe
39*5d9d9091SRichard Lowe#include "assym.h"		/* for FKIOCTL etc. */
40*5d9d9091SRichard Lowe
41*5d9d9091SRichard Lowe
42*5d9d9091SRichard Lowe/*
43*5d9d9091SRichard Lowe * Layered driver routines.
44*5d9d9091SRichard Lowe *
45*5d9d9091SRichard Lowe * At the time of writing, the compiler converts
46*5d9d9091SRichard Lowe *
47*5d9d9091SRichard Lowe * a() { return (b()); }
48*5d9d9091SRichard Lowe *
49*5d9d9091SRichard Lowe * into
50*5d9d9091SRichard Lowe *	save, call b, restore
51*5d9d9091SRichard Lowe *
52*5d9d9091SRichard Lowe * Though this is sort of ok, if the called routine is leaf routine,
53*5d9d9091SRichard Lowe * then we just burnt a register window.
54*5d9d9091SRichard Lowe *
55*5d9d9091SRichard Lowe * When the compiler understands this optimization, many
56*5d9d9091SRichard Lowe * of these routines can go back to C again.
57*5d9d9091SRichard Lowe */
58*5d9d9091SRichard Lowe
59*5d9d9091SRichard Lowe#define	FLATCALL(routine)	\
60*5d9d9091SRichard Lowe	mov	%o7, %g1;	\
61*5d9d9091SRichard Lowe	call	routine;	\
62*5d9d9091SRichard Lowe	mov	%g1, %o7
63*5d9d9091SRichard Lowe
64*5d9d9091SRichard Lowe	ENTRY(ddi_copyin)
65*5d9d9091SRichard Lowe	set	FKIOCTL, %o4
66*5d9d9091SRichard Lowe	andcc	%o3, %o4, %g0
67*5d9d9091SRichard Lowe	bne	.do_kcopy	! share code with ddi_copyout
68*5d9d9091SRichard Lowe	FLATCALL(copyin)
69*5d9d9091SRichard Lowe	/*NOTREACHED*/
70*5d9d9091SRichard Lowe
71*5d9d9091SRichard Lowe.do_kcopy:
72*5d9d9091SRichard Lowe	save	%sp, -SA(MINFRAME), %sp
73*5d9d9091SRichard Lowe	mov	%i2, %o2
74*5d9d9091SRichard Lowe	mov	%i1, %o1
75*5d9d9091SRichard Lowe	call	kcopy
76*5d9d9091SRichard Lowe	mov	%i0, %o0
77*5d9d9091SRichard Lowe	orcc	%g0, %o0, %i0	! if kcopy returns EFAULT ..
78*5d9d9091SRichard Lowe	bne,a	1f
79*5d9d9091SRichard Lowe	mov	-1, %i0		! .. we return -1
80*5d9d9091SRichard Lowe1:	ret
81*5d9d9091SRichard Lowe	restore
82*5d9d9091SRichard Lowe	SET_SIZE(ddi_copyin)
83*5d9d9091SRichard Lowe
84*5d9d9091SRichard Lowe	ENTRY(ddi_copyout)
85*5d9d9091SRichard Lowe	set	FKIOCTL, %o4
86*5d9d9091SRichard Lowe	andcc	%o3, %o4, %g0
87*5d9d9091SRichard Lowe	bne	.do_kcopy	! share code with ddi_copyin
88*5d9d9091SRichard Lowe	FLATCALL(copyout)
89*5d9d9091SRichard Lowe	/*NOTREACHED*/
90*5d9d9091SRichard Lowe	SET_SIZE(ddi_copyout)
91*5d9d9091SRichard Lowe
92*5d9d9091SRichard Lowe/*
93*5d9d9091SRichard Lowe * DDI spine wrapper routines - here so as to not have to
94*5d9d9091SRichard Lowe * buy register windows when climbing the device tree (which cost!)
95*5d9d9091SRichard Lowe */
96*5d9d9091SRichard Lowe
97*5d9d9091SRichard Lowe	ENTRY(ddi_ctlops)
98*5d9d9091SRichard Lowe	tst	%o0		! dip != 0?
99*5d9d9091SRichard Lowe	be,pn	%ncc, 2f	! nope
100*5d9d9091SRichard Lowe	tst	%o1		! rdip != 0?
101*5d9d9091SRichard Lowe	be,pn	%ncc, 2f	! nope
102*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_BUS_CTL], %o0
103*5d9d9091SRichard Lowe				! dip = (dev_info_t *)DEVI(dip)->devi_bus_ctl;
104*5d9d9091SRichard Lowe	brz,pn	%o0, 2f
105*5d9d9091SRichard Lowe	nop			! Delay slot
106*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
107*5d9d9091SRichard Lowe	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
108*5d9d9091SRichard Lowe	ldn	[%g1 + OPS_CTL], %g1	! dip->dev_ops->devo_bus_ops->bus_ctl
109*5d9d9091SRichard Lowe	jmpl	%g1, %g0	! bop off to new routine
110*5d9d9091SRichard Lowe	nop			! as if we had never been here
111*5d9d9091SRichard Lowe2:	retl
112*5d9d9091SRichard Lowe	sub	%g0, 1, %o0	! return (DDI_FAILURE);
113*5d9d9091SRichard Lowe	SET_SIZE(ddi_ctlops)
114*5d9d9091SRichard Lowe
115*5d9d9091SRichard Lowe	ENTRY(ddi_dma_allochdl)
116*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_BUS_DMA_ALLOCHDL], %o0
117*5d9d9091SRichard Lowe			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
118*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
119*5d9d9091SRichard Lowe	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
120*5d9d9091SRichard Lowe	ldn	[%g1 + OPS_ALLOCHDL], %g1
121*5d9d9091SRichard Lowe			! dip->dev_ops->devo_bus_ops->bus_dma_allochdl
122*5d9d9091SRichard Lowe	jmpl	%g1, %g0	! bop off to new routine
123*5d9d9091SRichard Lowe	nop			! as if we had never been here
124*5d9d9091SRichard Lowe	SET_SIZE(ddi_dma_allochdl)
125*5d9d9091SRichard Lowe
126*5d9d9091SRichard Lowe	ENTRY(ddi_dma_freehdl)
127*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_BUS_DMA_FREEHDL], %o0
128*5d9d9091SRichard Lowe			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_freehdl;
129*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
130*5d9d9091SRichard Lowe	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
131*5d9d9091SRichard Lowe	ldn	[%g1 + OPS_FREEHDL], %g1
132*5d9d9091SRichard Lowe			! dip->dev_ops->devo_bus_ops->bus_dma_freehdl
133*5d9d9091SRichard Lowe	jmpl	%g1, %g0	! bop off to new routine
134*5d9d9091SRichard Lowe	nop			! as if we had never been here
135*5d9d9091SRichard Lowe	SET_SIZE(ddi_dma_freehdl)
136*5d9d9091SRichard Lowe
137*5d9d9091SRichard Lowe	ENTRY(ddi_dma_bindhdl)
138*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_BUS_DMA_BINDHDL], %o0
139*5d9d9091SRichard Lowe			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl;
140*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
141*5d9d9091SRichard Lowe	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
142*5d9d9091SRichard Lowe	ldn	[%g1 + OPS_BINDHDL], %g1
143*5d9d9091SRichard Lowe			! dip->dev_ops->devo_bus_ops->bus_dma_bindhdl
144*5d9d9091SRichard Lowe	jmpl	%g1, %g0	! bop off to new routine
145*5d9d9091SRichard Lowe	nop			! as if we had never been here
146*5d9d9091SRichard Lowe	SET_SIZE(ddi_dma_bindhdl)
147*5d9d9091SRichard Lowe
148*5d9d9091SRichard Lowe	ENTRY(ddi_dma_unbindhdl)
149*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_BUS_DMA_UNBINDHDL], %o0
150*5d9d9091SRichard Lowe			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
151*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
152*5d9d9091SRichard Lowe	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
153*5d9d9091SRichard Lowe	ldn	[%g1 + OPS_UNBINDHDL], %g1
154*5d9d9091SRichard Lowe			! dip->dev_ops->devo_bus_ops->bus_dma_unbindhdl
155*5d9d9091SRichard Lowe	jmpl	%g1, %g0	! bop off to new routine
156*5d9d9091SRichard Lowe	nop			! as if we had never been here
157*5d9d9091SRichard Lowe	SET_SIZE(ddi_dma_unbindhdl)
158*5d9d9091SRichard Lowe
159*5d9d9091SRichard Lowe	ENTRY(ddi_dma_flush)
160*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_BUS_DMA_FLUSH], %o0
161*5d9d9091SRichard Lowe			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
162*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
163*5d9d9091SRichard Lowe	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
164*5d9d9091SRichard Lowe	ldn	[%g1 + OPS_FLUSH], %g1
165*5d9d9091SRichard Lowe			! dip->dev_ops->devo_bus_ops->bus_dma_flush
166*5d9d9091SRichard Lowe	jmpl	%g1, %g0	! bop off to new routine
167*5d9d9091SRichard Lowe	nop			! as if we had never been here
168*5d9d9091SRichard Lowe	SET_SIZE(ddi_dma_flush)
169*5d9d9091SRichard Lowe
170*5d9d9091SRichard Lowe	ENTRY(ddi_dma_win)
171*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_BUS_DMA_WIN], %o0
172*5d9d9091SRichard Lowe			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_win;
173*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
174*5d9d9091SRichard Lowe	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
175*5d9d9091SRichard Lowe	ldn	[%g1 + OPS_WIN], %g1
176*5d9d9091SRichard Lowe			! dip->dev_ops->devo_bus_ops->bus_dma_win
177*5d9d9091SRichard Lowe	jmpl	%g1, %g0	! bop off to new routine
178*5d9d9091SRichard Lowe	nop			! as if we had never been here
179*5d9d9091SRichard Lowe	SET_SIZE(ddi_dma_win)
180*5d9d9091SRichard Lowe
181*5d9d9091SRichard Lowe	ENTRY(ddi_dma_sync)
182*5d9d9091SRichard Lowe	ld	[%o0 + DMA_HANDLE_RFLAGS], %o4	! hp->dmai_rflags;
183*5d9d9091SRichard Lowe	sethi	%hi(DMP_NOSYNC), %o5
184*5d9d9091SRichard Lowe	and	%o4, %o5, %o4
185*5d9d9091SRichard Lowe	cmp	%o4, %o5
186*5d9d9091SRichard Lowe	bne	1f
187*5d9d9091SRichard Lowe	mov	%o3, %o5
188*5d9d9091SRichard Lowe	retl
189*5d9d9091SRichard Lowe	clr	%o0
190*5d9d9091SRichard Lowe1:	mov	%o1, %o3
191*5d9d9091SRichard Lowe	ldn	[%o0 + DMA_HANDLE_RDIP], %o1	! dip = hp->dmai_rdip;
192*5d9d9091SRichard Lowe	mov	%o0, %g2
193*5d9d9091SRichard Lowe	ldn	[%o1 + DEVI_BUS_DMA_FLUSH], %o0
194*5d9d9091SRichard Lowe			! dip = DEVI(dip)->devi_bus_dma_flush;
195*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
196*5d9d9091SRichard Lowe	mov	%o2, %o4
197*5d9d9091SRichard Lowe	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
198*5d9d9091SRichard Lowe	mov	%g2, %o2
199*5d9d9091SRichard Lowe	ldn	[%g1 + OPS_FLUSH], %g1
200*5d9d9091SRichard Lowe			! dip->dev_ops->devo_bus_ops->bus_dma_flush
201*5d9d9091SRichard Lowe	jmpl	%g1, %g0	! bop off to new routine
202*5d9d9091SRichard Lowe	nop			! as if we had never been here
203*5d9d9091SRichard Lowe	SET_SIZE(ddi_dma_sync)
204*5d9d9091SRichard Lowe
205*5d9d9091SRichard Lowe	ENTRY(ddi_dma_unbind_handle)
206*5d9d9091SRichard Lowe	ldn	[%o0 + DMA_HANDLE_RDIP], %o1	! dip = hp->dmai_rdip;
207*5d9d9091SRichard Lowe	mov	%o0, %o2
208*5d9d9091SRichard Lowe	ldn	[%o1 + DEVI_BUS_DMA_UNBINDFUNC ], %g1
209*5d9d9091SRichard Lowe		    ! funcp = DEVI(dip)->devi_bus_dma_unbindfunc;
210*5d9d9091SRichard Lowe	jmpl	%g1, %g0	! bop off to new routine
211*5d9d9091SRichard Lowe	ldn	[%o1 + DEVI_BUS_DMA_UNBINDHDL], %o0
212*5d9d9091SRichard Lowe		    ! hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
213*5d9d9091SRichard Lowe	SET_SIZE(ddi_dma_unbind_handle)
214*5d9d9091SRichard Lowe
215*5d9d9091SRichard Lowe
216*5d9d9091SRichard Lowe	ENTRY(ddi_dma_mctl)
217*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_BUS_DMA_CTL], %o0
218*5d9d9091SRichard Lowe			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_ctl;
219*5d9d9091SRichard Lowe	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
220*5d9d9091SRichard Lowe	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
221*5d9d9091SRichard Lowe	ldn	[%g1 + OPS_MCTL], %g1 ! dip->dev_ops->devo_bus_ops->bus_dma_ctl
222*5d9d9091SRichard Lowe	jmpl	%g1, %g0	! bop off to new routine
223*5d9d9091SRichard Lowe	nop			! as if we had never been here
224*5d9d9091SRichard Lowe	SET_SIZE(ddi_dma_mctl)
225*5d9d9091SRichard Lowe
226