~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c

Version: ~ [ linux-5.0-rc6 ] ~ [ linux-4.20.10 ] ~ [ linux-4.19.23 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.101 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.158 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.174 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.134 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.63 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *
  3  * This file is subject to the terms and conditions of the GNU General Public
  4  * License.  See the file "COPYING" in the main directory of this archive
  5  * for more details.
  6  *
  7  * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved.
  8  */
  9 
 10 #include <linux/types.h>
 11 #include <linux/slab.h>
 12 #include <linux/module.h>
 13 #include <linux/byteorder/swab.h>
 14 #include <asm/sn/sgi.h>
 15 #include <asm/sn/sn_cpuid.h>
 16 #include <asm/sn/addrs.h>
 17 #include <asm/sn/arch.h>
 18 #include <asm/sn/iograph.h>
 19 #include <asm/sn/invent.h>
 20 #include <asm/sn/hcl.h>
 21 #include <asm/sn/labelcl.h>
 22 #include <asm/sn/xtalk/xwidget.h>
 23 #include <asm/sn/pci/bridge.h>
 24 #include <asm/sn/pci/pciio.h>
 25 #include <asm/sn/pci/pcibr.h>
 26 #include <asm/sn/pci/pcibr_private.h>
 27 #include <asm/sn/pci/pci_defs.h>
 28 #include <asm/sn/prio.h>
 29 #include <asm/sn/xtalk/xbow.h>
 30 #include <asm/sn/io.h>
 31 #include <asm/sn/sn_private.h>
 32 
 33 extern pcibr_info_t      pcibr_info_get(vertex_hdl_t);
 34 
 35 uint64_t          pcibr_config_get(vertex_hdl_t, unsigned, unsigned);
 36 uint64_t          do_pcibr_config_get(cfg_p, unsigned, unsigned);
 37 void              pcibr_config_set(vertex_hdl_t, unsigned, unsigned, uint64_t);
 38 void              do_pcibr_config_set(cfg_p, unsigned, unsigned, uint64_t);
 39 
 40 /*
 41  * on sn-ia we need to twiddle the the addresses going out
 42  * the pci bus because we use the unswizzled synergy space
 43  * (the alternative is to use the swizzled synergy space
 44  * and byte swap the data)
 45  */
 46 #define CB(b,r) (((volatile uint8_t *) b)[((r)^4)])
 47 #define CS(b,r) (((volatile uint16_t *) b)[((r^4)/2)])
 48 #define CW(b,r) (((volatile uint32_t *) b)[((r^4)/4)])
 49 
 50 #define CBP(b,r) (((volatile uint8_t *) b)[(r)])
 51 #define CSP(b,r) (((volatile uint16_t *) b)[((r)/2)])
 52 #define CWP(b,r) (((volatile uint32_t *) b)[(r)/4])
 53 
 54 #define SCB(b,r) (((volatile uint8_t *) b)[((r)^3)])
 55 #define SCS(b,r) (((volatile uint16_t *) b)[((r^2)/2)])
 56 #define SCW(b,r) (((volatile uint32_t *) b)[((r)/4)])
 57 
 58 /*
 59  * Return a config space address for given slot / func / offset.  Note the
 60  * returned pointer is a 32bit word (ie. cfg_p) aligned pointer pointing to
 61  * the 32bit word that contains the "offset" byte.
 62  */
 63 cfg_p
 64 pcibr_func_config_addr(bridge_t *bridge, pciio_bus_t bus, pciio_slot_t slot, 
 65                                         pciio_function_t func, int offset)
 66 {
 67         /*
 68          * Type 1 config space
 69          */
 70         if (bus > 0) {
 71                 bridge->b_pci_cfg = ((bus << 16) | (slot << 11));
 72                 return &bridge->b_type1_cfg.f[func].l[(offset)];
 73         }
 74 
 75         /*
 76          * Type 0 config space
 77          */
 78         slot++;
 79         return &bridge->b_type0_cfg_dev[slot].f[func].l[offset];
 80 }
 81 
 82 /*
 83  * Return config space address for given slot / offset.  Note the returned
 84  * pointer is a 32bit word (ie. cfg_p) aligned pointer pointing to the
 85  * 32bit word that contains the "offset" byte.
 86  */
 87 cfg_p
 88 pcibr_slot_config_addr(bridge_t *bridge, pciio_slot_t slot, int offset)
 89 {
 90         return pcibr_func_config_addr(bridge, 0, slot, 0, offset);
 91 }
 92 
 93 /*
 94  * Return config space data for given slot / offset
 95  */
 96 unsigned
 97 pcibr_slot_config_get(bridge_t *bridge, pciio_slot_t slot, int offset)
 98 {
 99         cfg_p  cfg_base;
100         
101         cfg_base = pcibr_slot_config_addr(bridge, slot, 0);
102         return (do_pcibr_config_get(cfg_base, offset, sizeof(unsigned)));
103 }
104 
105 /*
106  * Return config space data for given slot / func / offset
107  */
108 unsigned
109 pcibr_func_config_get(bridge_t *bridge, pciio_slot_t slot, 
110                                         pciio_function_t func, int offset)
111 {
112         cfg_p  cfg_base;
113 
114         cfg_base = pcibr_func_config_addr(bridge, 0, slot, func, 0);
115         return (do_pcibr_config_get(cfg_base, offset, sizeof(unsigned)));
116 }
117 
118 /*
119  * Set config space data for given slot / offset
120  */
121 void
122 pcibr_slot_config_set(bridge_t *bridge, pciio_slot_t slot, 
123                                         int offset, unsigned val)
124 {
125         cfg_p  cfg_base;
126 
127         cfg_base = pcibr_slot_config_addr(bridge, slot, 0);
128         do_pcibr_config_set(cfg_base, offset, sizeof(unsigned), val);
129 }
130 
131 /*
132  * Set config space data for given slot / func / offset
133  */
134 void
135 pcibr_func_config_set(bridge_t *bridge, pciio_slot_t slot, 
136                         pciio_function_t func, int offset, unsigned val)
137 {
138         cfg_p  cfg_base;
139 
140         cfg_base = pcibr_func_config_addr(bridge, 0, slot, func, 0);
141         do_pcibr_config_set(cfg_base, offset, sizeof(unsigned), val);
142 }
143 
144 int pcibr_config_debug = 0;
145 
146 cfg_p
147 pcibr_config_addr(vertex_hdl_t conn,
148                   unsigned reg)
149 {
150     pcibr_info_t            pcibr_info;
151     pciio_bus_t             pciio_bus;
152     pciio_slot_t            pciio_slot;
153     pciio_function_t        pciio_func;
154     pcibr_soft_t            pcibr_soft;
155     bridge_t               *bridge;
156     cfg_p                   cfgbase = (cfg_p)0;
157     pciio_info_t            pciio_info;
158 
159     pciio_info = pciio_info_get(conn);
160     pcibr_info = pcibr_info_get(conn);
161 
162     /*
163      * Determine the PCI bus/slot/func to generate a config address for.
164      */
165 
166     if (pciio_info_type1_get(pciio_info)) {
167         /*
168          * Conn is a vhdl which uses TYPE 1 addressing explicitly passed 
169          * in reg.
170          */
171         pciio_bus = PCI_TYPE1_BUS(reg);
172         pciio_slot = PCI_TYPE1_SLOT(reg);
173         pciio_func = PCI_TYPE1_FUNC(reg);
174 
175         ASSERT(pciio_bus != 0);
176     } else {
177         /*
178          * Conn is directly connected to the host bus.  PCI bus number is
179          * hardcoded to 0 (even though it may have a logical bus number != 0)
180          * and slot/function are derived from the pcibr_info_t associated
181          * with the device.
182          */
183         pciio_bus = 0;
184 
185     pciio_slot = PCIBR_INFO_SLOT_GET_INT(pcibr_info);
186     if (pciio_slot == PCIIO_SLOT_NONE)
187         pciio_slot = PCI_TYPE1_SLOT(reg);
188 
189     pciio_func = pcibr_info->f_func;
190     if (pciio_func == PCIIO_FUNC_NONE)
191         pciio_func = PCI_TYPE1_FUNC(reg);
192     }
193 
194     pcibr_soft = (pcibr_soft_t) pcibr_info->f_mfast;
195 
196     bridge = pcibr_soft->bs_base;
197 
198     cfgbase = pcibr_func_config_addr(bridge,
199                         pciio_bus, pciio_slot, pciio_func, 0);
200 
201     return cfgbase;
202 }
203 
204 uint64_t
205 pcibr_config_get(vertex_hdl_t conn,
206                  unsigned reg,
207                  unsigned size)
208 {
209         return do_pcibr_config_get(pcibr_config_addr(conn, reg),
210                                 PCI_TYPE1_REG(reg), size);
211 }
212 
213 uint64_t
214 do_pcibr_config_get(cfg_p cfgbase,
215                        unsigned reg,
216                        unsigned size)
217 {
218     unsigned                value;
219 
220     value = CWP(cfgbase, reg);
221     if (reg & 3)
222         value >>= 8 * (reg & 3);
223     if (size < 4)
224         value &= (1 << (8 * size)) - 1;
225     return value;
226 }
227 
228 void
229 pcibr_config_set(vertex_hdl_t conn,
230                  unsigned reg,
231                  unsigned size,
232                  uint64_t value)
233 {
234         do_pcibr_config_set(pcibr_config_addr(conn, reg),
235                         PCI_TYPE1_REG(reg), size, value);
236 }
237 
238 void
239 do_pcibr_config_set(cfg_p cfgbase,
240                     unsigned reg,
241                     unsigned size,
242                     uint64_t value)
243 {
244         switch (size) {
245         case 1:
246                 CBP(cfgbase, reg) = value;
247                 break;
248         case 2:
249                 if (reg & 1) {
250                         CBP(cfgbase, reg) = value;
251                         CBP(cfgbase, reg + 1) = value >> 8;
252                 } else
253                         CSP(cfgbase, reg) = value;
254                 break;
255         case 3:
256                 if (reg & 1) {
257                         CBP(cfgbase, reg) = value;
258                         CSP(cfgbase, (reg + 1)) = value >> 8;
259                 } else {
260                         CSP(cfgbase, reg) = value;
261                         CBP(cfgbase, reg + 2) = value >> 16;
262                 }
263                 break;
264         case 4:
265                 CWP(cfgbase, reg) = value;
266                 break;
267         }
268 }
269 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp