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  * Assembly language support for physical big/little endian access of pcitool
  31  * in the PCI drivers.
  32  */
  33 
  34 #include <sys/asm_linkage.h>
  35 #include <sys/machthread.h>
  36 #include <sys/privregs.h>
  37 
  38 /*LINTLIBRARY*/
  39 
  40 #if defined(lint)
  41 
  42 /*ARGSUSED*/
  43 int pci_do_phys_peek(size_t size, uint64_t paddr, uint64_t *value, int type)
  44 { return (0); }
  45 
  46 int pci_do_phys_poke(size_t size, uint64_t paddr, uint64_t *value, int type)
  47 { return (0); }
  48 
  49 #else /* lint */
  50 
  51 ! pci_do_phys_peek: Do physical address read.
  52 !
  53 ! %o0 is size in bytes - Must be 8, 4, 2 or 1.  Invalid sizes default to 1.
  54 ! %o1 is address to read
  55 ! %o2 is address to save value into
  56 ! %o3 is 0 for little endian, non-zero for big endian
  57 !
  58 ! To be called from an on_trap environment.
  59 ! Interrupts will be disabled for the duration of the read, to prevent
  60 ! an interrupt from raising the trap level to 1 and then a possible
  61 ! data access exception being delivered while the trap level > 0.
  62 !
  63 ! Assumes alignment is correct.
  64 
  65         ENTRY(pci_do_phys_peek)
  66 
  67         rdpr    %pstate, %o4            ! Disable interrupts if not already
  68         andcc   %o4, PSTATE_IE, %g2     ! Save original state first
  69         bz      .peek_ints_disabled
  70         nop
  71         wrpr    %o4, PSTATE_IE, %pstate
  72 .peek_ints_disabled:
  73 
  74         tst     %o3                     ! Set up %asi with modifier for
  75         movz    %xcc, ASI_IOL, %g1      ! Big/little endian physical space
  76         movnz   %xcc, ASI_IO, %g1
  77         mov     %g1, %asi
  78 
  79         cmp     %o0, 8                  ! 64-bit?
  80         bne     .peek_int
  81         cmp     %o0, 4                  ! 32-bit?
  82         ldxa    [%o1]%asi, %g1
  83         ba      .peekdone
  84         stx     %g1, [%o2]
  85 
  86 .peek_int:
  87         bne     .peek_half
  88         cmp     %o0, 2                  ! 16-bit?
  89         lduwa   [%o1]%asi, %g1
  90         ba      .peekdone
  91         stuw    %g1, [%o2]
  92         
  93 .peek_half:
  94         bne     .peek_byte
  95         nop
  96         lduha   [%o1]%asi, %g1
  97         ba      .peekdone
  98         stuh    %g1, [%o2]
  99 
 100 .peek_byte:
 101         lduba   [%o1]%asi, %g1  ! 8-bit!
 102         stub    %g1, [%o2]
 103  
 104 .peekdone:
 105         membar  #Sync                   ! Make sure the loads take
 106         tst     %g2                     ! No need to reenable interrupts
 107         bz      .peek_ints_done         !       if not enabled at entry
 108         rdpr    %pstate, %o4
 109         wrpr    %o4, PSTATE_IE, %pstate
 110 .peek_ints_done:
 111         mov     %g0, %o0
 112         retl
 113         nop
 114         SET_SIZE(pci_do_phys_peek)
 115 
 116 
 117 ! pci_do_phys_poke: Do physical address write.
 118 !
 119 ! %o0 is size in bytes - Must be 8, 4, 2 or 1.  Invalid sizes default to 1.
 120 ! %o1 is address to write to
 121 ! %o2 is address to read from
 122 ! %o3 is 0 for little endian, non-zero for big endian
 123 !
 124 ! Always returns success (0) in %o0
 125 !
 126 ! Assumes alignment is correct and that on_trap handling has been installed
 127 
 128         ENTRY(pci_do_phys_poke)
 129 
 130         tst     %o3
 131         bz      .poke_asi_set
 132         mov     ASI_IOL, %asi
 133         mov     ASI_IO, %asi
 134 .poke_asi_set:
 135 
 136         cmp     %o0, 8                  ! 64 bit?
 137         bne     .poke_int
 138         cmp     %o0, 4                  ! 32-bit?
 139         ldx     [%o2], %g1
 140         ba      .pokedone
 141         stxa    %g1, [%o1]%asi
 142 
 143 .poke_int:
 144         bne     .poke_half
 145         cmp     %o0, 2                  ! 16-bit?
 146         lduw    [%o2], %g1
 147         ba      .pokedone
 148         stuwa   %g1, [%o1]%asi
 149 
 150 .poke_half:
 151         bne     .poke_byte
 152         nop
 153         lduh    [%o2], %g1
 154         ba      .pokedone
 155         stuha   %g1, [%o1]%asi
 156 
 157 .poke_byte:
 158         ldub    [%o2], %g1              ! 8-bit!
 159         stuba   %g1, [%o1]%asi
 160 
 161 .pokedone:
 162         membar  #Sync
 163         retl
 164         mov     %g0, %o0
 165         SET_SIZE(pci_do_phys_poke)
 166  
 167 #endif