import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / ia64 / sn / io / sn2 / geo_op.c
1 /* $Id$
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) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
8  */
9
10 /*
11  * @doc file m:hwcfg
12  * DESCRIPTION:
13  * 
14  * This file contains routines for manipulating and generating 
15  * Geographic IDs.  They are in a file by themself since they have
16  * no dependencies on other modules.
17  *  
18  * ORIGIN:
19  * 
20  * New for SN2
21  */
22
23 #include <linux/types.h>
24 #include <linux/slab.h>
25 #include <linux/interrupt.h>
26 #include <asm/smp.h>
27 #include <asm/irq.h>
28 #include <asm/hw_irq.h>
29 #include <asm/sn/types.h>
30 #include <asm/sn/sgi.h>
31 #include <asm/sn/iograph.h>
32 #include <asm/sn/invent.h>
33 #include <asm/sn/hcl.h>
34 #include <asm/sn/labelcl.h>
35 #include <asm/sn/io.h>
36 #include <asm/sn/sn_private.h>
37 #include <asm/sn/klconfig.h>
38 #include <asm/sn/sn_cpuid.h>
39 #include <asm/sn/pci/pciio.h>
40 #include <asm/sn/pci/pcibr.h>
41 #include <asm/sn/xtalk/xtalk.h>
42 #include <asm/sn/pci/pcibr_private.h>
43 #include <asm/sn/intr.h>
44 #include <asm/sn/sn2/shub_mmr_t.h>
45 #include <asm/sn/sn2/shubio.h>
46 #include <asm/sal.h>
47 #include <asm/sn/sn_sal.h>
48 #include <asm/sn/module.h>
49 #include <asm/sn/geo.h>
50
51 /********** Global functions and data (visible outside the module) ***********/
52
53 /*
54  * @doc gf:geo_module
55  * 
56  * moduleid_t geo_module(geoid_t g)
57  * 
58  * DESCRIPTION:
59  * 
60  * Return the moduleid component of a geoid.
61  *  
62  * INTERNALS:
63  * 
64  * Return INVALID_MODULE for an invalid geoid.  Otherwise extract the
65  * moduleid from the structure, and return it.
66  *   
67  * ORIGIN:
68  * 
69  * New for SN2
70  */
71
72 moduleid_t
73 geo_module(geoid_t g)
74 {
75     if (g.any.type == GEO_TYPE_INVALID)
76         return INVALID_MODULE;
77     else
78         return g.any.module;
79 }
80
81
82 /*
83  * @doc gf:geo_slab
84  * 
85  * slabid_t geo_slab(geoid_t g)
86  * 
87  * DESCRIPTION:
88  * 
89  * Return the slabid component of a geoid.
90  *  
91  * INTERNALS:
92  * 
93  * Return INVALID_SLAB for an invalid geoid.  Otherwise extract the
94  * slabid from the structure, and return it.
95  *   
96  * ORIGIN:
97  * 
98  * New for SN2
99  */
100
101 slabid_t
102 geo_slab(geoid_t g)
103 {
104     if (g.any.type == GEO_TYPE_INVALID)
105         return INVALID_SLAB;
106     else
107         return g.any.slab;
108 }
109
110
111 /*
112  * @doc gf:geo_type
113  * 
114  * geo_type_t geo_type(geoid_t g)
115  * 
116  * DESCRIPTION:
117  * 
118  * Return the type component of a geoid.
119  *  
120  * INTERNALS:
121  * 
122  * Extract the type from the structure, and return it.
123  *   
124  * ORIGIN:
125  * 
126  * New for SN2
127  */
128
129 geo_type_t
130 geo_type(geoid_t g)
131 {
132     return g.any.type;
133 }
134
135
136 /*
137  * @doc gf:geo_valid
138  * 
139  * int geo_valid(geoid_t g)
140  * 
141  * DESCRIPTION:
142  * 
143  * Return nonzero if g has a valid geoid type.
144  *  
145  * INTERNALS:
146  * 
147  * Test the type against GEO_TYPE_INVALID, and return the result.
148  *   
149  * ORIGIN:
150  * 
151  * New for SN2
152  */
153
154 int
155 geo_valid(geoid_t g)
156 {
157     return g.any.type != GEO_TYPE_INVALID;
158 }
159
160
161 /*
162  * @doc gf:geo_cmp
163  * 
164  * int geo_cmp(geoid_t g0, geoid_t g1)
165  * 
166  * DESCRIPTION:
167  * 
168  * Compare two geoid_t values, from the coarsest field to the finest.
169  * The comparison should be consistent with the physical locations of
170  * of the hardware named by the geoids.
171  *  
172  * INTERNALS:
173  * 
174  * First compare the module, then the slab, type, and type-specific fields.
175  *   
176  * ORIGIN:
177  * 
178  * New for SN2
179  */
180
181 int
182 geo_cmp(geoid_t g0, geoid_t g1)
183 {
184     int rv;
185
186     /* Compare the common fields */
187     rv = MODULE_CMP(geo_module(g0), geo_module(g1));
188     if (rv != 0)
189         return rv;
190
191     rv = geo_slab(g0) - geo_slab(g1);
192     if (rv != 0)
193         return rv;
194
195     /* Within a slab, sort by type */
196     rv = geo_type(g0) - geo_type(g1);
197     if (rv != 0)
198         return rv;
199
200     switch(geo_type(g0)) {
201     case GEO_TYPE_CPU:
202         rv = g0.cpu.slice - g1.cpu.slice;
203         break;
204
205     case GEO_TYPE_IOCARD:
206         rv = g0.pcicard.bus - g1.pcicard.bus;
207         if (rv) break;
208         rv = SLOTNUM_GETSLOT(g0.pcicard.slot) -
209             SLOTNUM_GETSLOT(g1.pcicard.slot);
210         break;
211
212     case GEO_TYPE_MEM:
213         rv = g0.mem.membus - g1.mem.membus;
214         if (rv) break;
215         rv = g0.mem.memslot - g1.mem.memslot;
216         break;
217
218     default:
219         rv = 0;
220     }
221
222     return rv;
223 }
224
225
226 /*
227  * @doc gf:geo_new
228  * 
229  * geoid_t geo_new(geo_type_t type, ...)
230  * 
231  * DESCRIPTION:
232  * 
233  * Generate a new geoid_t value of the given type from its components.
234  * Expected calling sequences:
235  * \@itemize \@bullet
236  * \@item
237  * \@code\{geo_new(GEO_TYPE_INVALID)\}
238  * \@item
239  * \@code\{geo_new(GEO_TYPE_MODULE, moduleid_t m)\}
240  * \@item
241  * \@code\{geo_new(GEO_TYPE_NODE, moduleid_t m, slabid_t s)\}
242  * \@item
243  * \@code\{geo_new(GEO_TYPE_RTR, moduleid_t m, slabid_t s)\}
244  * \@item
245  * \@code\{geo_new(GEO_TYPE_IOCNTL, moduleid_t m, slabid_t s)\}
246  * \@item
247  * \@code\{geo_new(GEO_TYPE_IOCARD, moduleid_t m, slabid_t s, char bus, slotid_t slot)\}
248  * \@item
249  * \@code\{geo_new(GEO_TYPE_CPU, moduleid_t m, slabid_t s, char slice)\}
250  * \@item
251  * \@code\{geo_new(GEO_TYPE_MEM, moduleid_t m, slabid_t s, char membus, char slot)\}
252  * \@end itemize
253  *
254  * Invalid types return a GEO_TYPE_INVALID geoid_t.
255  *  
256  * INTERNALS:
257  * 
258  * Use the type to determine which fields to expect.  Write the fields into
259  * a new geoid_t and return it.  Note:  scalars smaller than an "int" are
260  * promoted to "int" by the "..." operator, so we need extra casts on "char",
261  * "slotid_t", and "slabid_t".
262  *   
263  * ORIGIN:
264  * 
265  * New for SN2
266  */
267
268 geoid_t
269 geo_new(geo_type_t type, ...)
270 {
271     va_list al;
272     geoid_t g;
273     memset(&g, 0, sizeof(g));
274
275     va_start(al, type);
276
277     /* Make sure the type is sane */
278     if (type >= GEO_TYPE_MAX)
279         type = GEO_TYPE_INVALID;
280
281     g.any.type = type;
282     if (type == GEO_TYPE_INVALID)
283         goto done;              /* invalid geoids have no components at all */
284
285     g.any.module = va_arg(al, moduleid_t);
286     if (type == GEO_TYPE_MODULE)
287         goto done;
288
289     g.any.slab = (slabid_t)va_arg(al, int);
290
291     /* Some types have additional components */
292     switch(type) {
293     case GEO_TYPE_CPU:
294         g.cpu.slice = (char)va_arg(al, int);
295         break;
296
297     case GEO_TYPE_IOCARD:
298         g.pcicard.bus = (char)va_arg(al, int);
299         g.pcicard.slot = (slotid_t)va_arg(al, int);
300         break;
301
302     case GEO_TYPE_MEM:
303         g.mem.membus = (char)va_arg(al, int);
304         g.mem.memslot = (char)va_arg(al, int);
305         break;
306
307     default:
308         break;
309     }
310
311  done:
312     va_end(al);
313     return g;
314 }