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