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