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