1 | /* |
---|
2 | * Copyright (c) 1992-1998 Michael A. Cooper. |
---|
3 | * This software may be freely used and distributed provided it is not |
---|
4 | * sold for profit or used in part or in whole for commercial gain |
---|
5 | * without prior written agreement, and the author is credited |
---|
6 | * appropriately. |
---|
7 | */ |
---|
8 | |
---|
9 | #ifndef lint |
---|
10 | static char *RCSid = "$Revision: 1.1.1.1 $"; |
---|
11 | #endif |
---|
12 | |
---|
13 | /* |
---|
14 | * Open Boot PROM (OBP) routines |
---|
15 | */ |
---|
16 | |
---|
17 | #include "defs.h" |
---|
18 | #include "sunos-kdt.h" |
---|
19 | #include "sunos-obp.h" |
---|
20 | |
---|
21 | #if defined(HAVE_OPENPROM) |
---|
22 | |
---|
23 | #define OBP_IS_BOOL(tp) (tp->Key[strlen(tp->Key)-1] == '?' \ |
---|
24 | || !tp->Value || tp->Value[0] == CNULL) |
---|
25 | |
---|
26 | /* |
---|
27 | * Pointer to Tree of all OBP nodes. |
---|
28 | */ |
---|
29 | static OBPnode_t *OBPnodeTree = NULL; |
---|
30 | |
---|
31 | /* |
---|
32 | * Various declarations |
---|
33 | */ |
---|
34 | static long CpuClockFreq = 0; |
---|
35 | |
---|
36 | /* |
---|
37 | * Function declarations |
---|
38 | */ |
---|
39 | static int OBPgetCPUspeed(); |
---|
40 | |
---|
41 | /* |
---|
42 | * Print debugging info of Prop Info |
---|
43 | */ |
---|
44 | static void OBPprintPropInfo(NodeName, Prop) |
---|
45 | char *NodeName; |
---|
46 | OBPprop_t *Prop; |
---|
47 | { |
---|
48 | register OBPprop_t *Ptr; |
---|
49 | |
---|
50 | for (Ptr = Prop; Ptr; Ptr = Ptr->Next) |
---|
51 | SImsg(SIM_DBG, "OBPpropInfo:\t<%s> <%s>=<%s>", |
---|
52 | PRTS(NodeName), |
---|
53 | (Ptr->Key) ? Ptr->Key : "", (Ptr->Value) ? Ptr->Value : ""); |
---|
54 | } |
---|
55 | |
---|
56 | /* |
---|
57 | * Print debugging info of OBP Node |
---|
58 | */ |
---|
59 | static void OBPprintInfo(Node) |
---|
60 | OBPnode_t *Node; |
---|
61 | { |
---|
62 | SImsg(SIM_DBG, |
---|
63 | "OBPnode: Name=<%s> ID=<0x%x> ParentID=<0x%x> ParentName=<%s>", |
---|
64 | (Node->Name) ? Node->Name : "", Node->NodeID, Node->ParentID, |
---|
65 | (Node->ParentName) ? Node->ParentName : ""); |
---|
66 | |
---|
67 | if (Node->PropTable) |
---|
68 | OBPprintPropInfo(Node->Name, Node->PropTable); |
---|
69 | |
---|
70 | if (Node->Children) |
---|
71 | OBPprintInfo(Node->Children); |
---|
72 | |
---|
73 | if (Node->Next) |
---|
74 | OBPprintInfo(Node->Next); |
---|
75 | } |
---|
76 | |
---|
77 | /* |
---|
78 | * Get next OBP tree node id using "what" as what to get. |
---|
79 | */ |
---|
80 | static OBPnodeid_t OBPnodeNext(NodeID, obp_fd, What) |
---|
81 | OBPnodeid_t NodeID; |
---|
82 | int obp_fd; |
---|
83 | int What; |
---|
84 | { |
---|
85 | OBPio_t opio; |
---|
86 | struct openpromio *op; |
---|
87 | int *idptr; |
---|
88 | |
---|
89 | op = &(opio.opio_oprom); |
---|
90 | idptr = (OBPnodeid_t *) (op->oprom_array); |
---|
91 | memset((void *)opio.opio_buff, 0, sizeof(opio.opio_buff)); |
---|
92 | *idptr = NodeID; |
---|
93 | op->oprom_size = sizeof(opio.opio_buff); |
---|
94 | |
---|
95 | if (ioctl(obp_fd, What, op) < 0) { |
---|
96 | SImsg(SIM_GERR, "OBP ioctl %s failed: %s.", |
---|
97 | (What == OPROMNEXT) ? "OPROMNEXT" : "OPROMCHILD", |
---|
98 | SYSERR); |
---|
99 | return(0); |
---|
100 | } |
---|
101 | |
---|
102 | return(*((OBPnodeid_t *)op->oprom_array)); |
---|
103 | } |
---|
104 | |
---|
105 | /* |
---|
106 | * Set the property value of propname from the OBP. |
---|
107 | */ |
---|
108 | static int OBPsetPropVal(Prop, obp_fd) |
---|
109 | OBPprop_t *Prop; |
---|
110 | int obp_fd; |
---|
111 | { |
---|
112 | static OBPio_t opio; |
---|
113 | struct openpromio *op; |
---|
114 | register char *cp; |
---|
115 | |
---|
116 | op = &(opio.opio_oprom); |
---|
117 | op->oprom_size = sizeof(opio.opio_buff); |
---|
118 | (void) strcpy(op->oprom_array, Prop->Key); |
---|
119 | |
---|
120 | if (ioctl(obp_fd, OPROMGETPROP, op) < 0) { |
---|
121 | SImsg(SIM_GERR, "OBP ioctl OPROMGETPROP failed for '%s': %s.", |
---|
122 | Prop->Key, SYSERR); |
---|
123 | return(-1); |
---|
124 | } |
---|
125 | |
---|
126 | if (op->oprom_size == -1) { |
---|
127 | SImsg(SIM_DBG, "OBP no data available for '%s'.", Prop->Key); |
---|
128 | return(-1); |
---|
129 | } |
---|
130 | |
---|
131 | /* |
---|
132 | * Copy Raw info |
---|
133 | */ |
---|
134 | Prop->RawLen = op->oprom_size; |
---|
135 | Prop->Raw = (void *) xcalloc(1, Prop->RawLen); |
---|
136 | (void) memcpy(Prop->Raw, op->oprom_array, Prop->RawLen); |
---|
137 | |
---|
138 | /* |
---|
139 | * Now create a nice ASCII String for Value. |
---|
140 | * op->oprom_array points at opio.opio_buff where the results |
---|
141 | * really live. |
---|
142 | */ |
---|
143 | if (cp = DecodeVal(Prop->Key, op->oprom_array, op->oprom_size)) |
---|
144 | Prop->Value = strdup(cp); |
---|
145 | |
---|
146 | return(0); |
---|
147 | } |
---|
148 | |
---|
149 | /* |
---|
150 | * Create and copy a OBPprop_t |
---|
151 | */ |
---|
152 | static OBPprop_t *OBPcopyProp(old) |
---|
153 | OBPprop_t *old; |
---|
154 | { |
---|
155 | OBPprop_t *new; |
---|
156 | |
---|
157 | new = (OBPprop_t *) xmalloc(sizeof(OBPprop_t)); |
---|
158 | memcpy((void *)new, (void *)old, sizeof(OBPprop_t)); |
---|
159 | |
---|
160 | return(new); |
---|
161 | } |
---|
162 | |
---|
163 | /* |
---|
164 | * Get all OBP properties for the current OBP node and return |
---|
165 | * a table of the results. |
---|
166 | */ |
---|
167 | static OBPprop_t *OBPgetProps(obp_fd, OBPpropPtr) |
---|
168 | int obp_fd; |
---|
169 | OBPprop_t **OBPpropPtr; |
---|
170 | { |
---|
171 | static OBPio_t opio; |
---|
172 | struct openpromio *op; |
---|
173 | static OBPprop_t NewProp; |
---|
174 | OBPprop_t *PropTable; |
---|
175 | register OBPprop_t *PropPtr; |
---|
176 | |
---|
177 | if (OBPpropPtr) |
---|
178 | PropTable = *OBPpropPtr; |
---|
179 | else |
---|
180 | return((OBPprop_t *) NULL); |
---|
181 | |
---|
182 | op = &(opio.opio_oprom); |
---|
183 | memset((void *)opio.opio_buff, 0, sizeof(opio.opio_buff)); |
---|
184 | |
---|
185 | for ( ; ; ) { |
---|
186 | /* |
---|
187 | * Get next property |
---|
188 | */ |
---|
189 | op->oprom_size = sizeof(opio.opio_buff); |
---|
190 | if (ioctl(obp_fd, OPROMNXTPROP, op) < 0) { |
---|
191 | SImsg(SIM_GERR, "OBP ioctl OPROMNXTPROP failed: %s.", SYSERR); |
---|
192 | return((OBPprop_t *) NULL); |
---|
193 | } |
---|
194 | |
---|
195 | /* |
---|
196 | * We're done |
---|
197 | */ |
---|
198 | if (!op->oprom_size) |
---|
199 | break; |
---|
200 | |
---|
201 | (void) memset(&NewProp, 0, sizeof(NewProp)); |
---|
202 | NewProp.Key = strdup(op->oprom_array); |
---|
203 | |
---|
204 | /* |
---|
205 | * Set Value, Raw, RawLen |
---|
206 | */ |
---|
207 | (void) OBPsetPropVal(&NewProp, obp_fd); |
---|
208 | |
---|
209 | /* |
---|
210 | * Add this entry to the linked list. |
---|
211 | */ |
---|
212 | NewProp.Next = NULL; |
---|
213 | if (PropTable) { |
---|
214 | for (PropPtr = PropTable; PropPtr && PropPtr->Next; |
---|
215 | PropPtr = PropPtr->Next); |
---|
216 | PropPtr->Next = OBPcopyProp(&NewProp); |
---|
217 | } else |
---|
218 | PropTable = OBPcopyProp(&NewProp); |
---|
219 | } |
---|
220 | |
---|
221 | *OBPpropPtr = PropTable; |
---|
222 | |
---|
223 | return(PropTable); |
---|
224 | } |
---|
225 | |
---|
226 | /* |
---|
227 | * Get info about a CPU. |
---|
228 | * |
---|
229 | * CpuType is the type/model to lookup. |
---|
230 | * OBPprop is the OBP Property table for CpuType. |
---|
231 | * Results are stored in ModelPtr, VendorPtr, FreqPtr |
---|
232 | */ |
---|
233 | static int OBPgetCPUinfo(CpuType, OBPprop, ModelPtr, VendorPtr, FreqPtr) |
---|
234 | char *CpuType; |
---|
235 | OBPprop_t *OBPprop; |
---|
236 | char **ModelPtr; |
---|
237 | char **VendorPtr; |
---|
238 | long *FreqPtr; |
---|
239 | { |
---|
240 | long ClockFreq = 0; |
---|
241 | Define_t *Def; |
---|
242 | char *Str; |
---|
243 | char *Model = NULL; |
---|
244 | char *cp; |
---|
245 | |
---|
246 | Str = OBPfindPropVal(OBP_CLOCKFREQ, OBPprop, NULL, NULL); |
---|
247 | if (Str) |
---|
248 | ClockFreq = strtol(Str, (char **)NULL, 0); |
---|
249 | |
---|
250 | /* |
---|
251 | * No individual clock frequency, so we use the "global" |
---|
252 | * clock freqency that (hopefully) was set earlier. |
---|
253 | */ |
---|
254 | if (!ClockFreq) |
---|
255 | ClockFreq = CpuClockFreq; |
---|
256 | |
---|
257 | /* |
---|
258 | * Set the frequency we're using so our caller can use it. |
---|
259 | */ |
---|
260 | if (ClockFreq && FreqPtr) |
---|
261 | *FreqPtr = ClockFreq; |
---|
262 | |
---|
263 | /* |
---|
264 | * If CpuType is of form 'Foo,Bar' then use 'Foo' as the Vendor |
---|
265 | * and 'Bar' as the actual Model. |
---|
266 | */ |
---|
267 | if (cp = strchr(CpuType, ',')) { |
---|
268 | Model = strdup(cp + 1); |
---|
269 | Str = (char *) xmalloc(cp - CpuType); |
---|
270 | (void) strncpy(Str, CpuType, cp - CpuType); |
---|
271 | Str[cp - CpuType] = CNULL; |
---|
272 | *VendorPtr = Str; |
---|
273 | } |
---|
274 | |
---|
275 | /* |
---|
276 | * Scan the CPU types table looking for an entry that has |
---|
277 | * the same type name and the same clock frequency. |
---|
278 | */ |
---|
279 | for (Def = DefGetList(DL_CPU); Def; Def = Def->Next) { |
---|
280 | if (EQ(Def->KeyStr, CpuType)) { |
---|
281 | if ((Def->KeyNum == 0) || (Def->KeyNum == -1) || |
---|
282 | ((ClockFreq / MHERTZ) == Def->KeyNum)) |
---|
283 | *ModelPtr = Def->ValStr1; |
---|
284 | } |
---|
285 | } |
---|
286 | |
---|
287 | if (!*ModelPtr) { |
---|
288 | /* No special CPU Definetion was found, so use the OBP value */ |
---|
289 | if (Model) |
---|
290 | *ModelPtr = strdup(Model); /* Without Vendor Str */ |
---|
291 | else |
---|
292 | *ModelPtr = strdup(CpuType); |
---|
293 | } |
---|
294 | |
---|
295 | SImsg(SIM_DBG, "OBPgetCPUinfo(%s) Vendor=<%s> Model=<%s> Freq=%d", |
---|
296 | PRTS(CpuType), PRTS(*VendorPtr), PRTS(*ModelPtr), *FreqPtr); |
---|
297 | |
---|
298 | return(0); |
---|
299 | } |
---|
300 | |
---|
301 | /* |
---|
302 | * Get a nice informative string describing OBPprop information and |
---|
303 | * set the info into DevInfo. |
---|
304 | */ |
---|
305 | static void OBPsetOBPinfo(OBPprop, DevInfo) |
---|
306 | OBPprop_t *OBPprop; |
---|
307 | DevInfo_t *DevInfo; |
---|
308 | { |
---|
309 | char *ExpName = NULL; |
---|
310 | char *Val = NULL; |
---|
311 | Define_t *Def; |
---|
312 | |
---|
313 | /* |
---|
314 | * Try to see if this is one of the types of OBP info |
---|
315 | * that we want to use a more descriptive text than |
---|
316 | * the key itself. |
---|
317 | */ |
---|
318 | Def = DefGet(DL_OBP, OBPprop->Key, -1, 0); |
---|
319 | if (Def && Def->ValStr1) |
---|
320 | ExpName = Def->ValStr1; |
---|
321 | |
---|
322 | if (!ExpName) |
---|
323 | ExpName = ExpandKey(OBPprop->Key); |
---|
324 | |
---|
325 | if (!OBP_IS_BOOL(OBPprop) && OBPprop->Value) { |
---|
326 | if (EQ(OBPprop->Key, OBP_CLOCKFREQ)) |
---|
327 | Val = strdup(FreqStr(strtol(OBPprop->Value, |
---|
328 | (char **)NULL, 0))); |
---|
329 | else if (EQ(OBPprop->Key, OBP_ECACHESIZE) || |
---|
330 | EQ(OBPprop->Key, OBP_DCACHESIZE)) |
---|
331 | Val = GetSizeStr((Large_t) strtol(OBPprop->Value, |
---|
332 | (char **)NULL, 0), BYTES); |
---|
333 | else |
---|
334 | Val = OBPprop->Value; |
---|
335 | } |
---|
336 | |
---|
337 | if (OBP_IS_BOOL(OBPprop)) |
---|
338 | AddDevDesc(DevInfo, ExpName, "Has", DA_APPEND); |
---|
339 | else |
---|
340 | AddDevDesc(DevInfo, Val, ExpName, DA_APPEND); |
---|
341 | } |
---|
342 | |
---|
343 | /* |
---|
344 | * Fix an OBP node name to be compatable with the |
---|
345 | * conventions used in SunOS 5.x. |
---|
346 | * |
---|
347 | * i.e. All '/' characters are mapped to '_'. |
---|
348 | */ |
---|
349 | static char *OBPfixNodeName(string) |
---|
350 | char *string; |
---|
351 | { |
---|
352 | register char *cp; |
---|
353 | static char Buff[256]; |
---|
354 | |
---|
355 | (void) snprintf(Buff, sizeof(Buff), "%s", string); |
---|
356 | cp = Buff; |
---|
357 | while (cp = strchr(cp, '/')) |
---|
358 | *cp++ = '_'; |
---|
359 | |
---|
360 | return(Buff); |
---|
361 | } |
---|
362 | |
---|
363 | /* |
---|
364 | * Get (make) name of a CPU |
---|
365 | */ |
---|
366 | extern char *GetCpuName(ncpus, cpuid) |
---|
367 | int *ncpus; |
---|
368 | int cpuid; |
---|
369 | { |
---|
370 | static char Buff[32]; |
---|
371 | |
---|
372 | (void) snprintf(Buff, sizeof(Buff), "cpu%d", |
---|
373 | (cpuid >= 0) ? cpuid : (*ncpus)++); |
---|
374 | |
---|
375 | return(Buff); |
---|
376 | } |
---|
377 | |
---|
378 | /* |
---|
379 | * Probe a CPU using OBP info. |
---|
380 | */ |
---|
381 | extern DevInfo_t *OBPprobeCPU(ProbeData, Node, TreePtr, SearchNames) |
---|
382 | ProbeData_t *ProbeData; |
---|
383 | OBPnode_t *Node; |
---|
384 | DevInfo_t **TreePtr; |
---|
385 | char **SearchNames; |
---|
386 | { |
---|
387 | register OBPprop_t *PropPtr; |
---|
388 | DevInfo_t *DevInfo; |
---|
389 | DevInfo_t *fdev; |
---|
390 | static DevFind_t Find; |
---|
391 | register char *cp; |
---|
392 | register int i; |
---|
393 | static char Buff[256]; |
---|
394 | static int ncpus = 0; |
---|
395 | int cpuid = -1; |
---|
396 | char *CpuModel = NULL; |
---|
397 | char *CpuModelPart = NULL; |
---|
398 | char *CpuVendor = NULL; |
---|
399 | long ClockFreq = 0; |
---|
400 | char *ClockFreqStr = NULL; |
---|
401 | |
---|
402 | /* |
---|
403 | * This function may be called accidentally if a PROM/kernel node |
---|
404 | * called "cpu" is found. In such a case, we return immediately. |
---|
405 | * This function should only be called explicitly. |
---|
406 | */ |
---|
407 | if (ProbeData) |
---|
408 | return((DevInfo_t *) NULL); |
---|
409 | |
---|
410 | if (!(DevInfo = NewDevInfo(NULL))) |
---|
411 | return((DevInfo_t *)NULL); |
---|
412 | |
---|
413 | if (Debug) { |
---|
414 | (void) snprintf(Buff, sizeof(Buff), "Node ID is 0x%x", Node->NodeID); |
---|
415 | AddDevDesc(DevInfo, Buff, NULL, DA_APPEND); |
---|
416 | } |
---|
417 | |
---|
418 | for (PropPtr = Node->PropTable; PropPtr; PropPtr = PropPtr->Next) { |
---|
419 | /* |
---|
420 | * See if this is the CPU type |
---|
421 | */ |
---|
422 | if (EQ(OBP_NAME, PropPtr->Key)) { |
---|
423 | CpuModelPart = strdup(PropPtr->Value); |
---|
424 | OBPgetCPUinfo(PropPtr->Value, Node->PropTable, |
---|
425 | &CpuModel, &CpuVendor, &ClockFreq); |
---|
426 | continue; |
---|
427 | } else if (EQ(PropPtr->Key, OBP_CPUID) && PropPtr->Value) { |
---|
428 | cpuid = (int) strtol(PropPtr->Value, (char **)NULL, 0); |
---|
429 | } else if (EQ(PropPtr->Key, OBP_DEVTYPE) || |
---|
430 | EQ(PropPtr->Key, OBP_DEVTYPE2) || |
---|
431 | EQ(PropPtr->Key, OBP_CLOCKFREQ)) { |
---|
432 | continue; |
---|
433 | } |
---|
434 | |
---|
435 | OBPsetOBPinfo(PropPtr, DevInfo); |
---|
436 | } |
---|
437 | |
---|
438 | if (cp = GetCpuName(&ncpus, cpuid)) |
---|
439 | DevInfo->Name = strdup(cp); |
---|
440 | |
---|
441 | if (SearchNames && !SearchCheck(DevInfo->Name, SearchNames)) |
---|
442 | return((DevInfo_t *) NULL); |
---|
443 | |
---|
444 | if (CpuVendor) |
---|
445 | if (!(DevInfo->Vendor = GetVendorName(CpuVendor))) |
---|
446 | DevInfo->Vendor = CpuVendor; |
---|
447 | if (ClockFreq) { |
---|
448 | ClockFreqStr = FreqStr(ClockFreq); |
---|
449 | DevInfo->ModelDesc = strdup(ClockFreqStr); |
---|
450 | AddDevDesc(DevInfo, ClockFreqStr, "Speed", DA_INSERT); |
---|
451 | } |
---|
452 | if (CpuModel) |
---|
453 | DevInfo->Model = CpuModel; |
---|
454 | /* |
---|
455 | * This must be an unknown type of CPU |
---|
456 | */ |
---|
457 | if (!DevInfo->Model) |
---|
458 | DevInfo->Model = PrimeDesc(DevInfo); |
---|
459 | |
---|
460 | DevInfo->Type = DT_CPU; |
---|
461 | DevInfo->NodeID = Node->NodeID; |
---|
462 | |
---|
463 | /* |
---|
464 | * The rest of this function depends on CpuModel being available |
---|
465 | * so if it's not, return what we have so far. |
---|
466 | */ |
---|
467 | if (!CpuModel) |
---|
468 | return(DevInfo); |
---|
469 | |
---|
470 | /* |
---|
471 | * If no device by our name exists try to find a device |
---|
472 | * with a name which matches our CPU Model. This should |
---|
473 | * be the root device node. If so, make our device name |
---|
474 | * match the root device node name, so AddDevice() will |
---|
475 | * add our info to the root device node later. |
---|
476 | */ |
---|
477 | if (TreePtr && *TreePtr) { |
---|
478 | (void) memset(&Find, 0, sizeof(Find)); |
---|
479 | Find.Tree = *TreePtr; |
---|
480 | Find.NodeName = DevInfo->Name; |
---|
481 | if (!DevFind(&Find)) { |
---|
482 | Find.NodeName = CpuModelPart; |
---|
483 | fdev = DevFind(&Find); |
---|
484 | if (!fdev) { |
---|
485 | SImsg(SIM_DBG, "Cannot find CPU device <%s>", |
---|
486 | PRTS(CpuModelPart)); |
---|
487 | cp = OBPfixNodeName(CpuModelPart); |
---|
488 | if (!EQ(cp, CpuModelPart)) { |
---|
489 | Find.NodeName = cp; |
---|
490 | fdev = DevFind(&Find); |
---|
491 | } |
---|
492 | } else |
---|
493 | SImsg(SIM_DBG, "Found CPU device <%s>", PRTS(CpuModelPart)); |
---|
494 | if (fdev && !fdev->Master) |
---|
495 | DevInfo->Name = fdev->Name; |
---|
496 | } |
---|
497 | } |
---|
498 | |
---|
499 | if (CpuModelPart) |
---|
500 | (void) free(CpuModelPart); |
---|
501 | |
---|
502 | return(DevInfo); |
---|
503 | } |
---|
504 | |
---|
505 | /* |
---|
506 | * Get part description information using a model (part) name. |
---|
507 | */ |
---|
508 | static Define_t *OBPGetPart(PartName) |
---|
509 | char *PartName; |
---|
510 | { |
---|
511 | Define_t *PartList; |
---|
512 | register Define_t *Ptr; |
---|
513 | register int i; |
---|
514 | register char *cp; |
---|
515 | |
---|
516 | PartList = DefGetList(DL_PART); |
---|
517 | if (!PartList) { |
---|
518 | SImsg(SIM_DBG, "No Part List found."); |
---|
519 | return((Define_t *) NULL); |
---|
520 | } |
---|
521 | |
---|
522 | for (Ptr = PartList; Ptr; Ptr = Ptr->Next) { |
---|
523 | if (EQN(Ptr->KeyStr, PartName, strlen(Ptr->KeyStr))) |
---|
524 | return(Ptr); |
---|
525 | /* Try it without the manufacturer part of part name */ |
---|
526 | if ((cp = strchr(Ptr->KeyStr, ',')) && |
---|
527 | EQN(++cp, PartName, strlen(cp))) |
---|
528 | return(Ptr); |
---|
529 | } |
---|
530 | |
---|
531 | return((Define_t *) NULL); |
---|
532 | } |
---|
533 | |
---|
534 | /* |
---|
535 | * This is for sun4d and sun4u platforms. |
---|
536 | * |
---|
537 | * If this device has a board number, then we make a "fake" |
---|
538 | * device called OBP_SYSBOARD that we insert in between the |
---|
539 | * Device and it's logical/current Master. |
---|
540 | */ |
---|
541 | static void OBPsetBoard(DevInfo, OBPprop, BoardNum, TreePtr, SearchNames) |
---|
542 | DevInfo_t *DevInfo; |
---|
543 | OBPprop_t *OBPprop; |
---|
544 | int BoardNum; |
---|
545 | DevInfo_t **TreePtr; |
---|
546 | char **SearchNames; |
---|
547 | { |
---|
548 | static char BoardName[64]; |
---|
549 | static char Buff[128]; |
---|
550 | static DevFind_t Find; |
---|
551 | char *What; |
---|
552 | char *BoardType; |
---|
553 | register DevInfo_t *DevPtr; |
---|
554 | register DevInfo_t *SaveDev; |
---|
555 | register DevInfo_t *LastDev; |
---|
556 | register DevInfo_t *OldMaster = NULL; |
---|
557 | register DevInfo_t *Master = NULL; |
---|
558 | DevDefine_t *DevDefine = NULL; |
---|
559 | |
---|
560 | if (BoardNum < 0 || !DevInfo) |
---|
561 | return; |
---|
562 | |
---|
563 | (void) snprintf(BoardName, sizeof(BoardName), "%s%d", |
---|
564 | OBP_SYSBOARD, BoardNum); |
---|
565 | |
---|
566 | /* |
---|
567 | * Find the Old Master |
---|
568 | */ |
---|
569 | if (DevInfo->Master) { |
---|
570 | (void) memset(&Find, 0, sizeof(Find)); |
---|
571 | Find.Tree = *TreePtr; |
---|
572 | Find.NodeID = DevInfo->Master->NodeID; |
---|
573 | Find.NodeName = DevInfo->Master->Name; |
---|
574 | OldMaster = DevFind(&Find); |
---|
575 | } |
---|
576 | |
---|
577 | /* |
---|
578 | * If the Master (sysboard) device doesn't exit, create one. |
---|
579 | */ |
---|
580 | (void) memset(&Find, 0, sizeof(Find)); |
---|
581 | Find.Tree = *TreePtr; |
---|
582 | Find.NodeName = BoardName; |
---|
583 | if (!(Master = DevFind(&Find))) { |
---|
584 | Master = NewDevInfo(NULL); |
---|
585 | Master->Name = strdup(BoardName); |
---|
586 | Master->Unit = BoardNum; |
---|
587 | if (DevDefine = DevDefGet(OBP_SYSBOARD, 0, 0)) { |
---|
588 | Master->Model = DevDefine->Model; |
---|
589 | Master->ModelDesc = DevDefine->Desc; |
---|
590 | Master->Type = DevDefine->Type; |
---|
591 | } |
---|
592 | if (OldMaster) { |
---|
593 | Master->MasterName = OldMaster->Name; |
---|
594 | Master->Master = OldMaster; |
---|
595 | } |
---|
596 | AddDevice(Master, TreePtr, SearchNames); |
---|
597 | } |
---|
598 | |
---|
599 | /* |
---|
600 | * Insert sysboard between Device and it's logical Master. |
---|
601 | */ |
---|
602 | if (OldMaster) { |
---|
603 | Master->Master = OldMaster; |
---|
604 | |
---|
605 | /* |
---|
606 | * Find Device in OldMaster and remove it. |
---|
607 | */ |
---|
608 | SaveDev = NULL; |
---|
609 | for (DevPtr = OldMaster->Slaves, LastDev = DevPtr; DevPtr; |
---|
610 | LastDev = DevPtr, DevPtr = DevPtr->Next) { |
---|
611 | |
---|
612 | if (!EQ(DevPtr->Name, DevInfo->Name)) |
---|
613 | continue; |
---|
614 | |
---|
615 | SaveDev = DevPtr; |
---|
616 | LastDev->Next = DevPtr->Next; |
---|
617 | break; |
---|
618 | } |
---|
619 | |
---|
620 | /* |
---|
621 | * Add SaveDev back to new Master |
---|
622 | */ |
---|
623 | SaveDev->Next = NULL; |
---|
624 | if (Master->Slaves) { |
---|
625 | for (DevPtr = Master->Slaves; DevPtr && DevPtr->Next; |
---|
626 | DevPtr = DevPtr->Next); |
---|
627 | DevPtr->Next = SaveDev; |
---|
628 | } else |
---|
629 | Master->Slaves = SaveDev; |
---|
630 | } |
---|
631 | |
---|
632 | /* |
---|
633 | * Update Device |
---|
634 | */ |
---|
635 | if (Master) { |
---|
636 | DevInfo->MasterName = Master->Name; |
---|
637 | DevInfo->Master = Master; |
---|
638 | } |
---|
639 | |
---|
640 | /* |
---|
641 | * If this is an FHC device (sun4u), then try to figure out more |
---|
642 | * info about the type of board this is. |
---|
643 | */ |
---|
644 | if (EQN(DevInfo->Name, OBP_FHC, strlen(OBP_FHC))) { |
---|
645 | BoardType = OBPfindPropVal(OBP_BOARDTYPE, OBPprop, NULL, NULL); |
---|
646 | if (BoardType) { |
---|
647 | /* |
---|
648 | * There are different board types: |
---|
649 | * VALUE DESCRIPTION |
---|
650 | * mem CPU & Memory |
---|
651 | * cpu CPU & Memory |
---|
652 | * dual-sbus I/O |
---|
653 | * ? Graphics |
---|
654 | */ |
---|
655 | if (EQ(BoardType, "mem") || |
---|
656 | EQ(BoardType, "cpu")) |
---|
657 | What = "CPU & Memory"; |
---|
658 | else if (EQ(BoardType, "dual-sbus")) |
---|
659 | What = "Sbus I/O"; |
---|
660 | else |
---|
661 | What = NULL; |
---|
662 | if (What) { |
---|
663 | (void) snprintf(Buff, sizeof(Buff), "%s Board", What); |
---|
664 | Master->Model = strdup(Buff); |
---|
665 | } |
---|
666 | } |
---|
667 | } |
---|
668 | } |
---|
669 | |
---|
670 | /* |
---|
671 | * Decode memory string into number of MBYTES. |
---|
672 | */ |
---|
673 | static int OBPGetMemSize(MemStr) |
---|
674 | char *MemStr; |
---|
675 | { |
---|
676 | register char *cp; |
---|
677 | char *MemBuff; |
---|
678 | u_long Amt = 0; |
---|
679 | |
---|
680 | if (strchr(MemStr, '.')) { |
---|
681 | MemBuff = strdup(MemStr); |
---|
682 | for (cp = strtok(MemBuff, "."); cp; cp = strtok((char *)NULL, ".")) |
---|
683 | Amt += strtol(cp, (char **) NULL, 0); |
---|
684 | (void) free(MemBuff); |
---|
685 | } else |
---|
686 | Amt = strtol(MemStr, (char **) NULL, 0); |
---|
687 | |
---|
688 | return(Amt / MBYTES); |
---|
689 | } |
---|
690 | |
---|
691 | /* |
---|
692 | * Decode memory string into memory groups and add as a dev description. |
---|
693 | */ |
---|
694 | static void OBPSetMemGrps(DevInfo, MemStr) |
---|
695 | DevInfo_t *DevInfo; |
---|
696 | char *MemStr; |
---|
697 | { |
---|
698 | static char Buff[512]; |
---|
699 | register char *bPtr; |
---|
700 | register char *End; |
---|
701 | char Str[100]; |
---|
702 | register char *cp; |
---|
703 | char *MemBuff; |
---|
704 | int GrpNum = 0; |
---|
705 | |
---|
706 | if (!strchr(MemStr, '.')) |
---|
707 | return; |
---|
708 | |
---|
709 | Buff[0] = CNULL; |
---|
710 | bPtr = Buff; |
---|
711 | End = &Buff[sizeof(Buff)-1]; |
---|
712 | MemBuff = strdup(MemStr); |
---|
713 | for (cp = strtok(MemBuff, "."); cp && bPtr < End; |
---|
714 | cp = strtok((char *)NULL, ".")) { |
---|
715 | (void) snprintf(bPtr, sizeof(Buff)-(End-bPtr), "#%d=%s", |
---|
716 | GrpNum++, |
---|
717 | GetSizeStr((Large_t) |
---|
718 | strtol(cp, (char **) NULL, 0), BYTES)); |
---|
719 | if (bPtr != Buff) |
---|
720 | strcat(bPtr, ", "); |
---|
721 | bPtr += strlen(bPtr); |
---|
722 | } |
---|
723 | (void) free(MemBuff); |
---|
724 | |
---|
725 | AddDevDesc(DevInfo, Buff, "Memory Groups", DA_APPEND); |
---|
726 | } |
---|
727 | |
---|
728 | /* |
---|
729 | * Probe an OBP node. |
---|
730 | */ |
---|
731 | extern DevInfo_t *OBPprobe(Node, TreePtr, SearchNames) |
---|
732 | OBPnode_t *Node; |
---|
733 | DevInfo_t **TreePtr; |
---|
734 | char **SearchNames; |
---|
735 | { |
---|
736 | register OBPprop_t *PropPtr; |
---|
737 | DevInfo_t *DevInfo = NULL; |
---|
738 | DevInfo_t *ParentDevInfo; |
---|
739 | static DevFind_t Find; |
---|
740 | register char **cpp; |
---|
741 | register char *cp; |
---|
742 | static char Buff[128]; |
---|
743 | int BoardNum = -1; |
---|
744 | char *ObpModel = NULL; |
---|
745 | char *ObpModelBase = NULL; |
---|
746 | char *Vendor = NULL; |
---|
747 | Define_t *PartInfo = NULL; |
---|
748 | int MemSize = 0; |
---|
749 | |
---|
750 | /* |
---|
751 | * See if we can find the node by it's NodeID or NodeName. |
---|
752 | * NodeName works for the root "system" node and a few others. |
---|
753 | */ |
---|
754 | (void) memset(&Find, 0, sizeof(Find)); |
---|
755 | Find.Tree = *TreePtr; |
---|
756 | Find.NodeID = Node->NodeID; |
---|
757 | Find.NodeName = Node->Name; |
---|
758 | DevInfo = DevFind(&Find); |
---|
759 | if (!DevInfo) |
---|
760 | return((DevInfo_t *)NULL); |
---|
761 | |
---|
762 | /* |
---|
763 | * Get all the info we need |
---|
764 | */ |
---|
765 | for (PropPtr = Node->PropTable; PropPtr; PropPtr = PropPtr->Next) { |
---|
766 | /* |
---|
767 | * Skip these |
---|
768 | */ |
---|
769 | if (EQ(PropPtr->Key, OBP_NAME)) |
---|
770 | continue; |
---|
771 | else if (EQ(PropPtr->Key, OBP_MODEL)) |
---|
772 | ObpModel = PropPtr->Value; |
---|
773 | else if (EQ(PropPtr->Key, OBP_BOARD) && PropPtr->Value) |
---|
774 | BoardNum = strtol(PropPtr->Value, (char **) NULL, 0); |
---|
775 | else if (EQ(PropPtr->Key, OBP_SIZE) && |
---|
776 | EQ(Node->Name, OBP_MEMUNIT)) { |
---|
777 | MemSize = OBPGetMemSize(PropPtr->Value); |
---|
778 | OBPSetMemGrps(DevInfo, PropPtr->Value); |
---|
779 | /* |
---|
780 | * If this node has a key="keyboard" and is _NOT_ the |
---|
781 | * node called "aliases", then this is the kbd parent |
---|
782 | */ |
---|
783 | } else if (EQ(PropPtr->Key, OBP_KEYBOARD) && |
---|
784 | !EQ(Node->Name, OBP_ALIASES)) { |
---|
785 | DevInfo->Slaves = ProbeKbd((DevInfo_t **)NULL); |
---|
786 | } |
---|
787 | |
---|
788 | OBPsetOBPinfo(PropPtr, DevInfo); |
---|
789 | } |
---|
790 | |
---|
791 | /* |
---|
792 | * Handle special cases |
---|
793 | */ |
---|
794 | if (MemSize && DevInfo->Model) { |
---|
795 | (void) snprintf(Buff, sizeof(Buff), "%d MB %s", |
---|
796 | MemSize, DevInfo->Model); |
---|
797 | DevInfo->Model = strdup(Buff); |
---|
798 | } |
---|
799 | if (BoardNum >= 0) |
---|
800 | OBPsetBoard(DevInfo, Node->PropTable, BoardNum, TreePtr, SearchNames); |
---|
801 | |
---|
802 | /* |
---|
803 | * Add information to existing Device. |
---|
804 | */ |
---|
805 | if (ObpModel) { |
---|
806 | /* |
---|
807 | * If ObpModel is of form 'Foo,Bar' then use 'Foo' as the Vendor |
---|
808 | * and 'Bar' as the actual Model. |
---|
809 | */ |
---|
810 | if (cp = strchr(ObpModel, ',')) { |
---|
811 | ObpModelBase = cp + 1; |
---|
812 | Vendor = (char *) xmalloc(cp - ObpModel); |
---|
813 | (void) strncpy(Vendor, ObpModel, cp - ObpModel); |
---|
814 | Vendor[cp - ObpModel] = CNULL; |
---|
815 | if (cp = GetVendorName(Vendor)) { |
---|
816 | DevInfo->Vendor = cp; |
---|
817 | (void) free(Vendor); |
---|
818 | } else |
---|
819 | DevInfo->Vendor = Vendor; |
---|
820 | } |
---|
821 | |
---|
822 | /* |
---|
823 | * Now lookup the Part (including the Vendor part if any) |
---|
824 | */ |
---|
825 | PartInfo = OBPGetPart(ObpModel); |
---|
826 | if (PartInfo) { |
---|
827 | DevInfo->Model = PartInfo->ValStr1; |
---|
828 | AddDevDesc(DevInfo, PartInfo->ValStr2, NULL, DA_INSERT|DA_PRIME); |
---|
829 | } else if (!DevInfo->Model) |
---|
830 | DevInfo->Model = (ObpModelBase) ? ObpModelBase : ObpModel; |
---|
831 | } |
---|
832 | |
---|
833 | return((DevInfo_t *)NULL); |
---|
834 | } |
---|
835 | |
---|
836 | /* |
---|
837 | * Check over an OBP device. |
---|
838 | */ |
---|
839 | static void OBPdevCheck(Node, TreePtr, SearchNames) |
---|
840 | OBPnode_t *Node; |
---|
841 | DevInfo_t **TreePtr; |
---|
842 | char **SearchNames; |
---|
843 | { |
---|
844 | register OBPprop_t *PropPtr; |
---|
845 | static int first = TRUE; |
---|
846 | DevDefine_t *DevDefine = NULL; |
---|
847 | DevType_t *DevType = NULL; |
---|
848 | ClassType_t *ClassType = NULL; |
---|
849 | DevInfo_t *DevInfo = NULL; |
---|
850 | DevInfo_t *master = NULL; |
---|
851 | static DevFind_t Find; |
---|
852 | |
---|
853 | /* |
---|
854 | * Iterate over all the properties looking for interesting properties |
---|
855 | * or until we find the device type. If the device type is one which |
---|
856 | * we found in our probe list, go ahead and probe it. |
---|
857 | */ |
---|
858 | for (PropPtr = Node->PropTable; PropPtr; PropPtr = PropPtr->Next) { |
---|
859 | SImsg(SIM_DBG, "OBPdevCheck: NodeID 0x%x <%s> = <%s> (0x%x)", |
---|
860 | Node->NodeID, PropPtr->Key, |
---|
861 | (PropPtr->Value) ? PropPtr->Value : "", |
---|
862 | (PropPtr->Value) ? atol(PropPtr->Value) : 0); |
---|
863 | |
---|
864 | /* |
---|
865 | * If this is the first node and this property is the Clock Frequency |
---|
866 | * then save it for later use by the individual CPUs. |
---|
867 | */ |
---|
868 | if (first && !CpuClockFreq && EQ(PropPtr->Key, OBP_CLOCKFREQ) && |
---|
869 | PropPtr->Value) |
---|
870 | CpuClockFreq = strtol(PropPtr->Value, (char **)NULL, 0); |
---|
871 | |
---|
872 | if (EQ(PropPtr->Key, OBP_DEVTYPE) || EQ(PropPtr->Key, OBP_DEVTYPE2)) { |
---|
873 | /* |
---|
874 | * OBP isn't consistant in what OBP_DEVTYPE really is so |
---|
875 | * we do multiple lookups |
---|
876 | */ |
---|
877 | DevDefine = DevDefGet(PropPtr->Value, 0, 0); |
---|
878 | DevType = TypeGetByName(PropPtr->Value); |
---|
879 | ClassType = ClassTypeGetByName(PropPtr->Value); |
---|
880 | } |
---|
881 | } |
---|
882 | |
---|
883 | SImsg(SIM_DBG, |
---|
884 | "OBPdevCheck: NodeID 0x%x Name = <%s> DevDefine.Name = <%s>", |
---|
885 | Node->NodeID, (Node->Name[0]) ? Node->Name : "", |
---|
886 | (DevDefine && DevDefine->Name) ? DevDefine->Name : ""); |
---|
887 | |
---|
888 | /* |
---|
889 | * We use DevDefine->Probe for our own internal (obp.c) use so we |
---|
890 | * need to make sure we only call the right Probe functions |
---|
891 | */ |
---|
892 | if (DevDefine && DevDefine->Probe == OBPprobeCPU) |
---|
893 | DevInfo = OBPprobeCPU((ProbeData_t *) NULL, |
---|
894 | Node, TreePtr, SearchNames); |
---|
895 | |
---|
896 | if (!DevInfo) |
---|
897 | DevInfo = OBPprobe(Node, TreePtr, SearchNames); |
---|
898 | |
---|
899 | if (DevInfo) { |
---|
900 | /* |
---|
901 | * Find or create of Master |
---|
902 | */ |
---|
903 | if (TreePtr && !DevInfo->Master) { |
---|
904 | (void) memset(&Find, 0, sizeof(Find)); |
---|
905 | Find.NodeID = Node->ParentID; |
---|
906 | Find.Tree = *TreePtr; |
---|
907 | master = DevFind(&Find); |
---|
908 | if (!master && Node->ParentName) { |
---|
909 | master = NewDevInfo(NULL); |
---|
910 | master->Name = strdup(Node->ParentName); |
---|
911 | master->NodeID = Node->ParentID; |
---|
912 | } |
---|
913 | DevInfo->Master = master; |
---|
914 | } |
---|
915 | DevInfo->NodeID = Node->NodeID; |
---|
916 | if (DevType && !DevInfo->Type) |
---|
917 | DevInfo->Type = DevType->Type; |
---|
918 | if (ClassType && !DevInfo->ClassType) |
---|
919 | DevInfo->ClassType = ClassType->Type; |
---|
920 | AddDevice(DevInfo, TreePtr, SearchNames); |
---|
921 | } |
---|
922 | |
---|
923 | first = FALSE; |
---|
924 | } |
---|
925 | |
---|
926 | /* |
---|
927 | * Traverse OBP device tree and build device info |
---|
928 | */ |
---|
929 | static void OBPdevTraverse(Node, TreePtr, SearchNames) |
---|
930 | OBPnode_t *Node; |
---|
931 | DevInfo_t **TreePtr; |
---|
932 | char **SearchNames; |
---|
933 | { |
---|
934 | OBPdevCheck(Node, TreePtr, SearchNames); |
---|
935 | |
---|
936 | if (Node->Next) |
---|
937 | OBPdevTraverse(Node->Next, TreePtr, SearchNames); |
---|
938 | |
---|
939 | if (Node->Children) |
---|
940 | OBPdevTraverse(Node->Children, TreePtr, SearchNames); |
---|
941 | } |
---|
942 | |
---|
943 | /* |
---|
944 | * Find an OBP node in Node with an ID of NodeID. |
---|
945 | */ |
---|
946 | extern OBPnode_t *OBPfindNodeByID(Node, NodeID) |
---|
947 | OBPnode_t *Node; |
---|
948 | OBPnodeid_t NodeID; |
---|
949 | { |
---|
950 | OBPnode_t *Found = NULL; |
---|
951 | |
---|
952 | if (!Node) |
---|
953 | Node = OBPnodeTree; |
---|
954 | |
---|
955 | if (!Node) |
---|
956 | return((OBPnode_t *) NULL); |
---|
957 | |
---|
958 | if (Node->NodeID == NodeID) |
---|
959 | return(Node); |
---|
960 | |
---|
961 | if (Node->Children) |
---|
962 | if (Found = OBPfindNodeByID(Node->Children, NodeID)) |
---|
963 | return(Found); |
---|
964 | |
---|
965 | if (Node->Next) |
---|
966 | if (Found = OBPfindNodeByID(Node->Next, NodeID)) |
---|
967 | return(Found); |
---|
968 | |
---|
969 | return((OBPnode_t *) NULL); |
---|
970 | } |
---|
971 | |
---|
972 | /* |
---|
973 | * Find an OBP node in Node with a device type of MatchType |
---|
974 | */ |
---|
975 | static OBPnode_t *OBPfindNodeByType(Node, MatchType) |
---|
976 | OBPnode_t *Node; |
---|
977 | char *MatchType; |
---|
978 | { |
---|
979 | OBPnode_t *Found = NULL; |
---|
980 | char *NodeType; |
---|
981 | |
---|
982 | if (!Node) |
---|
983 | return((OBPnode_t *) NULL); |
---|
984 | |
---|
985 | if ((NodeType = OBPfindPropVal(OBP_DEVTYPE, Node->PropTable, NULL, NULL)) |
---|
986 | || |
---|
987 | (NodeType = OBPfindPropVal(OBP_DEVTYPE2, Node->PropTable, NULL, NULL))) |
---|
988 | if (EQ(NodeType, MatchType)) |
---|
989 | return(Node); |
---|
990 | |
---|
991 | if (Node->Children) |
---|
992 | if (Found = OBPfindNodeByType(Node->Children, MatchType)) |
---|
993 | return(Found); |
---|
994 | |
---|
995 | if (Node->Next) |
---|
996 | if (Found = OBPfindNodeByType(Node->Next, MatchType)) |
---|
997 | return(Found); |
---|
998 | |
---|
999 | return((OBPnode_t *) NULL); |
---|
1000 | } |
---|
1001 | |
---|
1002 | /* |
---|
1003 | * Find an OBP node in Node with a name of Name. |
---|
1004 | */ |
---|
1005 | static OBPnode_t *OBPfindNodeByName(Node, Name) |
---|
1006 | OBPnode_t *Node; |
---|
1007 | char *Name; |
---|
1008 | { |
---|
1009 | OBPnode_t *Found = NULL; |
---|
1010 | char *cp1; |
---|
1011 | char *cp2; |
---|
1012 | |
---|
1013 | if (!Node) |
---|
1014 | return((OBPnode_t *) NULL); |
---|
1015 | |
---|
1016 | if (EQ(Name, Node->Name)) |
---|
1017 | return(Node); |
---|
1018 | |
---|
1019 | /* |
---|
1020 | * Try a match by stripping out any commas found in the names. |
---|
1021 | */ |
---|
1022 | if (cp1 = strchr(Name, ',')) |
---|
1023 | ++cp1; |
---|
1024 | else |
---|
1025 | cp1 = Name; |
---|
1026 | if (cp2 = strchr(Node->Name, ',')) |
---|
1027 | ++cp2; |
---|
1028 | else |
---|
1029 | cp2 = Node->Name; |
---|
1030 | if (EQ(cp1, cp2)) |
---|
1031 | return(Node); |
---|
1032 | |
---|
1033 | if (Node->Children) |
---|
1034 | if (Found = OBPfindNodeByName(Node->Children, Name)) |
---|
1035 | return(Found); |
---|
1036 | |
---|
1037 | if (Node->Next) |
---|
1038 | if (Found = OBPfindNodeByName(Node->Next, Name)) |
---|
1039 | return(Found); |
---|
1040 | |
---|
1041 | return((OBPnode_t *) NULL); |
---|
1042 | } |
---|
1043 | |
---|
1044 | /* |
---|
1045 | * Get the OBP property entry which matches "Key" |
---|
1046 | * Look for Key in Table, by NodeID, or by NodeName (whichever is |
---|
1047 | * not NULL). |
---|
1048 | */ |
---|
1049 | extern OBPprop_t *OBPfindProp(Key, Table, NodeID, NodeName) |
---|
1050 | char *Key; |
---|
1051 | OBPprop_t *Table; |
---|
1052 | OBPnodeid_t NodeID; |
---|
1053 | char *NodeName; |
---|
1054 | { |
---|
1055 | register OBPprop_t *Ptr; |
---|
1056 | OBPprop_t *PropTable = NULL; |
---|
1057 | OBPnode_t *Node; |
---|
1058 | |
---|
1059 | if (Table) |
---|
1060 | PropTable = Table; |
---|
1061 | else if (NodeID) { |
---|
1062 | if (!OBPnodeTree) |
---|
1063 | OBPbuildNodeTree(&OBPnodeTree); |
---|
1064 | Node = OBPfindNodeByID(OBPnodeTree, NodeID); |
---|
1065 | if (Node) |
---|
1066 | PropTable = Node->PropTable; |
---|
1067 | } else if (NodeName) { |
---|
1068 | if (!OBPnodeTree) |
---|
1069 | OBPbuildNodeTree(&OBPnodeTree); |
---|
1070 | Node = OBPfindNodeByName(OBPnodeTree, NodeName); |
---|
1071 | if (Node) |
---|
1072 | PropTable = Node->PropTable; |
---|
1073 | } else |
---|
1074 | return((OBPprop_t *) NULL); |
---|
1075 | |
---|
1076 | /* |
---|
1077 | * See if this node has it's own clock frequency |
---|
1078 | */ |
---|
1079 | for (Ptr = PropTable; Ptr; Ptr = Ptr->Next) |
---|
1080 | if (Ptr->Key[0] && EQ(Ptr->Key, Key)) |
---|
1081 | return(Ptr); |
---|
1082 | |
---|
1083 | return((OBPprop_t *) NULL); |
---|
1084 | } |
---|
1085 | |
---|
1086 | /* |
---|
1087 | * Front-end to OBPfindProp() |
---|
1088 | */ |
---|
1089 | extern char *OBPfindPropVal(Key, Table, NodeID, NodeName) |
---|
1090 | char *Key; |
---|
1091 | OBPprop_t *Table; |
---|
1092 | OBPnodeid_t NodeID; |
---|
1093 | char *NodeName; |
---|
1094 | { |
---|
1095 | OBPprop_t *Prop; |
---|
1096 | |
---|
1097 | if (Prop = OBPfindProp(Key, Table, NodeID, NodeName)) |
---|
1098 | return(Prop->Value); |
---|
1099 | else |
---|
1100 | return((char *) NULL); |
---|
1101 | } |
---|
1102 | |
---|
1103 | /* |
---|
1104 | * Traverse tree of OBP I/O nodes |
---|
1105 | */ |
---|
1106 | static int OBPnodeTraverse(NodeTree, ParentID, ParentName, NodeID, obp_fd) |
---|
1107 | OBPnode_t **NodeTree; |
---|
1108 | OBPnodeid_t ParentID; |
---|
1109 | char *ParentName; |
---|
1110 | OBPnodeid_t NodeID; |
---|
1111 | int obp_fd; |
---|
1112 | { |
---|
1113 | OBPnodeid_t NewID; |
---|
1114 | OBPnode_t *NewNode; |
---|
1115 | register OBPnode_t *NodePtr; |
---|
1116 | register OBPnode_t *Master; |
---|
1117 | |
---|
1118 | NewNode = (OBPnode_t *) xcalloc(1, sizeof(OBPnode_t)); |
---|
1119 | NewNode->NodeID = NodeID; |
---|
1120 | NewNode->ParentID = ParentID; |
---|
1121 | NewNode->ParentName = ParentName; |
---|
1122 | if (OBPgetProps(obp_fd, &(NewNode->PropTable))) |
---|
1123 | NewNode->Name = OBPfindPropVal(OBP_NAME, NewNode->PropTable, |
---|
1124 | NULL, NULL); |
---|
1125 | |
---|
1126 | /* |
---|
1127 | * Add new node to NodeTree |
---|
1128 | */ |
---|
1129 | Master = OBPfindNodeByID(*NodeTree, ParentID); |
---|
1130 | if (Master) { |
---|
1131 | if (Master->Children) { |
---|
1132 | for (NodePtr = Master->Children; NodePtr && NodePtr->Next; |
---|
1133 | NodePtr = NodePtr->Next); |
---|
1134 | NodePtr->Next = NewNode; |
---|
1135 | } else |
---|
1136 | Master->Children = NewNode; |
---|
1137 | } else |
---|
1138 | *NodeTree = NewNode; |
---|
1139 | |
---|
1140 | /* |
---|
1141 | * Traverse Children and Peers (Next) |
---|
1142 | */ |
---|
1143 | if (NewID = OBPnodeNext(NodeID, obp_fd, OPROMCHILD)) |
---|
1144 | OBPnodeTraverse(NodeTree, NewNode->NodeID, NewNode->Name, |
---|
1145 | NewID, obp_fd); |
---|
1146 | if (NewID = OBPnodeNext(NodeID, obp_fd, OPROMNEXT)) |
---|
1147 | OBPnodeTraverse(NodeTree, ParentID, ParentName, NewID, obp_fd); |
---|
1148 | |
---|
1149 | return(0); |
---|
1150 | } |
---|
1151 | |
---|
1152 | /* |
---|
1153 | * Build tree of OBP nodes based on what we find using I/O calls |
---|
1154 | * to the OBP device. |
---|
1155 | */ |
---|
1156 | extern int OBPbuildNodeTree(NodeTree) |
---|
1157 | OBPnode_t **NodeTree; |
---|
1158 | { |
---|
1159 | int obp_fd; |
---|
1160 | int status; |
---|
1161 | |
---|
1162 | if (!NodeTree) { |
---|
1163 | SImsg(SIM_DBG, "OBPbuildeNodeTree: NULL NodeTree Ptr."); |
---|
1164 | return(-1); |
---|
1165 | } |
---|
1166 | |
---|
1167 | /* |
---|
1168 | * Note: Only one process at a time can open _PATH_OPENPROM. |
---|
1169 | */ |
---|
1170 | if ((obp_fd = open(_PATH_OPENPROM, O_RDONLY)) < 0) { |
---|
1171 | SImsg(SIM_GERR, "Cannot open \"%s\": %s.", _PATH_OPENPROM, SYSERR); |
---|
1172 | return(-1); |
---|
1173 | } |
---|
1174 | |
---|
1175 | status = OBPnodeTraverse(NodeTree, (OBPnodeid_t) 0, (char *) NULL, |
---|
1176 | OBPnodeNext((OBPnodeid_t) 0, obp_fd, OPROMNEXT), |
---|
1177 | obp_fd); |
---|
1178 | |
---|
1179 | (void) close(obp_fd); |
---|
1180 | |
---|
1181 | if (Debug && NodeTree && *NodeTree) |
---|
1182 | OBPprintInfo(*NodeTree); |
---|
1183 | |
---|
1184 | return(status); |
---|
1185 | } |
---|
1186 | |
---|
1187 | /* |
---|
1188 | * Build device tree from OBP device. |
---|
1189 | */ |
---|
1190 | extern int OBPbuild(TreePtr, SearchNames) |
---|
1191 | DevInfo_t **TreePtr; |
---|
1192 | char **SearchNames; |
---|
1193 | { |
---|
1194 | int status = 0; |
---|
1195 | |
---|
1196 | /* |
---|
1197 | * Build the OBP Node Tree if it hasn't been done already. |
---|
1198 | */ |
---|
1199 | if (!OBPnodeTree) { |
---|
1200 | status = OBPbuildNodeTree(&OBPnodeTree); |
---|
1201 | if (status != 0) |
---|
1202 | return(status); |
---|
1203 | } |
---|
1204 | |
---|
1205 | /* |
---|
1206 | * Build the device tree by walking the OBP Node Tree |
---|
1207 | */ |
---|
1208 | OBPdevTraverse(*OBPnodeTree, TreePtr, SearchNames); |
---|
1209 | |
---|
1210 | return(status); |
---|
1211 | } |
---|
1212 | |
---|
1213 | /* |
---|
1214 | * Get the "ROM Version" by querying the OBP |
---|
1215 | */ |
---|
1216 | extern char *OBPgetRomVersion() |
---|
1217 | { |
---|
1218 | static char Version[OPROMMAXPARAM]; |
---|
1219 | #if defined(OPROMGETVERSION) |
---|
1220 | int obp_fd; |
---|
1221 | struct openpromio *op; |
---|
1222 | static OBPio_t opio; |
---|
1223 | |
---|
1224 | /* |
---|
1225 | * Note: Only one process at a time can open _PATH_OPENPROM. |
---|
1226 | */ |
---|
1227 | if ((obp_fd = open(_PATH_OPENPROM, O_RDONLY)) < 0) { |
---|
1228 | SImsg(SIM_GERR, "Cannot open \"%s\": %s.", _PATH_OPENPROM, SYSERR); |
---|
1229 | return((char *) NULL); |
---|
1230 | } |
---|
1231 | |
---|
1232 | op = &(opio.opio_oprom); |
---|
1233 | op->oprom_size = sizeof(opio.opio_buff); |
---|
1234 | |
---|
1235 | if (ioctl(obp_fd, OPROMGETVERSION, op) < 0) { |
---|
1236 | SImsg(SIM_GERR, "OBP ioctl OPROMGETVERSION failed: %s", SYSERR); |
---|
1237 | return((char *) NULL); |
---|
1238 | } |
---|
1239 | (void) close(obp_fd); |
---|
1240 | |
---|
1241 | strcpy(Version, op->oprom_array); |
---|
1242 | #endif /* OPROMGETVERSION */ |
---|
1243 | |
---|
1244 | return((Version[0]) ? Version : (char *) NULL); |
---|
1245 | } |
---|
1246 | |
---|
1247 | /* |
---|
1248 | * Get sub system model variables |
---|
1249 | */ |
---|
1250 | extern char *OBPsubSysGetVar(Variable, Params) |
---|
1251 | char *Variable; |
---|
1252 | Opaque_t Params; |
---|
1253 | { |
---|
1254 | static char *Banner; |
---|
1255 | static int CPUspeed = 0; |
---|
1256 | static int ClockFreq = 0; |
---|
1257 | register char *cp; |
---|
1258 | register char *End; |
---|
1259 | SubSysVar_t *SubSysVar; |
---|
1260 | OBPnode_t *OBPtree; |
---|
1261 | |
---|
1262 | SubSysVar = (SubSysVar_t *) Params; |
---|
1263 | SubSysVar->IntVal = 0; |
---|
1264 | SubSysVar->StrVal = NULL; |
---|
1265 | OBPtree = SubSysVar->OBPtree; |
---|
1266 | |
---|
1267 | if (EQ(Variable, "BannerName")) { |
---|
1268 | Banner = OBPfindPropVal(OBP_BANNERNAME, |
---|
1269 | OBPtree->PropTable, NULL, NULL); |
---|
1270 | if (Banner) { |
---|
1271 | End = &Banner[strlen(Banner)]; |
---|
1272 | if (cp = strchr(Banner, '-')) { |
---|
1273 | if (strncmp(cp, "-slot ", 6) == 0 && cp < End) |
---|
1274 | Banner = cp + 6; |
---|
1275 | else if (strncmp(cp, "-way ", 5) == 0 && cp < End) |
---|
1276 | Banner = cp + 5; |
---|
1277 | } |
---|
1278 | SubSysVar->StrVal = Banner; |
---|
1279 | return(Banner); |
---|
1280 | } |
---|
1281 | } else if (EQ(Variable, "ClockFreq")) { |
---|
1282 | if (!ClockFreq) { |
---|
1283 | cp = OBPfindPropVal(OBP_CLOCKFREQ, OBPtree->PropTable, NULL, NULL); |
---|
1284 | if (cp) |
---|
1285 | ClockFreq = (int) ((long)atoi(cp) / (long)MHERTZ); |
---|
1286 | else |
---|
1287 | return((char *) NULL); |
---|
1288 | } |
---|
1289 | SubSysVar->IntVal = ClockFreq; |
---|
1290 | SubSysVar->StrVal = itoa(ClockFreq); |
---|
1291 | return(SubSysVar->StrVal); |
---|
1292 | } else if (EQ(Variable, "NumCPU")) { |
---|
1293 | if (cp = GetNumCpu()) { |
---|
1294 | SubSysVar->IntVal = atoi(cp); |
---|
1295 | SubSysVar->StrVal = cp; |
---|
1296 | } |
---|
1297 | return(cp); |
---|
1298 | } else if (EQ(Variable, "CPUspeed")) { |
---|
1299 | if (!CPUspeed) |
---|
1300 | CPUspeed = OBPgetCPUspeed(OBPnodeTree); |
---|
1301 | SubSysVar->IntVal = CPUspeed; |
---|
1302 | SubSysVar->StrVal = itoa(CPUspeed); |
---|
1303 | return(SubSysVar->StrVal); |
---|
1304 | } else { |
---|
1305 | SImsg(SIM_UNKN, "OBPsubSysGetVar: Unknown variable `%s'", Variable); |
---|
1306 | } |
---|
1307 | |
---|
1308 | return((char *) NULL); |
---|
1309 | } |
---|
1310 | |
---|
1311 | /* |
---|
1312 | * Get the clock frequency from the OBP property table. |
---|
1313 | */ |
---|
1314 | static int OBPgetCPUclockfreq(PropTable) |
---|
1315 | OBPprop_t *PropTable; |
---|
1316 | { |
---|
1317 | char *ClockStr; |
---|
1318 | long ClockFreq; |
---|
1319 | |
---|
1320 | ClockStr = OBPfindPropVal(OBP_CLOCKFREQ, PropTable, NULL, NULL); |
---|
1321 | if (!ClockStr) { |
---|
1322 | SImsg(SIM_DBG, "OBPgetCPUclockfreq: Could not find CPU clockfreq."); |
---|
1323 | return(0); |
---|
1324 | } |
---|
1325 | ClockFreq = strtol(ClockStr, (char **)NULL, 0); |
---|
1326 | |
---|
1327 | if (ClockFreq > MHERTZ) |
---|
1328 | return((int) (ClockFreq / MHERTZ)); |
---|
1329 | else |
---|
1330 | return((int) ClockFreq); |
---|
1331 | } |
---|
1332 | |
---|
1333 | /* |
---|
1334 | * Get the speed of any CPU (they should all be the same). |
---|
1335 | */ |
---|
1336 | static int OBPgetCPUspeed(NodeTree) |
---|
1337 | OBPnode_t *NodeTree; |
---|
1338 | { |
---|
1339 | OBPnode_t *Node; |
---|
1340 | int Speed; |
---|
1341 | |
---|
1342 | /* |
---|
1343 | * First try to find a CPU node. |
---|
1344 | */ |
---|
1345 | Node = OBPfindNodeByType(NodeTree, OBP_CPU); |
---|
1346 | if (Node) { |
---|
1347 | Speed = OBPgetCPUclockfreq(Node->PropTable); |
---|
1348 | if (Speed) |
---|
1349 | return(Speed); |
---|
1350 | } else { |
---|
1351 | SImsg(SIM_DBG, "OBPgetCPUspeed: Could not find any CPU nodes."); |
---|
1352 | } |
---|
1353 | |
---|
1354 | /* |
---|
1355 | * Some machines have the clock frequency in the root node. |
---|
1356 | */ |
---|
1357 | Speed = OBPgetCPUclockfreq(NodeTree->PropTable); |
---|
1358 | if (Speed) |
---|
1359 | return(Speed); |
---|
1360 | else |
---|
1361 | SImsg(SIM_DBG, "OBPgetCPUspeed: No clockfreq in root Node."); |
---|
1362 | |
---|
1363 | return(0); |
---|
1364 | } |
---|
1365 | |
---|
1366 | /* |
---|
1367 | * Set Conditionals. |
---|
1368 | * Conditions are set in SubSysDef->Conditions. |
---|
1369 | * If String is of form 'key=val', break apart and set Conditions. |
---|
1370 | * If String is of form 'string' (no '=') and DefaultKey is set, do |
---|
1371 | * backwards compatibility. |
---|
1372 | */ |
---|
1373 | Condition_t *SetCondition(SubSysDef, String, DefaultKey) |
---|
1374 | Define_t *SubSysDef; |
---|
1375 | char *String; |
---|
1376 | char *DefaultKey; |
---|
1377 | { |
---|
1378 | register char *cp; |
---|
1379 | register char *StrKey = NULL; |
---|
1380 | register char *StrVal = NULL; |
---|
1381 | Condition_t *Cond = NULL; |
---|
1382 | static Condition_t *LastCon; |
---|
1383 | static Define_t *LastSubSysDef; |
---|
1384 | |
---|
1385 | /* |
---|
1386 | * See if this is 'key=val' |
---|
1387 | */ |
---|
1388 | cp = strchr(String, '='); |
---|
1389 | if (!cp) { |
---|
1390 | if (DefaultKey) { |
---|
1391 | /* |
---|
1392 | * Do backwards compatibility |
---|
1393 | */ |
---|
1394 | StrKey = DefaultKey; |
---|
1395 | StrVal = String; |
---|
1396 | } else |
---|
1397 | return((Condition_t *) NULL); |
---|
1398 | } else |
---|
1399 | *cp = CNULL; |
---|
1400 | |
---|
1401 | /* |
---|
1402 | * If we've changed to a new SubSysDef, invalidate LastCon |
---|
1403 | */ |
---|
1404 | if (LastSubSysDef && LastSubSysDef != SubSysDef) |
---|
1405 | LastCon = NULL; |
---|
1406 | LastSubSysDef = SubSysDef; |
---|
1407 | |
---|
1408 | Cond = (Condition_t *) xcalloc(1, sizeof(Condition_t)); |
---|
1409 | if (StrKey) |
---|
1410 | Cond->Key = StrKey; |
---|
1411 | else |
---|
1412 | Cond->Key = String; |
---|
1413 | if (StrVal) { |
---|
1414 | Cond->StrVal = StrVal; |
---|
1415 | Cond->IntVal = atoi(StrVal); |
---|
1416 | } else if (++cp) { |
---|
1417 | Cond->StrVal = cp; |
---|
1418 | Cond->IntVal = atoi(cp); |
---|
1419 | } |
---|
1420 | |
---|
1421 | /* |
---|
1422 | * Add to end of linked list. |
---|
1423 | */ |
---|
1424 | if (!SubSysDef->Conditions) |
---|
1425 | LastCon = SubSysDef->Conditions = Cond; |
---|
1426 | else { |
---|
1427 | if (LastCon) { |
---|
1428 | LastCon->Next = Cond; |
---|
1429 | LastCon = Cond; |
---|
1430 | } else |
---|
1431 | LastCon = SubSysDef->Conditions = Cond; |
---|
1432 | } |
---|
1433 | |
---|
1434 | return(Cond); |
---|
1435 | } |
---|
1436 | |
---|
1437 | /* |
---|
1438 | * Get the sub system model type. |
---|
1439 | * i.e. "Ultra-1 140" |
---|
1440 | */ |
---|
1441 | extern char *OBPgetSubSysModel(SubSysDef) |
---|
1442 | Define_t *SubSysDef; |
---|
1443 | { |
---|
1444 | static char ErrBuff[128]; |
---|
1445 | static SubSysVar_t SubSysVar; |
---|
1446 | Condition_t *Conditions; |
---|
1447 | register Condition_t *Cond; |
---|
1448 | int AllMatch; |
---|
1449 | register int Argc; |
---|
1450 | char **Argv = NULL; |
---|
1451 | char *ExpandStr = NULL; |
---|
1452 | char *SubSysName = NULL; |
---|
1453 | int CPUspeedDelta = CPU_SPEED_DELTA; |
---|
1454 | char *cp; |
---|
1455 | register int i; |
---|
1456 | |
---|
1457 | if (SubSysDef->ValStr1) |
---|
1458 | ExpandStr = SubSysDef->ValStr1; |
---|
1459 | else |
---|
1460 | return((char *) NULL); |
---|
1461 | |
---|
1462 | /* |
---|
1463 | * Gather info needed for comparision and use in model name expansion |
---|
1464 | */ |
---|
1465 | if (!OBPnodeTree) |
---|
1466 | OBPbuildNodeTree(&OBPnodeTree); |
---|
1467 | SubSysVar.OBPtree = OBPnodeTree; |
---|
1468 | |
---|
1469 | if (SubSysDef->Conditions) { |
---|
1470 | /* Reset */ |
---|
1471 | for (Cond = SubSysDef->Conditions; Cond; Cond = Cond->Next) |
---|
1472 | Cond->Matches = FALSE; |
---|
1473 | } else { |
---|
1474 | /* Initialize */ |
---|
1475 | /* |
---|
1476 | * The first field (ValStr2) is what should be used normally. |
---|
1477 | * We default to CPUspeed if there is no 'key=val' for backwards |
---|
1478 | * compat. The remaining ValStr[3-5] parse are also for backwards |
---|
1479 | * compat. |
---|
1480 | */ |
---|
1481 | if (SubSysDef->ValStr2 && *SubSysDef->ValStr2) |
---|
1482 | if (Argc = StrToArgv(SubSysDef->ValStr2, " ", &Argv, NULL, 0)) |
---|
1483 | for (i = 0; i < Argc; ++i) |
---|
1484 | (void) SetCondition(SubSysDef, Argv[i], "CPUspeed"); |
---|
1485 | if (SubSysDef->ValStr3 && *SubSysDef->ValStr3) |
---|
1486 | if (Argc = StrToArgv(SubSysDef->ValStr3, " ", &Argv, NULL, 0)) |
---|
1487 | for (i = 0; i < Argc; ++i) |
---|
1488 | (void) SetCondition(SubSysDef, Argv[i], "NumCPU"); |
---|
1489 | if (SubSysDef->ValStr4 && *SubSysDef->ValStr4) |
---|
1490 | if (Argc = StrToArgv(SubSysDef->ValStr4, " ", &Argv, NULL, 0)) |
---|
1491 | for (i = 0; i < Argc; ++i) |
---|
1492 | (void) SetCondition(SubSysDef, Argv[i], "HasDev"); |
---|
1493 | if (SubSysDef->ValStr5 && *SubSysDef->ValStr5) |
---|
1494 | if (Argc = StrToArgv(SubSysDef->ValStr5, " ", &Argv, NULL, 0)) |
---|
1495 | for (i = 0; i < Argc; ++i) |
---|
1496 | (void) SetCondition(SubSysDef, Argv[i], "HasType"); |
---|
1497 | } |
---|
1498 | |
---|
1499 | /* |
---|
1500 | * Iterate through each condition and set Matches==TRUE if condition |
---|
1501 | * is met. |
---|
1502 | */ |
---|
1503 | for (Cond = SubSysDef->Conditions; Cond; Cond = Cond->Next) { |
---|
1504 | if (EQ("HasDev", Cond->Key) && Cond->StrVal) { |
---|
1505 | if (OBPfindNodeByName(OBPnodeTree, Cond->StrVal)) |
---|
1506 | Cond->Matches = TRUE; |
---|
1507 | } else if (EQ("HasType", Cond->Key) && Cond->StrVal) { |
---|
1508 | if (OBPfindNodeByType(OBPnodeTree, Cond->StrVal)) |
---|
1509 | Cond->Matches = TRUE; |
---|
1510 | } else if (EQ("CPUspeedDelta", Cond->Key) && Cond->IntVal) { |
---|
1511 | /* |
---|
1512 | * Set the CPUspeedDelta |
---|
1513 | * This variable specifies how much leeway is given when |
---|
1514 | * comparing CPUspeed (in MHz) below. |
---|
1515 | */ |
---|
1516 | CPUspeedDelta = Cond->IntVal; |
---|
1517 | /* Don't use this entry for comparisons */ |
---|
1518 | Cond->Flags |= CONFL_SETONLY; |
---|
1519 | } else if (cp = OBPsubSysGetVar(Cond->Key, (Opaque_t) &SubSysVar)) { |
---|
1520 | if (EQ("CPUspeed", Cond->Key)) { |
---|
1521 | /* |
---|
1522 | * SubSysVar.IntVal is system's actual CPUspeed. |
---|
1523 | * Cond->IntVal is CPUspeed from the .cf parameter. |
---|
1524 | * CPUspeed may vary by +/- CPUspeedDelta. |
---|
1525 | */ |
---|
1526 | if (SubSysVar.IntVal >= (Cond->IntVal - CPUspeedDelta) && |
---|
1527 | SubSysVar.IntVal <= (Cond->IntVal + CPUspeedDelta)) |
---|
1528 | Cond->Matches = TRUE; |
---|
1529 | } else if (EQ("NumCPU", Cond->Key)) { |
---|
1530 | if (SubSysVar.IntVal == Cond->IntVal) |
---|
1531 | Cond->Matches = TRUE; |
---|
1532 | } else if (EQ("ClockFreq", Cond->Key)) { |
---|
1533 | if (Cond->IntVal == atoi(cp)) |
---|
1534 | Cond->Matches = TRUE; |
---|
1535 | } |
---|
1536 | } else { |
---|
1537 | SImsg(SIM_DBG, "%s: Bad keyword in SubSysModel rule.", |
---|
1538 | Cond->Key); |
---|
1539 | } |
---|
1540 | } |
---|
1541 | |
---|
1542 | /* |
---|
1543 | * If all conditions Match (are TRUE), then everything is GO. If any ONE |
---|
1544 | * item is not a Match (FALSE), then it's no GO. |
---|
1545 | */ |
---|
1546 | for (AllMatch = TRUE, Cond = SubSysDef->Conditions; Cond; |
---|
1547 | Cond = Cond->Next) { |
---|
1548 | if (FLAGS_ON(Cond->Flags, CONFL_SETONLY)) |
---|
1549 | continue; |
---|
1550 | if (!Cond->Matches) { |
---|
1551 | AllMatch = FALSE; |
---|
1552 | break; |
---|
1553 | } |
---|
1554 | } |
---|
1555 | |
---|
1556 | /* |
---|
1557 | * Expand name if needed. |
---|
1558 | */ |
---|
1559 | if (AllMatch) { |
---|
1560 | SubSysName = VarSub(ExpandStr, ErrBuff, sizeof(ErrBuff), |
---|
1561 | OBPsubSysGetVar, (Opaque_t) &SubSysVar); |
---|
1562 | if (SubSysName) |
---|
1563 | return(SubSysName); |
---|
1564 | else |
---|
1565 | SImsg(SIM_GERR, "Variable error in `%s': %s", ExpandStr, ErrBuff); |
---|
1566 | } |
---|
1567 | |
---|
1568 | return((char *) NULL); |
---|
1569 | } |
---|
1570 | |
---|
1571 | /* |
---|
1572 | * Get system model type from OBP directly. |
---|
1573 | */ |
---|
1574 | extern char *OBPgetSysModel() |
---|
1575 | { |
---|
1576 | int obp_fd; |
---|
1577 | char *Name; |
---|
1578 | char *SubName; |
---|
1579 | static OBPprop_t *OBPprop = NULL; |
---|
1580 | register Define_t *DefPtr; |
---|
1581 | register Define_t *SubSysDefs; |
---|
1582 | |
---|
1583 | /* |
---|
1584 | * Note: Only one process at a time can open _PATH_OPENPROM. |
---|
1585 | */ |
---|
1586 | if ((obp_fd = open(_PATH_OPENPROM, O_RDONLY)) < 0) { |
---|
1587 | SImsg(SIM_GERR, "Cannot open \"%s\": %s.", _PATH_OPENPROM, SYSERR); |
---|
1588 | return((char *) NULL); |
---|
1589 | } |
---|
1590 | |
---|
1591 | /* |
---|
1592 | * Position ourselves at root OBP node. |
---|
1593 | */ |
---|
1594 | (void) OBPnodeNext((OBPnodeid_t) 0, obp_fd, OPROMNEXT); |
---|
1595 | |
---|
1596 | /* |
---|
1597 | * Get all the properties for the current node. |
---|
1598 | */ |
---|
1599 | if (!OBPgetProps(obp_fd, &OBPprop)) { |
---|
1600 | SImsg(SIM_GERR, "Get OBP Property table failed."); |
---|
1601 | return((char *)NULL); |
---|
1602 | } |
---|
1603 | |
---|
1604 | (void) close(obp_fd); |
---|
1605 | |
---|
1606 | /* |
---|
1607 | * Find the root node's name |
---|
1608 | */ |
---|
1609 | Name = OBPfindPropVal(OBP_NAME, OBPprop, NULL, NULL); |
---|
1610 | if (!Name) { |
---|
1611 | SImsg(SIM_GERR, "Could not find system model in OBP."); |
---|
1612 | return((char *) NULL); |
---|
1613 | } |
---|
1614 | |
---|
1615 | /* |
---|
1616 | * See if there is a sub system model name for this. |
---|
1617 | */ |
---|
1618 | SubSysDefs = DefGet(DL_SUBSYSMODEL, Name, 0, 0); |
---|
1619 | if (!SubSysDefs) { |
---|
1620 | /* No Sub System Model defined, so we just return the base name */ |
---|
1621 | SImsg(SIM_DBG, "No sub system model defined for `%s'", Name); |
---|
1622 | return(Name); |
---|
1623 | } |
---|
1624 | |
---|
1625 | for (DefPtr = SubSysDefs; DefPtr; DefPtr = DefPtr->Next) |
---|
1626 | if (EQ(Name, DefPtr->KeyStr) && (SubName = OBPgetSubSysModel(DefPtr))) |
---|
1627 | return(SubName); |
---|
1628 | |
---|
1629 | return(Name); |
---|
1630 | } |
---|
1631 | |
---|
1632 | #endif /* HAVE_OPENPROM */ |
---|