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