/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/asm_linkage.h>
#include <sys/machthread.h>
#include <sys/privregs.h>
#include <sys/dditypes.h>
#ifndef lint
#include "assym.h"
#endif
#if defined(lint)
#include <sys/isa_defs.h>
#endif /* lint */
/*
* This file implements the following ddi common access
* functions:
*
* ddi_get{8,16,32,64}
* ddi_put{8,16,32,64}
*
* and the underlying "trivial" implementations
*
* i_ddi_{get,put}{8,16,32,64}
*
* which assume that there is no need to check the access handle -
* byte swapping will be done by the mmu and the address is always
*/
#if defined(lint)
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
{
return (0);
}
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
int
{
return (0);
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
#else
/*
* the respective indirect function defined in the access handle. Use of
* the access handle functions provides compatibility across platforms for
* drivers.
*
* By default, the indirect access handle functions are initialized to the
* is not possible or desired, the access handle must be intialized to another
* valid routine to perform the sepcified IO operation.
*
* The alignment and placement of the following functions have been optimized
* such that the implementation specific versions, i_ddi*, fall within the
* same cache-line of the generic versions, ddi_*. This insures that an
* I-cache hit will occur thus minimizing the performance impact of using the
* access handle.
*/
.align 32
.align 16
.align 32
.align 16
.align 32
.align 16
.align 32
.align 16
.align 32
.align 16
.align 32
.align 16
.align 32
.align 16
.align 32
.align 16
/*
* The ddi_io_rep_get/put routines don't take a flag argument like the "plain"
* and mem versions do. This flag is used to determine whether or not the
* device address or port should be automatically incremented. For IO space,
* the device port is never incremented and as such, the flag is always set
* to DDI_DEV_NO_AUTOINCR.
*
* This define processes the repetitive get functionality. Automatic
* incrementing of the device address is determined by the flag field
* %o4. If this is set for AUTOINCR, %o4 is updated with 1 for the
* subsequent increment in 2:.
*
* If this flag is not set for AUTOINCR, %o4 is update with a value of 0 thus
* making the increment operation a non-operation.
*/
#define DDI_REP_GET(n,s) \
2: \
1:
.align 32
.align 16
.align 32
.align 16
.align 32
.align 16
.align 32
.align 16
DDI_REP_GET(8,x)
/*
* This define processes the repetitive put functionality. Automatic
* incrementing of the device address is determined by the flag field
* %o4. If this is set for AUTOINCR, %o4 is updated with 1 for the
* subsequent increment in 2:.
*
* If this flag is not set for AUTOINCR, %o4 is update with a value of 0 thus
* making the increment operation a non-operation.
*/
#define DDI_REP_PUT(n,s) \
2: \
1:
.align 32
.align 16
.align 32
.align 16
.align 32
.align 16
.align 32
.align 16
DDI_REP_PUT(8,x)
.align 16
.align 16
.align 16
.align 16
.align 64
0: ! else return (DDI_SUCCESS)
.align 16
.align 16
.align 16
.align 16
.align 16
.peek_int:
.peekdone:
bnz 1f
1:
done:
.poke_int:
.pokedone:
/*
* The peek_fault() and poke_fault() routines below are used as on_trap()
* trampoline routines. i_ddi_peek and i_ddi_poke execute do_peek and do_poke
* refer to the corresponding routine below. If a trap occurs, the trap code
* will bounce back to the trampoline code, which will effectively cause
* do_peek or do_poke to return DDI_FAILURE, instead of longjmp'ing back to
* on_trap. In the case of a peek, we may also need to re-enable interrupts.
*/
.seg ".data"
.asciz "peek_fault: missing or invalid on_trap_data"
.asciz "poke_fault: missing or invalid on_trap_data"
bnz 1f
1:
.peekfail:
.pokefail:
/*
* IO Fault Services
*
* Support for protected IO accesses is implemented in the following
* functions. A driver may request one of three protection mechanisms
* that enable the system to survive an access errors. The protection
* mechansim is set-up during ddi_regs_map_setup time and may be one of:
*
* DDI_DEFAULT_ACC - no error protection requested. We will
* defined above.
*
* DDI_FLAGERR - Driver requests that errors encountered will
* be flagged by the system. The driver is
* responsible for checking the error status
* of the access with a call to ddi_acc_err_get()
* upon return of ddi_get or ddi_put. To prevent
* an access from causing a system we use internal
* on_trap semantics.
*
* The system, depending upon the error,
* may or may not panic.
*
* DDI_CAUTIOUS_ACC - Driver expects that the access may cause
* an error to occur. The system will return
* an error status but will not generate an ereport.
* The system will also ensure synchronous and
* exclusive access to the IO space accessed by
* the caller.
*
* To prevent an access from causing a system panic,
* we use on_trap semantics to catch the error and
* set error status.
*
* If a read access error is detected and DDI_CAUTIOUS_ACC or
* DDI_FLAGERR_ACC protection was requested, we will trampoline to the
* error handler, i_ddi_trampoline. i_ddi_trampoline will:
* - check for proper protection semantics
* - set the error status of the access handle to DDI_FM_NONFATAL
* - re-enable interrupts if neccessary
* - longjmp back to the initiating access function.
* If a write access error is detected, an interrupt is typically
* generated and claimed by a bus nexus responsible for the write
* transaction. The nexus error handler is expected to set the
* error status and the IO initiating driver is expected to check
* for a failed transaction via ddi_fm_acc_err_get().
*
*/
.seg ".data"
.asciz "DDI access: missing or invalid on_trap_data"
bnz 1f
1:
/*
* DDI on_trap set-up functions, i_ddi_ontrap() and i_ddinotrap() are used
* to protect * ddi_get accesses for DDI_CAUT_ACC. i_ddi_ontrap() sets
* the jumpbuf (setjmp) that will return back to the access routine from
* i_ddi_trampoline(). DDI_NOPROTECT() clears the ontrap set-up.
*/
b setjmp
/*
* Internal on_trap set-up macros. DDI_PROTECT() and DDI_NOPROTECT() are used
* to protect * ddi_get accesses for DDI_FLAGERR_ACC. DDI_NOPROTECT() sets
* the jumpbuf that will return back to the access routine from
* i_ddi_protect_trampoline(). DDI_NOPROTECT() clears the ontrap set-up.
*/
bnz 1f
1:
#define DDI_PROTECT() \
#define DDI_NOPROTECT() \
/*
*/
.align 16
.align 16
.align 16
.align 16
.align 16
.align 16
.align 16
.align 16
.align 16
bnz,a 1f
1:
.align 16
bnz,a 1f
1:
.align 16
bnz,a 1f
1:
.align 16
bnz,a 1f
DDI_REP_GET(8,x)
1:
.align 16
.align 16
.align 16
.align 16
DDI_REP_PUT(8,x)
/*
* Common DDI_CAUTIOUS_ACC routine called from cautious access routines
* in ddi_impl.c
*/
.get_int:
.get_half:
.get_byte:
.getdone:
#endif /* lint */