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#pragma ident "%Z%%M% %I% %E% SMI" 28 29/* 30 * Assembler routines to make some DDI routines go faster. 31 * These routines should ONLY be ISA-dependent. 32 */ 33 34#if defined(lint) 35 36#include <sys/types.h> 37#include <sys/systm.h> 38#include <sys/file.h> 39#include <sys/sunddi.h> 40 41#else /* lint */ 42 43#include <sys/asm_linkage.h> 44#include <sys/clock.h> 45#include <sys/intreg.h> 46 47#include "assym.h" /* for FKIOCTL etc. */ 48 49#endif /* lint */ 50 51 52/* 53 * Layered driver routines. 54 * 55 * At the time of writing, the compiler converts 56 * 57 * a() { return (b()); } 58 * 59 * into 60 * save, call b, restore 61 * 62 * Though this is sort of ok, if the called routine is leaf routine, 63 * then we just burnt a register window. 64 * 65 * When the compiler understands this optimization, many 66 * of these routines can go back to C again. 67 */ 68 69#define FLATCALL(routine) \ 70 mov %o7, %g1; \ 71 call routine; \ 72 mov %g1, %o7 73 74#ifdef lint 75 76int 77ddi_copyin(const void *buf, void *kernbuf, size_t size, int flags) 78{ 79 if (flags & FKIOCTL) 80 return (kcopy(buf, kernbuf, size) ? -1 : 0); 81 return (copyin(buf, kernbuf, size)); 82} 83 84#else /* lint */ 85 86 ENTRY(ddi_copyin) 87 set FKIOCTL, %o4 88 andcc %o3, %o4, %g0 89 bne .do_kcopy ! share code with ddi_copyout 90 FLATCALL(copyin) 91 /*NOTREACHED*/ 92 93.do_kcopy: 94 save %sp, -SA(MINFRAME), %sp 95 mov %i2, %o2 96 mov %i1, %o1 97 call kcopy 98 mov %i0, %o0 99 orcc %g0, %o0, %i0 ! if kcopy returns EFAULT .. 100 bne,a 1f 101 mov -1, %i0 ! .. we return -1 1021: ret 103 restore 104 SET_SIZE(ddi_copyin) 105 106#endif /* lint */ 107 108#ifdef lint 109 110int 111ddi_copyout(const void *buf, void *kernbuf, size_t size, int flags) 112{ 113 if (flags & FKIOCTL) 114 return (kcopy(buf, kernbuf, size) ? -1 : 0); 115 return (copyout(buf, kernbuf, size)); 116} 117 118#else /* lint */ 119 120 ENTRY(ddi_copyout) 121 set FKIOCTL, %o4 122 andcc %o3, %o4, %g0 123 bne .do_kcopy ! share code with ddi_copyin 124 FLATCALL(copyout) 125 /*NOTREACHED*/ 126 SET_SIZE(ddi_copyout) 127 128#endif /* lint */ 129 130/* 131 * DDI spine wrapper routines - here so as to not have to 132 * buy register windows when climbing the device tree (which cost!) 133 */ 134 135#if defined(lint) 136 137/*ARGSUSED*/ 138int 139ddi_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t op, void *a, void *v) 140{ 141 return (DDI_SUCCESS); 142} 143 144#else /* lint */ 145 146 ENTRY(ddi_ctlops) 147 tst %o0 ! dip != 0? 148 be,pn %ncc, 2f ! nope 149 tst %o1 ! rdip != 0? 150 be,pn %ncc, 2f ! nope 151 ldn [%o0 + DEVI_BUS_CTL], %o0 152 ! dip = (dev_info_t *)DEVI(dip)->devi_bus_ctl; 153 brz,pn %o0, 2f 154 nop ! Delay slot 155 ldn [%o0 + DEVI_DEV_OPS], %g1 ! dip->dev_ops 156 ldn [%g1 + DEVI_BUS_OPS], %g1 ! dip->dev_ops->devo_bus_ops 157 ldn [%g1 + OPS_CTL], %g1 ! dip->dev_ops->devo_bus_ops->bus_ctl 158 jmpl %g1, %g0 ! bop off to new routine 159 nop ! as if we had never been here 1602: retl 161 sub %g0, 1, %o0 ! return (DDI_FAILURE); 162 SET_SIZE(ddi_ctlops) 163 164#endif /* lint */ 165 166#if defined(lint) 167 168/* ARGSUSED */ 169int 170ddi_dma_map(dev_info_t *dip, dev_info_t *rdip, 171 struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep) 172{ 173 return (DDI_SUCCESS); 174} 175 176#else /* lint */ 177 178 ENTRY(ddi_dma_map) 179 ldn [%o0 + DEVI_BUS_DMA_MAP], %o0 180 ! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_map; 181 ldn [%o0 + DEVI_DEV_OPS], %g1 ! dip->dev_ops 182 ldn [%g1 + DEVI_BUS_OPS], %g1 ! dip->dev_ops->devo_bus_ops 183 ldn [%g1 + OPS_MAP], %g1 ! dip->dev_ops->devo_bus_ops->bus_dma_map 184 jmpl %g1, %g0 ! bop off to new routine 185 nop ! as if we had never been here 186 SET_SIZE(ddi_dma_map) 187 188#endif /* lint */ 189 190#if defined(lint) 191 192/* ARGSUSED */ 193int 194ddi_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr, 195 int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep) 196{ 197 return (DDI_SUCCESS); 198} 199 200#else /* lint */ 201 202 ENTRY(ddi_dma_allochdl) 203 ldn [%o0 + DEVI_BUS_DMA_ALLOCHDL], %o0 204 ! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl; 205 ldn [%o0 + DEVI_DEV_OPS], %g1 ! dip->dev_ops 206 ldn [%g1 + DEVI_BUS_OPS], %g1 ! dip->dev_ops->devo_bus_ops 207 ldn [%g1 + OPS_ALLOCHDL], %g1 208 ! dip->dev_ops->devo_bus_ops->bus_dma_allochdl 209 jmpl %g1, %g0 ! bop off to new routine 210 nop ! as if we had never been here 211 SET_SIZE(ddi_dma_allochdl) 212 213#endif /* lint */ 214 215#if defined(lint) 216 217/* ARGSUSED */ 218int 219ddi_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handlep) 220{ 221 return (DDI_SUCCESS); 222} 223 224#else /* lint */ 225 226 ENTRY(ddi_dma_freehdl) 227 ldn [%o0 + DEVI_BUS_DMA_FREEHDL], %o0 228 ! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_freehdl; 229 ldn [%o0 + DEVI_DEV_OPS], %g1 ! dip->dev_ops 230 ldn [%g1 + DEVI_BUS_OPS], %g1 ! dip->dev_ops->devo_bus_ops 231 ldn [%g1 + OPS_FREEHDL], %g1 232 ! dip->dev_ops->devo_bus_ops->bus_dma_freehdl 233 jmpl %g1, %g0 ! bop off to new routine 234 nop ! as if we had never been here 235 SET_SIZE(ddi_dma_freehdl) 236 237#endif /* lint */ 238 239#if defined(lint) 240 241/* ARGSUSED */ 242int 243ddi_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 244 ddi_dma_handle_t handle, struct ddi_dma_req *dmareq, 245 ddi_dma_cookie_t *cp, u_int *ccountp) 246{ 247 return (DDI_SUCCESS); 248} 249 250#else /* lint */ 251 252 ENTRY(ddi_dma_bindhdl) 253 ldn [%o0 + DEVI_BUS_DMA_BINDHDL], %o0 254 ! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl; 255 ldn [%o0 + DEVI_DEV_OPS], %g1 ! dip->dev_ops 256 ldn [%g1 + DEVI_BUS_OPS], %g1 ! dip->dev_ops->devo_bus_ops 257 ldn [%g1 + OPS_BINDHDL], %g1 258 ! dip->dev_ops->devo_bus_ops->bus_dma_bindhdl 259 jmpl %g1, %g0 ! bop off to new routine 260 nop ! as if we had never been here 261 SET_SIZE(ddi_dma_bindhdl) 262 263#endif /* lint */ 264 265#if defined(lint) 266 267/* ARGSUSED */ 268int 269ddi_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 270 ddi_dma_handle_t handle) 271{ 272 return (DDI_SUCCESS); 273} 274 275#else /* lint */ 276 277 ENTRY(ddi_dma_unbindhdl) 278 ldn [%o0 + DEVI_BUS_DMA_UNBINDHDL], %o0 279 ! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl; 280 ldn [%o0 + DEVI_DEV_OPS], %g1 ! dip->dev_ops 281 ldn [%g1 + DEVI_BUS_OPS], %g1 ! dip->dev_ops->devo_bus_ops 282 ldn [%g1 + OPS_UNBINDHDL], %g1 283 ! dip->dev_ops->devo_bus_ops->bus_dma_unbindhdl 284 jmpl %g1, %g0 ! bop off to new routine 285 nop ! as if we had never been here 286 SET_SIZE(ddi_dma_unbindhdl) 287 288#endif /* lint */ 289 290#if defined(lint) 291 292/* ARGSUSED */ 293int 294ddi_dma_flush(dev_info_t *dip, dev_info_t *rdip, 295 ddi_dma_handle_t handle, off_t off, size_t len, 296 u_int cache_flags) 297{ 298 return (DDI_SUCCESS); 299} 300 301#else /* lint */ 302 303 ENTRY(ddi_dma_flush) 304 ldn [%o0 + DEVI_BUS_DMA_FLUSH], %o0 305 ! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush; 306 ldn [%o0 + DEVI_DEV_OPS], %g1 ! dip->dev_ops 307 ldn [%g1 + DEVI_BUS_OPS], %g1 ! dip->dev_ops->devo_bus_ops 308 ldn [%g1 + OPS_FLUSH], %g1 309 ! dip->dev_ops->devo_bus_ops->bus_dma_flush 310 jmpl %g1, %g0 ! bop off to new routine 311 nop ! as if we had never been here 312 SET_SIZE(ddi_dma_flush) 313 314#endif /* lint */ 315 316#if defined(lint) 317 318/* ARGSUSED */ 319int 320ddi_dma_win(dev_info_t *dip, dev_info_t *rdip, 321 ddi_dma_handle_t handle, uint_t win, off_t *offp, 322 size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp) 323{ 324 return (DDI_SUCCESS); 325} 326 327#else /* lint */ 328 329 ENTRY(ddi_dma_win) 330 ldn [%o0 + DEVI_BUS_DMA_WIN], %o0 331 ! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_win; 332 ldn [%o0 + DEVI_DEV_OPS], %g1 ! dip->dev_ops 333 ldn [%g1 + DEVI_BUS_OPS], %g1 ! dip->dev_ops->devo_bus_ops 334 ldn [%g1 + OPS_WIN], %g1 335 ! dip->dev_ops->devo_bus_ops->bus_dma_win 336 jmpl %g1, %g0 ! bop off to new routine 337 nop ! as if we had never been here 338 SET_SIZE(ddi_dma_win) 339 340#endif /* lint */ 341 342#if defined(lint) 343 344/* ARGSUSED */ 345int 346ddi_dma_sync(ddi_dma_handle_t h, off_t o, size_t l, u_int whom) 347{ 348 return (DDI_SUCCESS); 349} 350 351#else /* lint */ 352 353 ENTRY(ddi_dma_sync) 354 ld [%o0 + DMA_HANDLE_RFLAGS], %o4 ! hp->dmai_rflags; 355 sethi %hi(DMP_NOSYNC), %o5 356 and %o4, %o5, %o4 357 cmp %o4, %o5 358 bne 1f 359 mov %o3, %o5 360 retl 361 clr %o0 3621: mov %o1, %o3 363 ldn [%o0 + DMA_HANDLE_RDIP], %o1 ! dip = hp->dmai_rdip; 364 mov %o0, %g2 365 ldn [%o1 + DEVI_BUS_DMA_FLUSH], %o0 366 ! dip = DEVI(dip)->devi_bus_dma_flush; 367 ldn [%o0 + DEVI_DEV_OPS], %g1 ! dip->dev_ops 368 mov %o2, %o4 369 ldn [%g1 + DEVI_BUS_OPS], %g1 ! dip->dev_ops->devo_bus_ops 370 mov %g2, %o2 371 ldn [%g1 + OPS_FLUSH], %g1 372 ! dip->dev_ops->devo_bus_ops->bus_dma_flush 373 jmpl %g1, %g0 ! bop off to new routine 374 nop ! as if we had never been here 375 SET_SIZE(ddi_dma_sync) 376 377#endif /* lint */ 378 379#if defined(lint) 380 381/* ARGSUSED */ 382int 383ddi_dma_unbind_handle(ddi_dma_handle_t h) 384{ 385 return (DDI_SUCCESS); 386} 387 388#else /* lint */ 389 390 ENTRY(ddi_dma_unbind_handle) 391 ldn [%o0 + DMA_HANDLE_RDIP], %o1 ! dip = hp->dmai_rdip; 392 mov %o0, %o2 393 ldn [%o1 + DEVI_BUS_DMA_UNBINDFUNC ], %g1 394 ! funcp = DEVI(dip)->devi_bus_dma_unbindfunc; 395 jmpl %g1, %g0 ! bop off to new routine 396 ldn [%o1 + DEVI_BUS_DMA_UNBINDHDL], %o0 397 ! hdip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl; 398 SET_SIZE(ddi_dma_unbind_handle) 399 400#endif /* lint */ 401 402 403#if defined(lint) 404 405/*ARGSUSED*/ 406int 407ddi_dma_mctl(register dev_info_t *dip, dev_info_t *rdip, 408 ddi_dma_handle_t handle, enum ddi_dma_ctlops request, 409 off_t *offp, size_t *lenp, caddr_t *objp, u_int flags) 410{ 411 return (DDI_SUCCESS); 412} 413 414#else /* lint */ 415 416 ENTRY(ddi_dma_mctl) 417 ldn [%o0 + DEVI_BUS_DMA_CTL], %o0 418 ! dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_ctl; 419 ldn [%o0 + DEVI_DEV_OPS], %g1 ! dip->dev_ops 420 ldn [%g1 + DEVI_BUS_OPS], %g1 ! dip->dev_ops->devo_bus_ops 421 ldn [%g1 + OPS_MCTL], %g1 ! dip->dev_ops->devo_bus_ops->bus_dma_ctl 422 jmpl %g1, %g0 ! bop off to new routine 423 nop ! as if we had never been here 424 SET_SIZE(ddi_dma_mctl) 425 426#endif /* lint */ 427