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
geo_module(geoid_t g)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
geo_slab(geoid_t g)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
geo_type(geoid_t g)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
geo_valid(geoid_t g)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
geo_cmp(geoid_t g0,geoid_t g1)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
geo_new(geo_type_t type,...)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 }
315