xref: /titanic_52/usr/src/uts/sparc/ml/sparc_ddi.s (revision 2c2d21e98a95cba5687ec6574c974a5c6c4a6adb)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26/*
27 * Copyright 2012  Garrett D'Amore <garrett@damore.org>.  All rights reserved.
28 */
29
30/*
31 * Assembler routines to make some DDI routines go faster.
32 * These routines should ONLY be ISA-dependent.
33 */
34
35#if defined(lint)
36
37#include <sys/types.h>
38#include <sys/systm.h>
39#include <sys/file.h>
40#include <sys/sunddi.h>
41
42#else	/* lint */
43
44#include <sys/asm_linkage.h>
45#include <sys/clock.h>
46#include <sys/intreg.h>
47
48#include "assym.h"		/* for FKIOCTL etc. */
49
50#endif	/* lint */
51
52
53/*
54 * Layered driver routines.
55 *
56 * At the time of writing, the compiler converts
57 *
58 * a() { return (b()); }
59 *
60 * into
61 *	save, call b, restore
62 *
63 * Though this is sort of ok, if the called routine is leaf routine,
64 * then we just burnt a register window.
65 *
66 * When the compiler understands this optimization, many
67 * of these routines can go back to C again.
68 */
69
70#define	FLATCALL(routine)	\
71	mov	%o7, %g1;	\
72	call	routine;	\
73	mov	%g1, %o7
74
75#ifdef	lint
76
77int
78ddi_copyin(const void *buf, void *kernbuf, size_t size, int flags)
79{
80	if (flags & FKIOCTL)
81		return (kcopy(buf, kernbuf, size) ? -1 : 0);
82	return (copyin(buf, kernbuf, size));
83}
84
85#else	/* lint */
86
87	ENTRY(ddi_copyin)
88	set	FKIOCTL, %o4
89	andcc	%o3, %o4, %g0
90	bne	.do_kcopy	! share code with ddi_copyout
91	FLATCALL(copyin)
92	/*NOTREACHED*/
93
94.do_kcopy:
95	save	%sp, -SA(MINFRAME), %sp
96	mov	%i2, %o2
97	mov	%i1, %o1
98	call	kcopy
99	mov	%i0, %o0
100	orcc	%g0, %o0, %i0	! if kcopy returns EFAULT ..
101	bne,a	1f
102	mov	-1, %i0		! .. we return -1
1031:	ret
104	restore
105	SET_SIZE(ddi_copyin)
106
107#endif	/* lint */
108
109#ifdef	lint
110
111int
112ddi_copyout(const void *buf, void *kernbuf, size_t size, int flags)
113{
114	if (flags & FKIOCTL)
115		return (kcopy(buf, kernbuf, size) ? -1 : 0);
116	return (copyout(buf, kernbuf, size));
117}
118
119#else	/* lint */
120
121	ENTRY(ddi_copyout)
122	set	FKIOCTL, %o4
123	andcc	%o3, %o4, %g0
124	bne	.do_kcopy	! share code with ddi_copyin
125	FLATCALL(copyout)
126	/*NOTREACHED*/
127	SET_SIZE(ddi_copyout)
128
129#endif	/* lint */
130
131/*
132 * DDI spine wrapper routines - here so as to not have to
133 * buy register windows when climbing the device tree (which cost!)
134 */
135
136#if	defined(lint)
137
138/*ARGSUSED*/
139int
140ddi_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t op, void *a, void *v)
141{
142	return (DDI_SUCCESS);
143}
144
145#else	/* lint */
146
147	ENTRY(ddi_ctlops)
148	tst	%o0		! dip != 0?
149	be,pn	%ncc, 2f	! nope
150	tst	%o1		! rdip != 0?
151	be,pn	%ncc, 2f	! nope
152	ldn	[%o0 + DEVI_BUS_CTL], %o0
153				! dip = (dev_info_t *)DEVI(dip)->devi_bus_ctl;
154	brz,pn	%o0, 2f
155	nop			! Delay slot
156	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
157	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
158	ldn	[%g1 + OPS_CTL], %g1	! dip->dev_ops->devo_bus_ops->bus_ctl
159	jmpl	%g1, %g0	! bop off to new routine
160	nop			! as if we had never been here
1612:	retl
162	sub	%g0, 1, %o0	! return (DDI_FAILURE);
163	SET_SIZE(ddi_ctlops)
164
165#endif	/* lint */
166
167#if	defined(lint)
168
169/* ARGSUSED */
170int
171ddi_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
172	int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
173{
174	return (DDI_SUCCESS);
175}
176
177#else	/* lint */
178
179	ENTRY(ddi_dma_allochdl)
180	ldn	[%o0 + DEVI_BUS_DMA_ALLOCHDL], %o0
181			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl;
182	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
183	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
184	ldn	[%g1 + OPS_ALLOCHDL], %g1
185			! dip->dev_ops->devo_bus_ops->bus_dma_allochdl
186	jmpl	%g1, %g0	! bop off to new routine
187	nop			! as if we had never been here
188	SET_SIZE(ddi_dma_allochdl)
189
190#endif	/* lint */
191
192#if	defined(lint)
193
194/* ARGSUSED */
195int
196ddi_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handlep)
197{
198	return (DDI_SUCCESS);
199}
200
201#else	/* lint */
202
203	ENTRY(ddi_dma_freehdl)
204	ldn	[%o0 + DEVI_BUS_DMA_FREEHDL], %o0
205			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_freehdl;
206	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
207	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
208	ldn	[%g1 + OPS_FREEHDL], %g1
209			! dip->dev_ops->devo_bus_ops->bus_dma_freehdl
210	jmpl	%g1, %g0	! bop off to new routine
211	nop			! as if we had never been here
212	SET_SIZE(ddi_dma_freehdl)
213
214#endif	/* lint */
215
216#if	defined(lint)
217
218/* ARGSUSED */
219int
220ddi_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
221	ddi_dma_handle_t handle, struct ddi_dma_req *dmareq,
222	ddi_dma_cookie_t *cp, u_int *ccountp)
223{
224	return (DDI_SUCCESS);
225}
226
227#else	/* lint */
228
229	ENTRY(ddi_dma_bindhdl)
230	ldn	[%o0 + DEVI_BUS_DMA_BINDHDL], %o0
231			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl;
232	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
233	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
234	ldn	[%g1 + OPS_BINDHDL], %g1
235			! dip->dev_ops->devo_bus_ops->bus_dma_bindhdl
236	jmpl	%g1, %g0	! bop off to new routine
237	nop			! as if we had never been here
238	SET_SIZE(ddi_dma_bindhdl)
239
240#endif	/* lint */
241
242#if	defined(lint)
243
244/* ARGSUSED */
245int
246ddi_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
247	ddi_dma_handle_t handle)
248{
249	return (DDI_SUCCESS);
250}
251
252#else	/* lint */
253
254	ENTRY(ddi_dma_unbindhdl)
255	ldn	[%o0 + DEVI_BUS_DMA_UNBINDHDL], %o0
256			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
257	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
258	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
259	ldn	[%g1 + OPS_UNBINDHDL], %g1
260			! dip->dev_ops->devo_bus_ops->bus_dma_unbindhdl
261	jmpl	%g1, %g0	! bop off to new routine
262	nop			! as if we had never been here
263	SET_SIZE(ddi_dma_unbindhdl)
264
265#endif	/* lint */
266
267#if	defined(lint)
268
269/* ARGSUSED */
270int
271ddi_dma_flush(dev_info_t *dip, dev_info_t *rdip,
272	ddi_dma_handle_t handle, off_t off, size_t len,
273	u_int cache_flags)
274{
275	return (DDI_SUCCESS);
276}
277
278#else	/* lint */
279
280	ENTRY(ddi_dma_flush)
281	ldn	[%o0 + DEVI_BUS_DMA_FLUSH], %o0
282			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush;
283	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
284	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
285	ldn	[%g1 + OPS_FLUSH], %g1
286			! dip->dev_ops->devo_bus_ops->bus_dma_flush
287	jmpl	%g1, %g0	! bop off to new routine
288	nop			! as if we had never been here
289	SET_SIZE(ddi_dma_flush)
290
291#endif	/* lint */
292
293#if	defined(lint)
294
295/* ARGSUSED */
296int
297ddi_dma_win(dev_info_t *dip, dev_info_t *rdip,
298	ddi_dma_handle_t handle, uint_t win, off_t *offp,
299	size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
300{
301	return (DDI_SUCCESS);
302}
303
304#else	/* lint */
305
306	ENTRY(ddi_dma_win)
307	ldn	[%o0 + DEVI_BUS_DMA_WIN], %o0
308			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_win;
309	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
310	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
311	ldn	[%g1 + OPS_WIN], %g1
312			! dip->dev_ops->devo_bus_ops->bus_dma_win
313	jmpl	%g1, %g0	! bop off to new routine
314	nop			! as if we had never been here
315	SET_SIZE(ddi_dma_win)
316
317#endif	/* lint */
318
319#if	defined(lint)
320
321/* ARGSUSED */
322int
323ddi_dma_sync(ddi_dma_handle_t h, off_t o, size_t l, u_int whom)
324{
325	return (DDI_SUCCESS);
326}
327
328#else	/* lint */
329
330	ENTRY(ddi_dma_sync)
331	ld	[%o0 + DMA_HANDLE_RFLAGS], %o4	! hp->dmai_rflags;
332	sethi	%hi(DMP_NOSYNC), %o5
333	and	%o4, %o5, %o4
334	cmp	%o4, %o5
335	bne	1f
336	mov	%o3, %o5
337	retl
338	clr	%o0
3391:	mov	%o1, %o3
340	ldn	[%o0 + DMA_HANDLE_RDIP], %o1	! dip = hp->dmai_rdip;
341	mov	%o0, %g2
342	ldn	[%o1 + DEVI_BUS_DMA_FLUSH], %o0
343			! dip = DEVI(dip)->devi_bus_dma_flush;
344	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
345	mov	%o2, %o4
346	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
347	mov	%g2, %o2
348	ldn	[%g1 + OPS_FLUSH], %g1
349			! dip->dev_ops->devo_bus_ops->bus_dma_flush
350	jmpl	%g1, %g0	! bop off to new routine
351	nop			! as if we had never been here
352	SET_SIZE(ddi_dma_sync)
353
354#endif	/* lint */
355
356#if	defined(lint)
357
358/* ARGSUSED */
359int
360ddi_dma_unbind_handle(ddi_dma_handle_t h)
361{
362	return (DDI_SUCCESS);
363}
364
365#else	/* lint */
366
367	ENTRY(ddi_dma_unbind_handle)
368	ldn	[%o0 + DMA_HANDLE_RDIP], %o1	! dip = hp->dmai_rdip;
369	mov	%o0, %o2
370	ldn	[%o1 + DEVI_BUS_DMA_UNBINDFUNC ], %g1
371		    ! funcp = DEVI(dip)->devi_bus_dma_unbindfunc;
372	jmpl	%g1, %g0	! bop off to new routine
373	ldn	[%o1 + DEVI_BUS_DMA_UNBINDHDL], %o0
374		    ! hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl;
375	SET_SIZE(ddi_dma_unbind_handle)
376
377#endif	/* lint */
378
379
380#if	defined(lint)
381
382/*ARGSUSED*/
383int
384ddi_dma_mctl(register dev_info_t *dip, dev_info_t *rdip,
385    ddi_dma_handle_t handle, enum ddi_dma_ctlops request,
386    off_t *offp, size_t *lenp, caddr_t *objp, u_int flags)
387{
388	return (DDI_SUCCESS);
389}
390
391#else	/* lint */
392
393	ENTRY(ddi_dma_mctl)
394	ldn	[%o0 + DEVI_BUS_DMA_CTL], %o0
395			! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_ctl;
396	ldn	[%o0 + DEVI_DEV_OPS], %g1	! dip->dev_ops
397	ldn	[%g1 + DEVI_BUS_OPS], %g1	! dip->dev_ops->devo_bus_ops
398	ldn	[%g1 + OPS_MCTL], %g1 ! dip->dev_ops->devo_bus_ops->bus_dma_ctl
399	jmpl	%g1, %g0	! bop off to new routine
400	nop			! as if we had never been here
401	SET_SIZE(ddi_dma_mctl)
402
403#endif	/* lint */
404