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 77 int 78 ddi_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 103 1: ret 104 restore 105 SET_SIZE(ddi_copyin) 106 107 #endif /* lint */ 108 109 #ifdef lint 110 111 int 112 ddi_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*/ 139 int 140 ddi_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 161 2: 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 */ 170 int 171 ddi_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 */ 195 int 196 ddi_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 */ 219 int 220 ddi_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 */ 245 int 246 ddi_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 */ 270 int 271 ddi_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 */ 296 int 297 ddi_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 */ 322 int 323 ddi_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 339 1: 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 */ 359 int 360 ddi_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*/ 383 int 384 ddi_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 */