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.3 $"; |
---|
11 | #endif |
---|
12 | |
---|
13 | /* |
---|
14 | * AIX specific functions |
---|
15 | */ |
---|
16 | |
---|
17 | #include "defs.h" |
---|
18 | #include <nl_types.h> |
---|
19 | #include <locale.h> |
---|
20 | |
---|
21 | /* |
---|
22 | * Platform Specific Interfaces |
---|
23 | */ |
---|
24 | extern char *GetKernArchCfg(); |
---|
25 | PSI_t GetKernArchPSI[] = { /* Get Kernel Architecture */ |
---|
26 | { GetKernArchCfg }, |
---|
27 | { GetKernArchSysinfo }, |
---|
28 | { GetKernArchDef }, |
---|
29 | { GetAppArch }, |
---|
30 | { NULL }, |
---|
31 | }; |
---|
32 | PSI_t GetAppArchPSI[] = { /* Get Application Architecture */ |
---|
33 | { GetAppArchSysinfo }, |
---|
34 | { GetAppArchDef }, |
---|
35 | { NULL }, |
---|
36 | }; |
---|
37 | PSI_t GetCpuTypePSI[] = { /* Get CPU Type */ |
---|
38 | { GetCpuTypeSysinfo }, |
---|
39 | { GetCpuTypeDef }, |
---|
40 | { NULL }, |
---|
41 | }; |
---|
42 | PSI_t GetNumCpuPSI[] = { /* Get Number of CPU's */ |
---|
43 | { GetNumCpuSysconf }, |
---|
44 | { NULL }, |
---|
45 | }; |
---|
46 | PSI_t GetKernVerPSI[] = { /* Get Kernel Version */ |
---|
47 | { NULL }, |
---|
48 | }; |
---|
49 | PSI_t GetOSNamePSI[] = { /* Get OS Name */ |
---|
50 | { GetOSNameSysinfo }, |
---|
51 | { GetOSNameUname }, |
---|
52 | { NULL }, |
---|
53 | }; |
---|
54 | PSI_t GetOSDistPSI[] = { /* Get OS Release */ |
---|
55 | { NULL }, |
---|
56 | }; |
---|
57 | extern char *GetOSVerFiles(); |
---|
58 | PSI_t GetOSVerPSI[] = { /* Get OS Version */ |
---|
59 | { GetOSVerFiles }, |
---|
60 | { GetOSVerSysinfo }, |
---|
61 | { GetOSVerUname }, |
---|
62 | { NULL }, |
---|
63 | }; |
---|
64 | char *GetModelODM(); |
---|
65 | PSI_t GetModelPSI[] = { /* Get system Model */ |
---|
66 | { GetModelFile }, |
---|
67 | { GetModelODM }, |
---|
68 | { NULL }, |
---|
69 | }; |
---|
70 | PSI_t GetSerialPSI[] = { /* Get Serial Number */ |
---|
71 | { NULL }, |
---|
72 | }; |
---|
73 | PSI_t GetRomVerPSI[] = { /* Get ROM Version */ |
---|
74 | { NULL }, |
---|
75 | }; |
---|
76 | PSI_t GetManShortPSI[] = { /* Get Short Man Name */ |
---|
77 | { GetManShortSysinfo }, |
---|
78 | { GetManShortDef }, |
---|
79 | { NULL }, |
---|
80 | }; |
---|
81 | PSI_t GetManLongPSI[] = { /* Get Long Man Name */ |
---|
82 | { GetManLongSysinfo }, |
---|
83 | { GetManLongDef }, |
---|
84 | { NULL }, |
---|
85 | }; |
---|
86 | extern char *GetMemoryODM(); |
---|
87 | PSI_t GetMemoryPSI[] = { /* Get amount of memory */ |
---|
88 | { GetMemoryODM }, |
---|
89 | { NULL }, |
---|
90 | }; |
---|
91 | extern char *GetVirtMemODM(); |
---|
92 | PSI_t GetVirtMemPSI[] = { /* Get amount of virtual memory */ |
---|
93 | { GetVirtMemODM }, |
---|
94 | { NULL }, |
---|
95 | }; |
---|
96 | PSI_t GetBootTimePSI[] = { /* Get System Boot Time */ |
---|
97 | { GetBootTimeUtmp }, |
---|
98 | { NULL }, |
---|
99 | }; |
---|
100 | |
---|
101 | /* |
---|
102 | * Get ODM Error string. |
---|
103 | */ |
---|
104 | static char *odmerror() |
---|
105 | { |
---|
106 | static char odmerrstr[256]; |
---|
107 | |
---|
108 | if (odm_err_msg(odmerrno, (char **) &odmerrstr)) |
---|
109 | (void) snprintf(odmerrstr, sizeof(odmerrstr), |
---|
110 | "unknown ODM error %d", odmerrno); |
---|
111 | |
---|
112 | return(odmerrstr); |
---|
113 | } |
---|
114 | |
---|
115 | /* |
---|
116 | * Get the value of attribute 'Attr' with name 'Name' |
---|
117 | * from the Custom Attribute ODM. |
---|
118 | */ |
---|
119 | static char *GetAttrVal(Name, Attr) |
---|
120 | char *Name; |
---|
121 | char *Attr; |
---|
122 | { |
---|
123 | static struct CuAt CuAt; |
---|
124 | static char Query[128]; |
---|
125 | char *errstr = NULL; |
---|
126 | int ret; |
---|
127 | |
---|
128 | if (odm_initialize() == -1) { |
---|
129 | SImsg(SIM_GERR, "ODM initialize failed: %s", odmerror()); |
---|
130 | return((char *) NULL); |
---|
131 | } |
---|
132 | |
---|
133 | (void) snprintf(Query, sizeof(Query), "attribute = '%s' and name = '%s'", |
---|
134 | Attr, Name); |
---|
135 | |
---|
136 | ret = (int) odm_get_obj(CuAt_CLASS, Query, &CuAt, ODM_FIRST); |
---|
137 | if (ret == -1) |
---|
138 | errstr = odmerror(); |
---|
139 | else if (ret == 0) |
---|
140 | errstr = "No entry found"; |
---|
141 | |
---|
142 | if (errstr) { |
---|
143 | SImsg(SIM_GERR, "ODM get \"%s\" from \"%s\" failed: %s", |
---|
144 | Query, CuAt_CLASS[0].classname, errstr); |
---|
145 | return((char *) NULL); |
---|
146 | } |
---|
147 | |
---|
148 | return((CuAt.value[0]) ? CuAt.value : (char *) NULL); |
---|
149 | } |
---|
150 | |
---|
151 | /* |
---|
152 | * Get the PvDv ODM entry with the criteria 'Criteria'. |
---|
153 | */ |
---|
154 | static struct PdDv *GetPdDv(Criteria) |
---|
155 | char *Criteria; |
---|
156 | { |
---|
157 | static struct PdDv PdDv; |
---|
158 | char *errstr = NULL; |
---|
159 | int ret; |
---|
160 | |
---|
161 | if (odm_initialize() == -1) { |
---|
162 | SImsg(SIM_GERR, "ODM initialize failed: %s", odmerror()); |
---|
163 | return((struct PdDv *) NULL); |
---|
164 | } |
---|
165 | |
---|
166 | ret = (int) odm_get_obj(PdDv_CLASS, Criteria, &PdDv, ODM_FIRST); |
---|
167 | if (ret == -1) |
---|
168 | errstr = odmerror(); |
---|
169 | else if (ret == 0) |
---|
170 | errstr = "No entry found"; |
---|
171 | |
---|
172 | if (errstr) { |
---|
173 | SImsg(SIM_GERR, "ODM get \"%s\" from \"%s\" failed: %s", |
---|
174 | Criteria, PdDv_CLASS[0].classname, errstr); |
---|
175 | return((struct PdDv *) NULL); |
---|
176 | } |
---|
177 | |
---|
178 | return(&PdDv); |
---|
179 | } |
---|
180 | |
---|
181 | /* |
---|
182 | * Clean up a VPD string. Remove initial non alpha-numeric characters |
---|
183 | * as well as any trailing white space. |
---|
184 | */ |
---|
185 | static char *CleanVPD(string) |
---|
186 | char *string; |
---|
187 | { |
---|
188 | register char *cp, *end; |
---|
189 | |
---|
190 | while (string && *string && !isalnum(*string)) |
---|
191 | ++string; |
---|
192 | |
---|
193 | cp = end = &string[strlen(string) - 1]; |
---|
194 | |
---|
195 | while (cp && *cp && isspace(*cp)) |
---|
196 | --cp; |
---|
197 | |
---|
198 | if (cp != end) |
---|
199 | *(cp+1) = CNULL; |
---|
200 | |
---|
201 | return(string); |
---|
202 | } |
---|
203 | |
---|
204 | /* |
---|
205 | * Find the VPD info entry for "String". Return a vpdinfo_t |
---|
206 | * entry for the matching entry and set it's "value" correctly. |
---|
207 | */ |
---|
208 | static VPDinfo_t *GetVPDinfo(String) |
---|
209 | char *String; |
---|
210 | { |
---|
211 | static char Buff[BUFSIZ]; |
---|
212 | static char Code[3]; |
---|
213 | static VPDinfo_t VPDinfo; |
---|
214 | |
---|
215 | (void) strncpy(Code, String, 2); /* XXX Assume codes are only 2 bytes */ |
---|
216 | Code[2] = CNULL; |
---|
217 | |
---|
218 | VPDinfo.Code = Code; |
---|
219 | /* |
---|
220 | * The "value" portion of "String" starts after the "code" portion. |
---|
221 | * CleanVPD() is harmful, so we need to pass it a private copy. |
---|
222 | */ |
---|
223 | (void) snprintf(Buff, sizeof(Buff), "%s", String + strlen(VPDinfo.Code)); |
---|
224 | VPDinfo.Value = CleanVPD(Buff); |
---|
225 | |
---|
226 | return(&VPDinfo); |
---|
227 | } |
---|
228 | |
---|
229 | /* |
---|
230 | * Given a VPD string "vpdstr", decode it into a list of strings. |
---|
231 | */ |
---|
232 | static int DecodeVPD(DevInfo, VPDstr) |
---|
233 | DevInfo_t *DevInfo; |
---|
234 | char *VPDstr; |
---|
235 | { |
---|
236 | char *myVPDstr; |
---|
237 | register char *cp; |
---|
238 | Define_t *Def; |
---|
239 | VPDinfo_t *VPDinfo; |
---|
240 | |
---|
241 | if (!VPDstr) |
---|
242 | return(-1); |
---|
243 | |
---|
244 | /* strtok() is destructive */ |
---|
245 | myVPDstr = strdup(VPDstr); |
---|
246 | |
---|
247 | /* |
---|
248 | * Each field in "VPDstr" is seperated by a "*", followed by |
---|
249 | * the code for the field and it's value. Looks something like: |
---|
250 | * |
---|
251 | * *TM 19445*MF IBM |
---|
252 | */ |
---|
253 | for (cp = strtok(myVPDstr, "*"); cp; cp = strtok((char *)NULL, "*")) { |
---|
254 | if (!(VPDinfo = GetVPDinfo(cp))) |
---|
255 | continue; |
---|
256 | |
---|
257 | if (EQ(VPDinfo->Code, "MF")) |
---|
258 | DevInfo->Vendor = strdup(VPDinfo->Value); |
---|
259 | else if (EQ(VPDinfo->Code, "TM")) |
---|
260 | DevInfo->Model = strdup(VPDinfo->Value); |
---|
261 | else if (EQ(VPDinfo->Code, "DS")) |
---|
262 | DevInfo->ModelDesc = strdup(VPDinfo->Value); |
---|
263 | else if (EQ(VPDinfo->Code, "SN")) |
---|
264 | DevInfo->Serial = strdup(VPDinfo->Value); |
---|
265 | else { |
---|
266 | if (Def = DefGet(DL_VPD, VPDinfo->Code, -1, 0)) |
---|
267 | AddDevDesc(DevInfo, VPDinfo->Value, Def->ValStr1, DA_APPEND); |
---|
268 | else |
---|
269 | SImsg(SIM_UNKN, "Unknown VPD code=`%s' value=`%s'.", |
---|
270 | VPDinfo->Code, VPDinfo->Value); |
---|
271 | } |
---|
272 | } |
---|
273 | |
---|
274 | if (myVPDstr) |
---|
275 | (void) free(myVPDstr); |
---|
276 | |
---|
277 | return(0); |
---|
278 | } |
---|
279 | |
---|
280 | /* |
---|
281 | * Get and decode the Vital Product Data informatin for device "Name". |
---|
282 | */ |
---|
283 | static int GetVPD(DevInfo) |
---|
284 | DevInfo_t *DevInfo; |
---|
285 | { |
---|
286 | static struct CuVPD cuvpd; |
---|
287 | static char Query[128]; |
---|
288 | int ret; |
---|
289 | |
---|
290 | if (odm_initialize() == -1) { |
---|
291 | SImsg(SIM_GERR, "ODM initialize failed: %s", odmerror()); |
---|
292 | return(-1); |
---|
293 | } |
---|
294 | |
---|
295 | (void) snprintf(Query, sizeof(Query), "name=%s", DevInfo->Name); |
---|
296 | ret = (int) odm_get_obj(CuVPD_CLASS, Query, &cuvpd, ODM_FIRST); |
---|
297 | if (ret == -1) { |
---|
298 | SImsg(SIM_GERR, "ODM get VPD object for \"%s\" failed: %s", |
---|
299 | DevInfo->Name, odmerror()); |
---|
300 | return(-1); |
---|
301 | } else if (ret == 0) { |
---|
302 | return(-1); |
---|
303 | } |
---|
304 | |
---|
305 | SImsg(SIM_DBG, "VPD: name = '%s' type = %d VPD = '%s'", |
---|
306 | cuvpd.name, cuvpd.vpd_type, cuvpd.vpd); |
---|
307 | |
---|
308 | return(DecodeVPD(DevInfo, cuvpd.vpd)); |
---|
309 | } |
---|
310 | |
---|
311 | /* |
---|
312 | * Get the system model name. |
---|
313 | */ |
---|
314 | extern char *GetModelODM() |
---|
315 | { |
---|
316 | Define_t *Model; |
---|
317 | register char *val, *cp; |
---|
318 | register int i, SysType; |
---|
319 | |
---|
320 | if ((val = GetAttrVal(NN_SYS0, AT_MODELCODE)) == NULL) { |
---|
321 | SImsg(SIM_GERR, "Cannot get \"%s\" for \"%s\" from ODM.", |
---|
322 | AT_MODELCODE, NN_SYS0); |
---|
323 | return((char *) NULL); |
---|
324 | } |
---|
325 | |
---|
326 | SysType = (int) strtol(val, NULL, 0); |
---|
327 | |
---|
328 | SImsg(SIM_DBG, "System type = 0x%x (%s)", SysType, val); |
---|
329 | |
---|
330 | Model = DefGet(DL_SYSMODEL, NULL, (long) SysType, 0); |
---|
331 | if (Model && Model->ValStr1) |
---|
332 | return(Model->ValStr1); |
---|
333 | |
---|
334 | SImsg(SIM_UNKN, "system model/type 0x%x is unknown.", SysType); |
---|
335 | |
---|
336 | return((char *) NULL); |
---|
337 | } |
---|
338 | |
---|
339 | /* |
---|
340 | * Use the kernels _system_configuration structure to determine |
---|
341 | * our kernel architecture. |
---|
342 | * |
---|
343 | * XXX This isn't working right now |
---|
344 | */ |
---|
345 | #include <sys/systemcfg.h> |
---|
346 | static char SysCfgSYM[] = "_system_configuration"; |
---|
347 | extern char *GetKernArchCfg() |
---|
348 | { |
---|
349 | #ifdef notdef /* XXX */ |
---|
350 | struct nlist *NLPtr; |
---|
351 | kvm_t *kd; |
---|
352 | Define_t *Define; |
---|
353 | |
---|
354 | /* |
---|
355 | * Get _system_configuration |
---|
356 | */ |
---|
357 | if (!(kd = KVMopen())) |
---|
358 | return((char *) NULL); |
---|
359 | if ((NLPtr = KVMnlist(kd, SysCfgSYM, (struct nlist *)NULL, 0)) == NULL) |
---|
360 | return((char *) NULL); |
---|
361 | if (CheckNlist(NLPtr)) |
---|
362 | return((char *) NULL); |
---|
363 | if (KVMget(kd, NLPtr->n_value, (char *) &_system_configuration, |
---|
364 | sizeof(_system_configuration), KDT_DATA)) { |
---|
365 | SImsg(SIM_GERR, "Cannot read `%s' from kernel.", SysCfgSYM); |
---|
366 | return((char *) NULL); |
---|
367 | } |
---|
368 | KVMclose(kd); |
---|
369 | |
---|
370 | Define = DefGet(DL_CPU, NULL, _system_configuration.implementation, 0); |
---|
371 | if (Define && Define->ValStr1) |
---|
372 | return(Define->ValStr1); |
---|
373 | #endif /* notdef */ |
---|
374 | return((char *) NULL); |
---|
375 | } |
---|
376 | |
---|
377 | /* |
---|
378 | * Get amount of physical memory from the ODM CuAt data. |
---|
379 | */ |
---|
380 | extern char *GetMemoryODM() |
---|
381 | { |
---|
382 | register char *val; |
---|
383 | Large_t amtval; |
---|
384 | static char Buff[64]; |
---|
385 | |
---|
386 | if ((val = GetAttrVal(NN_SYS0, AT_REALMEM)) == NULL) { |
---|
387 | SImsg(SIM_GERR, "Cannot get \"%s\" for \"%s\" from ODM.", |
---|
388 | AT_REALMEM, NN_SYS0); |
---|
389 | return((char *) NULL); |
---|
390 | } |
---|
391 | |
---|
392 | amtval = (Large_t) strtol(val, NULL, 0); |
---|
393 | (void) snprintf(Buff, sizeof(Buff), "%d MB", |
---|
394 | DivRndUp(amtval, (Large_t)KBYTES)); |
---|
395 | |
---|
396 | return(Buff); |
---|
397 | } |
---|
398 | |
---|
399 | /* |
---|
400 | * Get version of OS |
---|
401 | * |
---|
402 | * The following is based on what the /bin/oslevel script does. |
---|
403 | * There are several files that contain the full OS version/revision |
---|
404 | * level. The first line of these files contains the version number. |
---|
405 | * The line either looks like '3.2.5' or '3250'. |
---|
406 | */ |
---|
407 | static char *OSVfiles[] = { |
---|
408 | OSV_OPP, OSV_MAINT, (char *)0 |
---|
409 | }; |
---|
410 | |
---|
411 | extern char *GetOSVerFiles() |
---|
412 | { |
---|
413 | register char *Ptr; |
---|
414 | register char *Ptr2; |
---|
415 | register char **PtrPtr; |
---|
416 | FILE *FilePtr; |
---|
417 | static char Buff[100]; |
---|
418 | static char Version[100]; |
---|
419 | int Len; |
---|
420 | |
---|
421 | Version[0] = CNULL; |
---|
422 | for (PtrPtr = OSVfiles; PtrPtr && *PtrPtr; ++PtrPtr) { |
---|
423 | FilePtr = fopen(*PtrPtr, "r"); |
---|
424 | if (!FilePtr) { |
---|
425 | SImsg(SIM_GERR, "Open %s failed: %s.", *PtrPtr, SYSERR); |
---|
426 | continue; |
---|
427 | } |
---|
428 | if (fgets(Buff, sizeof(Buff), FilePtr) && isdigit(Buff[0])) { |
---|
429 | Len = strlen(Buff); |
---|
430 | if (Buff[Len-1] == '\n') |
---|
431 | Buff[Len-1] = CNULL; |
---|
432 | if (strchr(Buff, '.')) |
---|
433 | (void) strcpy(Version, Buff); |
---|
434 | else |
---|
435 | for (Ptr = Buff, Ptr2 = Version; Ptr && *Ptr; ++Ptr, ++Ptr2) { |
---|
436 | /* If the line ends in 0, don't add it */ |
---|
437 | if (!(*Ptr == '0' && *(Ptr+1) == CNULL)) |
---|
438 | *Ptr2 = *Ptr; |
---|
439 | if (*(Ptr + 1)) |
---|
440 | *++Ptr2 = '.'; |
---|
441 | } |
---|
442 | /* Zap trailing '.' if present */ |
---|
443 | Len = strlen(Version); |
---|
444 | if (Version[Len-1] == '.') |
---|
445 | Version[Len-1] = CNULL; |
---|
446 | } |
---|
447 | (void) fclose(FilePtr); |
---|
448 | if (Version[0]) |
---|
449 | return(Version); |
---|
450 | } |
---|
451 | |
---|
452 | return((char *) NULL); |
---|
453 | } |
---|
454 | |
---|
455 | /* |
---|
456 | * Take a device name, remove and then return the unit number. |
---|
457 | * e.g. Take "hdisk0", remove "0", and then return 0. |
---|
458 | */ |
---|
459 | static int GetUnit(Name) |
---|
460 | char *Name; |
---|
461 | { |
---|
462 | int unit; |
---|
463 | register char *cp; |
---|
464 | |
---|
465 | for (cp = Name; cp && *cp; ++cp) |
---|
466 | if (isdigit(*cp)) { |
---|
467 | unit = (int) atoi(cp); |
---|
468 | *cp = CNULL; |
---|
469 | return(unit); |
---|
470 | } |
---|
471 | |
---|
472 | return(-1); |
---|
473 | } |
---|
474 | |
---|
475 | /* |
---|
476 | * Get the location information from CuDvPtr. |
---|
477 | */ |
---|
478 | static char *GetLocation(CuDvPtr) |
---|
479 | struct CuDv *CuDvPtr; |
---|
480 | { |
---|
481 | if (CuDvPtr->location[0]) |
---|
482 | return(CuDvPtr->location); |
---|
483 | |
---|
484 | return((char *) NULL); |
---|
485 | } |
---|
486 | |
---|
487 | /* |
---|
488 | * Get Class information. |
---|
489 | */ |
---|
490 | static char *GetClassInfo(CuDvPtr) |
---|
491 | struct CuDv *CuDvPtr; |
---|
492 | { |
---|
493 | if (CuDvPtr->PdDvLn_Lvalue[0]) |
---|
494 | return(CuDvPtr->PdDvLn_Lvalue); |
---|
495 | |
---|
496 | return((char *) NULL); |
---|
497 | } |
---|
498 | |
---|
499 | /* |
---|
500 | * Set the description informatin for DevInfo. |
---|
501 | */ |
---|
502 | static void SetDescript(DevInfo, CuDvPtr) |
---|
503 | DevInfo_t *DevInfo; |
---|
504 | struct CuDv *CuDvPtr; |
---|
505 | { |
---|
506 | AddDevDesc(DevInfo, GetLocation(CuDvPtr), "Location", DA_APPEND); |
---|
507 | AddDevDesc(DevInfo, GetClassInfo(CuDvPtr), "Class/SubClass/Type", |
---|
508 | DA_APPEND); |
---|
509 | GetVPD(DevInfo); |
---|
510 | } |
---|
511 | |
---|
512 | /* |
---|
513 | * Special routine to get memory information. |
---|
514 | */ |
---|
515 | extern DevInfo_t *ProbeMemory(ProbeData, CuDvPtr, PdDvPtr) |
---|
516 | ProbeData_t *ProbeData; |
---|
517 | struct CuDv *CuDvPtr; |
---|
518 | struct PdDv *PdDvPtr; |
---|
519 | { |
---|
520 | DevInfo_t *DevInfo; |
---|
521 | char *cp; |
---|
522 | char Buff[64]; |
---|
523 | char *Name; |
---|
524 | DevData_t *DevData; |
---|
525 | |
---|
526 | if (!ProbeData) |
---|
527 | return((DevInfo_t *) NULL); |
---|
528 | Name = ProbeData->DevName; |
---|
529 | DevData = ProbeData->DevData; |
---|
530 | |
---|
531 | if ((cp = GetAttrVal(Name, AT_SIZE)) == NULL) |
---|
532 | return((DevInfo_t *) NULL); |
---|
533 | |
---|
534 | DevInfo = NewDevInfo((DevInfo_t *) NULL); |
---|
535 | |
---|
536 | (void) snprintf(Buff, sizeof(Buff), "%s MB Memory Card", cp); |
---|
537 | DevInfo->Model = strdup(Buff); |
---|
538 | |
---|
539 | DevInfo->Name = Name; |
---|
540 | DevInfo->Unit = DevData->DevUnit; |
---|
541 | DevInfo->Master = MkMasterFromDevData(DevData); |
---|
542 | DevInfo->Type = DT_MEMORY; |
---|
543 | SetDescript(DevInfo, CuDvPtr); |
---|
544 | |
---|
545 | return(DevInfo); |
---|
546 | } |
---|
547 | |
---|
548 | /* |
---|
549 | * Get description information |
---|
550 | */ |
---|
551 | static char *GetDescript(CuDvPtr, PdDvPtr) |
---|
552 | struct CuDv *CuDvPtr; |
---|
553 | struct PdDv *PdDvPtr; |
---|
554 | { |
---|
555 | static char Buff[BUFSIZ]; |
---|
556 | static char lastcat[BUFSIZ]; |
---|
557 | static nl_catd catd; |
---|
558 | char *msg = NULL; |
---|
559 | char *cp; |
---|
560 | |
---|
561 | if (!PdDvPtr->catalog[0]) |
---|
562 | return((char *) NULL); |
---|
563 | |
---|
564 | /* |
---|
565 | * Reuse open catalog if it's the same as the last time |
---|
566 | */ |
---|
567 | if ((int) catd <= 0 || !lastcat[0] || strcmp(PdDvPtr->catalog, lastcat)) { |
---|
568 | if ((int) catd > 0) |
---|
569 | (void) catclose(catd); |
---|
570 | |
---|
571 | if ((int) catd == 0) { |
---|
572 | /* |
---|
573 | * First time stuff. |
---|
574 | */ |
---|
575 | |
---|
576 | if (putenv(ENV_NLSPATH) != 0) |
---|
577 | SImsg(SIM_GERR, "Cannot set environment $NLSPATH."); |
---|
578 | |
---|
579 | /* |
---|
580 | * If our LANG is "C", then set to our default in order to |
---|
581 | * avoid a bug in AIX that fails to find any catalogs in |
---|
582 | * this case. |
---|
583 | */ |
---|
584 | cp = (char *) getenv("LANG"); |
---|
585 | if (!cp || (cp && EQ(cp, "C"))) { |
---|
586 | (void) snprintf(Buff, sizeof(Buff), "LANG=%s", DEFAULT_LANG); |
---|
587 | if (putenv(strdup(Buff)) != 0) |
---|
588 | SImsg(SIM_GERR, "Cannot set environment %s.", Buff); |
---|
589 | Buff[0] = CNULL; |
---|
590 | } |
---|
591 | (void) setlocale(LC_ALL, ""); |
---|
592 | } |
---|
593 | |
---|
594 | catd = catopen(PdDvPtr->catalog, 0); |
---|
595 | if ((int) catd <= 0) |
---|
596 | SImsg(SIM_GERR, "Catalog open of \"%s\" failed: %s.", |
---|
597 | PdDvPtr->catalog, SYSERR); |
---|
598 | } |
---|
599 | |
---|
600 | /* |
---|
601 | * Retrieve the message from the catalog |
---|
602 | */ |
---|
603 | if ((int) catd > 0) { |
---|
604 | msg = catgets(catd, PdDvPtr->setno, PdDvPtr->msgno, Buff); |
---|
605 | /* Save catalog name */ |
---|
606 | (void) strcpy(lastcat, PdDvPtr->catalog); |
---|
607 | } |
---|
608 | |
---|
609 | return((msg && *msg) ? msg : (char *) NULL); |
---|
610 | } |
---|
611 | |
---|
612 | /* |
---|
613 | * General routine to get device information from ODM. |
---|
614 | */ |
---|
615 | extern DevInfo_t *ProbeODM(DevData, TreePtr, CuDvPtr) |
---|
616 | /*ARGSUSED*/ |
---|
617 | DevData_t *DevData; |
---|
618 | DevInfo_t **TreePtr; |
---|
619 | struct CuDv *CuDvPtr; |
---|
620 | { |
---|
621 | DevDefine_t *DevDefine; |
---|
622 | DevInfo_t *DevInfo; |
---|
623 | DevInfo_t *Master; |
---|
624 | char *MasterName; |
---|
625 | char *DevName; |
---|
626 | char *desc; |
---|
627 | char *cp; |
---|
628 | static char Query[128]; |
---|
629 | struct PdDv *PdDvPtr; |
---|
630 | static ProbeData_t ProbeData; |
---|
631 | static DevFind_t Find; |
---|
632 | |
---|
633 | DevName = MkDevName(DevData->DevName, DevData->DevUnit, 0, 0); |
---|
634 | (void) memset(&Find, 0, sizeof(Find)); |
---|
635 | Find.Tree = *TreePtr; |
---|
636 | Find.NodeName = DevName; |
---|
637 | DevInfo = DevFind(&Find); |
---|
638 | |
---|
639 | if (CuDvPtr->PdDvLn_Lvalue[0]) { |
---|
640 | (void) snprintf(Query, sizeof(Query), "uniquetype='%s'", |
---|
641 | CuDvPtr->PdDvLn_Lvalue); |
---|
642 | PdDvPtr = GetPdDv(Query); |
---|
643 | } else { |
---|
644 | SImsg(SIM_GERR, "No PdDv link value for '%s'.", DevName); |
---|
645 | return((DevInfo_t *) NULL); |
---|
646 | } |
---|
647 | |
---|
648 | /* |
---|
649 | * If we can't get the description for this device, then |
---|
650 | * use the device specific probe routine if one is defined. |
---|
651 | */ |
---|
652 | if ((desc = GetDescript(CuDvPtr, PdDvPtr)) == (char *) NULL) { |
---|
653 | if ((DevDefine = DevDefGet(DL_VPD, DevData->DevName, 0)) && |
---|
654 | DevDefine->Probe) { |
---|
655 | (void) memset(&ProbeData, CNULL, sizeof(ProbeData)); |
---|
656 | ProbeData.DevName = DevName; |
---|
657 | ProbeData.DevData = DevData; |
---|
658 | ProbeData.DevDefine = DevDefine; |
---|
659 | return((*DevDefine->Probe)(&ProbeData, CuDvPtr, PdDvPtr)); |
---|
660 | } else { |
---|
661 | if (Debug) |
---|
662 | SImsg(SIM_GERR, "No description found for '%s'.", DevName); |
---|
663 | return((DevInfo_t *) NULL); |
---|
664 | } |
---|
665 | } |
---|
666 | |
---|
667 | if (!DevInfo) |
---|
668 | DevInfo = NewDevInfo((DevInfo_t *) NULL); |
---|
669 | |
---|
670 | DevInfo->Name = DevName; |
---|
671 | DevInfo->Unit = DevData->DevUnit; |
---|
672 | DevInfo->Type = DT_GENERIC; |
---|
673 | DevInfo->ModelDesc = strdup(desc); |
---|
674 | SetDescript(DevInfo, CuDvPtr); |
---|
675 | if (!DevInfo->MasterName) |
---|
676 | DevInfo->MasterName = MkMasterName(DevData); |
---|
677 | if (!DevInfo->Master) { |
---|
678 | (void) memset(&Find, 0, sizeof(Find)); |
---|
679 | Find.Tree = *TreePtr; |
---|
680 | Find.NodeName = DevInfo->MasterName; |
---|
681 | if (Master = DevFind(&Find)) |
---|
682 | DevInfo->Master = Master; |
---|
683 | else { |
---|
684 | DevInfo->Master = MkMasterFromDevData(DevData); |
---|
685 | if (DevInfo->Master) |
---|
686 | DevInfo->MasterName = DevInfo->Master->Name; |
---|
687 | } |
---|
688 | } |
---|
689 | |
---|
690 | return(DevInfo); |
---|
691 | } |
---|
692 | |
---|
693 | /* |
---|
694 | * Build device tree by looking at the Object Database Manager (ODM) |
---|
695 | */ |
---|
696 | static int BuildODM(TreePtr, Names) |
---|
697 | DevInfo_t **TreePtr; |
---|
698 | char **Names; |
---|
699 | { |
---|
700 | static struct CuDv CuDv; |
---|
701 | extern struct Class CuDv_CLASS[]; |
---|
702 | static DevData_t DevData; |
---|
703 | DevInfo_t *DevInfo; |
---|
704 | int op, ret; |
---|
705 | |
---|
706 | if (odm_initialize() == -1) { |
---|
707 | SImsg(SIM_GERR, "ODM initialize failed: %s", odmerror()); |
---|
708 | return(-1); |
---|
709 | } |
---|
710 | |
---|
711 | for (op = ODM_FIRST; ; op = ODM_NEXT) { |
---|
712 | /* |
---|
713 | * Retrieve the object from ODM. |
---|
714 | */ |
---|
715 | ret = (int) odm_get_obj(CuDv_CLASS, (char *)NULL, &CuDv, op); |
---|
716 | if (ret == -1) { |
---|
717 | SImsg(SIM_GERR, "ODM get object \"%s\" failed: %s", |
---|
718 | CuDv_CLASS[0].classname, odmerror()); |
---|
719 | return(-1); |
---|
720 | } else if (ret == 0) |
---|
721 | /* |
---|
722 | * We're done |
---|
723 | */ |
---|
724 | break; |
---|
725 | |
---|
726 | if (CuDv.status != AVAILABLE) { |
---|
727 | SImsg(SIM_GERR, "Device \"%s\" is not available.", CuDv.name); |
---|
728 | continue; |
---|
729 | } |
---|
730 | |
---|
731 | /* |
---|
732 | * This should never happen |
---|
733 | */ |
---|
734 | if (CuDv.name[0] == CNULL) |
---|
735 | continue; |
---|
736 | |
---|
737 | /* Make sure devdata is clean */ |
---|
738 | bzero(&DevData, sizeof(DevData_t)); |
---|
739 | |
---|
740 | /* Set what we know */ |
---|
741 | DevData.DevName = strdup(CuDv.name); |
---|
742 | DevData.DevUnit = GetUnit(DevData.DevName); |
---|
743 | if (CuDv.parent[0]) { |
---|
744 | DevData.CtlrName = strdup(CuDv.parent); |
---|
745 | DevData.CtlrUnit = GetUnit(DevData.CtlrName); |
---|
746 | } |
---|
747 | DevData.Flags |= DD_IS_ALIVE; |
---|
748 | |
---|
749 | SImsg(SIM_DBG, "ODM: Found '%s' parent '%s' location '%s' uniq = '%s'", |
---|
750 | CuDv.name, CuDv.parent, CuDv.location, CuDv.PdDvLn_Lvalue); |
---|
751 | |
---|
752 | /* Probe and add device */ |
---|
753 | if (DevInfo = ProbeODM(&DevData, TreePtr, &CuDv)) |
---|
754 | AddDevice(DevInfo, TreePtr, Names); |
---|
755 | } |
---|
756 | |
---|
757 | if (odm_terminate() != 0) |
---|
758 | SImsg(SIM_WARN, "ODM Terminate did not succeed."); |
---|
759 | |
---|
760 | return(0); |
---|
761 | } |
---|
762 | |
---|
763 | /* |
---|
764 | * Build device tree using TreePtr. |
---|
765 | * Calls bus and method specific functions to |
---|
766 | * search for devices. |
---|
767 | */ |
---|
768 | extern int BuildDevices(TreePtr, Names) |
---|
769 | DevInfo_t **TreePtr; |
---|
770 | char **Names; |
---|
771 | { |
---|
772 | int Found = 1; |
---|
773 | |
---|
774 | if (BuildODM(TreePtr, Names) == 0) |
---|
775 | Found = 0; |
---|
776 | |
---|
777 | return(Found); |
---|
778 | } |
---|
779 | |
---|
780 | #include <sys/vminfo.h> |
---|
781 | |
---|
782 | static char QueryStr[] = |
---|
783 | "value = 'paging' and attribute = 'type'"; |
---|
784 | |
---|
785 | extern char *GetVirtMemODM() |
---|
786 | { |
---|
787 | struct CuAt *CuAtPtr; |
---|
788 | struct objlistinfo ObjListInfo; |
---|
789 | register int i; |
---|
790 | static char DevName[MAXPATHLEN]; |
---|
791 | static struct pginfo pginfo; |
---|
792 | Large_t Amount = 0; |
---|
793 | static char Buff[100]; |
---|
794 | |
---|
795 | odm_initialize(); |
---|
796 | odm_set_path(_PATH_ODM); |
---|
797 | |
---|
798 | CuAtPtr = get_CuAt_list(CuAt_CLASS, QueryStr, &ObjListInfo, 20, 1); |
---|
799 | if ((int)CuAtPtr == -1) { |
---|
800 | SImsg(SIM_GERR, "get_CuAt_list paging info failed: %s.", SYSERR); |
---|
801 | odm_terminate(); |
---|
802 | return((char *)NULL); |
---|
803 | } |
---|
804 | |
---|
805 | for (i = 0; i < ObjListInfo.num; ++i, ++CuAtPtr) { |
---|
806 | (void) snprintf(DevName, sizeof(DevName), "/dev/%s", CuAtPtr->name); |
---|
807 | |
---|
808 | if (swapqry(DevName, &pginfo) == -1) { |
---|
809 | SImsg(SIM_GERR, "swapqry %s failed: %s.", DevName, SYSERR); |
---|
810 | continue; |
---|
811 | } |
---|
812 | |
---|
813 | Amount += (Large_t) ( (pginfo.size * getpagesize() ) / KBYTES ); |
---|
814 | } |
---|
815 | |
---|
816 | odm_terminate(); |
---|
817 | (void) snprintf(Buff, sizeof(Buff), "%d MB", |
---|
818 | DivRndUp(Amount, (Large_t)KBYTES)); |
---|
819 | |
---|
820 | return(Buff); |
---|
821 | } |
---|
822 | |
---|
823 | /* |
---|
824 | * Initialize the OS specific parts of the Device Types table |
---|
825 | */ |
---|
826 | void DevTypesInit() |
---|
827 | { |
---|
828 | register int i; |
---|
829 | |
---|
830 | for (i = 0; DevTypes[i].Name; ++i) |
---|
831 | switch (DevTypes[i].Type) { |
---|
832 | case DT_MEMORY: DevTypes[i].Probe = ProbeMemory; break; |
---|
833 | } |
---|
834 | } |
---|