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