1 /*      $NetBSD: residual.c,v 1.19 2023/11/24 16:49:59 christos Exp $     */
2 
3 /*-
4  * Copyright (c) 2002 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by NONAKA Kimihiro.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: residual.c,v 1.19 2023/11/24 16:49:59 christos Exp $");
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/inttypes.h>
38 
39 #include <machine/residual.h>
40 #include <machine/pnp.h>
41 
42 #include "opt_residual.h"
43 
44 #ifdef RESIDUAL_DATA_DUMP
45 
46 #include <machine/chpidpnp.h>
47 #include <machine/pcipnp.h>
48 
49 static void make_pnp_device_tree(void *);
50 static void bustype_subr(DEVICE_ID *);
51 
52 int dump_residual_data = 1;
53 
54 #define   NELEMS(array)       ((size_t)(sizeof(array)/sizeof(array[0])))
55 
56 static const char *FirmwareSupplier[] = {
57           "IBMFirmware",
58           "MotoFirmware",
59           "FirmWorks",
60           "Bull",
61 };
62 
63 static const char *FirmwareSupports[] = {
64           "Conventional",
65           "OpenFirmware",
66           "Diagnostics",
67           "LowDebug",
68           "Multiboot",
69           "LowClient",
70           "Hex41",
71           "FAT",
72           "ISO9660",
73           "SCSI_InitiatorID_Override",
74           "Tape_Boot",
75           "FW_Boot_Path",
76 };
77 
78 static const char *EndianSwitchMethod[] = {
79           "Unknown",
80           "UsePort92",
81           "UsePCIConfigA8",
82           "UseFF001030",
83 };
84 
85 static const char *SpreadIOMethod[] = {
86           "UsePort850",
87 };
88 
89 static const char *CacheAttrib[] = {
90           "No cache",
91           "Split cache",
92           "Combined cache",
93 };
94 
95 static const char *TLBAttrib[] = {
96           "No TLB",
97           "Split TLB",
98           "Combined TLB",
99 };
100 
101 static const char *Usage[] = {
102           "FirmwareStack",
103           "FirmwareHeap",
104           "FirmwareCode",
105           "BootImage",
106           "Free",
107           "Unpopulated",
108           "ISAAddr",
109           "PCIConfig",
110           "PCIAddr",
111           "SystemRegs",
112           "SystemIO",
113           "IOMemory",
114           "UnPopSystemROM",
115           "SystemROM",
116           "ResumeBlock",
117           "Other",
118 };
119 
120 static const char *BusId[] = {
121           "ISA",
122           "EISA",
123           "PCI",
124           "PCMCIA",
125           "ISAPNP",
126           "MCA",
127           "MX",
128           "PROCESSOR",
129           "VME",
130 };
131 
132 static const char *Flags[] = {
133           "Output",
134           "Input",
135           "ConsoleOut",
136           "ConsoleIn",
137           "Removable",
138           "ReadOnly",
139           "PowerManaged",
140           "Disableable",
141           "Configurable",
142           "Boot",
143           "Dock",
144           "Static",
145           "Failed",
146           "Integrated",
147           "Enabled",
148 };
149 
150 #endif /* RESIDUAL_DATA_DUMP */
151 
152 
153 /*
154  * Convert a pnp DevId to a string.
155  */
156 
157 void
pnp_devid_to_string(uint32_t devid,char * s)158 pnp_devid_to_string(uint32_t devid, char *s)
159 {
160           uint8_t p[4];
161           uint32_t l;
162 
163           if (res->Revision == 0)
164                     l = le32toh(devid);
165           else
166                     l = be32toh(devid);
167           p[0] = (l >> 24) & 0xff;
168           p[1] = (l >> 16) & 0xff;
169           p[2] = (l >> 8) & 0xff;
170           p[3] = l & 0xff;
171 
172           *s++ = ((p[0] >> 2) & 0x1f) + 'A' - 1;
173           *s++ = (((p[0] & 0x03) << 3) | ((p[1] >> 5) & 0x07)) + 'A' - 1;
174           *s++ = (p[1] & 0x1f) + 'A' - 1;
175           *s++ = HEXDIGITS[(p[2] >> 4) & 0xf];
176           *s++ = HEXDIGITS[p[2] & 0xf];
177           *s++ = HEXDIGITS[(p[3] >> 4) & 0xf];
178           *s++ = HEXDIGITS[p[3] & 0xf];
179           *s = '\0';
180 }
181 
182 /*
183  * Count the number of a specific deviceid on the pnp tree.
184  */
185 
186 int
count_pnp_devices(const char * devid)187 count_pnp_devices(const char *devid)
188 {
189           PPC_DEVICE *ppc_dev;
190           int i, found=0;
191           uint32_t ndev;
192           char deviceid[8];
193 
194           ndev = be32toh(res->ActualNumDevices);
195           ppc_dev = res->Devices;
196 
197           for (i = 0; i < ((ndev > MAX_DEVICES) ? MAX_DEVICES : ndev); i++) {
198                     DEVICE_ID *id = &ppc_dev[i].DeviceId;
199 
200                     pnp_devid_to_string(id->DevId, deviceid);
201                     if (strcmp(deviceid, devid) == 0)
202                               found++;
203           }
204           return found;
205 }
206 
207 /*
208  * find and return a pointer to the N'th device of a given type.
209  */
210 
211 PPC_DEVICE *
find_nth_pnp_device(const char * devid,int busid,int n)212 find_nth_pnp_device(const char *devid, int busid, int n)
213 {
214           PPC_DEVICE *ppc_dev;
215           int i, found=0;
216           uint32_t ndev, l, bid = 0;
217           char deviceid[8];
218 
219           ndev = be32toh(res->ActualNumDevices);
220           ppc_dev = res->Devices;
221           n++;
222 
223           if (busid != 0)
224                     bid = 1UL << busid;
225 
226           for (i = 0; i < ((ndev > MAX_DEVICES) ? MAX_DEVICES : ndev); i++) {
227                     DEVICE_ID *id = &ppc_dev[i].DeviceId;
228 
229                     if (bid) {
230                               printf("???\n");
231                               l = be32toh(id->BusId);
232                               if ((l & bid) == 0)
233                                         continue;
234                     }
235                     pnp_devid_to_string(id->DevId, deviceid);
236                     if (strcmp(deviceid, devid) == 0) {
237                               found++;
238                               if (found == n)
239                                         return &ppc_dev[i];
240                     }
241           }
242           return NULL;
243 }
244 
245 int
pnp_pci_busno(void * v,int * bus)246 pnp_pci_busno(void *v, int *bus)
247 {
248           struct _L4_Pack *pack = v;
249           struct _L4_PPCPack *p = &pack->L4_Data.L4_PPCPack;
250           int item, size, tag = *(unsigned char *)v;
251           unsigned char *q = v;
252 
253           item = tag_large_item_name(tag);
254           size = (q[1] | (q[2] << 8)) + 3 /* tag + length */;
255           *bus = -1;
256 
257           if (res->Revision == 0)
258                 return size;
259           if (item != LargeVendorItem)
260                     return size;
261           if (p->Type != LV_PCIBridge) /* PCI Bridge type */
262                     return size;
263 
264           *bus = p->PPCData[16];
265           return size;
266 }
267 
268 /* Get the PCI config base and addr from PNP */
269 
270 int
pnp_pci_configbase(void * v,uint32_t * addr,uint32_t * data)271 pnp_pci_configbase(void *v, uint32_t *addr, uint32_t *data)
272 {
273           struct _L4_Pack *pack = v;
274           struct _L4_PPCPack *p = &pack->L4_Data.L4_PPCPack;
275           int item, size, tag = *(unsigned char *)v;
276           unsigned char *q = v;
277 
278           item = tag_large_item_name(tag);
279           size = (q[1] | (q[2] << 8)) + 3 /* tag + length */;
280           /* init to zero so we don't return garbage values */
281           *addr = 0;
282           *data = 0;
283 
284           if (res->Revision == 0)
285                     return size;
286           if (item != LargeVendorItem)
287                     return size;
288           if (p->Type != LV_PCIBridge) /* PCI Bridge type */
289                     return size;
290 
291           *addr = (uint32_t)le64dec(&p->PPCData[0]);
292           *data = (uint32_t)le64dec(&p->PPCData[8]);
293           return size;
294 }
295 
296 #ifdef RESIDUAL_DATA_DUMP
297 
298 void
print_residual_device_info(void)299 print_residual_device_info(void)
300 {
301           VPD *vpd;
302           PPC_CPU *ppc_cpu;
303           MEM_MAP *mem_map;
304           PPC_MEM *ppc_mem;
305           PPC_DEVICE *ppc_dev;
306           const char *str;
307           unsigned long l;
308           unsigned short s;
309           unsigned long nmseg;
310           unsigned long nmem;
311           unsigned long ndev;
312           unsigned long page_size;
313           int ncpus;
314           int first;
315           int i, j;
316           char deviceid[9];
317 
318           if (!dump_residual_data)
319                     return;
320 
321           if (be32toh(res->ResidualLength) == 0)
322                     return;
323 
324           printf("ResidualLength = %ld\n", be32toh(res->ResidualLength));
325           printf("Version = %d\n", res->Version);
326           printf("Revision = %d\n", res->Revision);
327           printf("EC = %d\n", be16toh(res->EC));
328 
329           /*
330            * VPD
331            */
332           vpd = &res->VitalProductData;
333           printf("\nVPD\n");
334           printf("  PrintableModel = %-32s\n", vpd->PrintableModel);
335           printf("  Serial = %-16s\n", vpd->Serial);
336 
337           l = be32toh(vpd->FirmwareSupplier);
338           printf("  FirmwareSupplier = %s\n",
339               (l >= NELEMS(FirmwareSupplier)) ? "Unknown" : FirmwareSupplier[l]);
340           l = be32toh(vpd->FirmwareSupports);
341           printf("  FirmwareSupports = 0x%08lx\n", l);
342           for (first = 1, i = 0; i < sizeof(unsigned long) * 8; i++) {
343                     if ((l & (1UL << i)) != 0) {
344                               printf("    : %s\n", i >= NELEMS(FirmwareSupports)
345                                   ? "Unknown" : FirmwareSupports[i]);
346                                  first = 0;
347                     }
348           }
349           if (first)
350                     printf("    : None\n");
351 
352           printf("  NvramSize = %ld\n", be32toh(vpd->NvramSize));
353           printf("  NumSIMMSlots = %ld\n", be32toh(vpd->NumSIMMSlots));
354           s = be16toh(vpd->EndianSwitchMethod);
355           printf("  EndianSwitchMethod = %s\n",
356               (s >= NELEMS(EndianSwitchMethod))
357                 ? "Unknown" : EndianSwitchMethod[s]);
358           s = be16toh(vpd->SpreadIOMethod);
359           printf("  SpreadIOMethod = %s\n",
360               (s >= NELEMS(SpreadIOMethod)) ? "Unknown" : SpreadIOMethod[s]);
361           printf("  SmpIar = %ld\n", be32toh(vpd->SmpIar));
362           printf("  RAMErrLogOffset = %ld\n", be32toh(vpd->RAMErrLogOffset));
363           printf("  ProcessorHz = %ld\n", be32toh(vpd->ProcessorHz));
364           printf("  ProcessorBusHz = %ld\n", be32toh(vpd->ProcessorBusHz));
365           printf("  TimeBaseDivisor = %ld\n", be32toh(vpd->TimeBaseDivisor));
366           printf("  WordWidth = %ld\n", be32toh(vpd->WordWidth));
367           page_size = be32toh(vpd->PageSize);
368           printf("  PageSize = %ld\n", page_size);
369           printf("  CoherenceBlockSize = %ld\n",be32toh(vpd->CoherenceBlockSize));
370           printf("  GranuleSize = %ld\n", be32toh(vpd->GranuleSize));
371 
372           printf("  L1 Cache variables\n");
373           printf("    CacheSize = %ld\n", be32toh(vpd->CacheSize));
374           l = be32toh(vpd->CacheAttrib);
375           printf("    CacheAttrib = %s\n",
376               (l >= NELEMS(CacheAttrib)) ? "Unknown" : CacheAttrib[l]);
377           printf("    CacheAssoc = %ld\n", be32toh(vpd->CacheAssoc));
378           printf("    CacheLineSize = %ld\n", be32toh(vpd->CacheLineSize));
379           printf("    I-CacheSize = %ld\n", be32toh(vpd->I_CacheSize));
380           printf("    I-CacheAssoc = %ld\n", be32toh(vpd->I_CacheAssoc));
381           printf("    I-CacheLineSize = %ld\n", be32toh(vpd->I_CacheLineSize));
382           printf("    D-CacheSize = %ld\n", be32toh(vpd->D_CacheSize));
383           printf("    D-CacheAssoc = %ld\n", be32toh(vpd->D_CacheAssoc));
384           printf("    D-CacheLineSize = %ld\n", be32toh(vpd->D_CacheLineSize));
385           printf("  Translation Lookaside Buffer variables\n");
386           printf("    Number of TLB entries = %ld\n", be32toh(vpd->TLBSize));
387           l = be32toh(vpd->TLBAttrib);
388           printf("    TLBAttrib = %s\n",
389               (l >= NELEMS(TLBAttrib)) ? "Unknown" : TLBAttrib[l]);
390           printf("    TLBAssoc = %ld\n", be32toh(vpd->TLBAssoc));
391           printf("    I-TLBSize = %ld\n", be32toh(vpd->I_TLBSize));
392           printf("    I-TLBAssoc = %ld\n", be32toh(vpd->I_TLBAssoc));
393           printf("    D-TLBSize = %ld\n", be32toh(vpd->D_TLBSize));
394           printf("    D-TLBAssoc = %ld\n", be32toh(vpd->D_TLBAssoc));
395           printf("  ExtendedVPD = 0x%lx\n", be32toh(vpd->ExtendedVPD));
396 
397           /*
398            * PPC_CPU
399            */
400           printf("\n");
401           printf("MaxNumCpus = %d\n", be16toh(res->MaxNumCpus));
402           ncpus = be16toh(res->ActualNumCpus);
403           printf("ActualNumCpus = %d\n", ncpus);
404           ppc_cpu = res->Cpus;
405           for (i = 0; i < ((ncpus > MAX_CPUS) ? MAX_CPUS : ncpus); i++) {
406                     printf("%d:\n", i);
407                     printf("  CpuType = %08lx\n", be32toh(ppc_cpu[i].CpuType));
408                     printf("  CpuNumber = %d\n", ppc_cpu[i].CpuNumber);
409                     switch (ppc_cpu[i].CpuState) {
410                     case CPU_GOOD:
411                               str = "CPU is present, and active";
412                               break;
413                     case CPU_GOOD_FW:
414                               str = "CPU is present, and in firmware";
415                               break;
416                     case CPU_OFF:
417                               str = "CPU is present, but inactive";
418                               break;
419                     case CPU_FAILED:
420                               str = "CPU is present, but failed POST";
421                               break;
422                     case CPU_NOT_PRESENT:
423                               str = "CPU not present";
424                               break;
425                     default:
426                               str = "Unknown state";
427                               break;
428                     }
429                     printf("  CpuState: %s (%d)\n", str, ppc_cpu[i].CpuState);
430           }
431 
432           printf("\n");
433           printf("TotalMemory = %ld (0x%08lx)\n",
434               be32toh(res->TotalMemory) ,be32toh(res->TotalMemory));
435           printf("GoodMemory  = %ld (0x%08lx)\n",
436               be32toh(res->GoodMemory), be32toh(res->GoodMemory));
437 
438           /*
439            * MEM_MAP
440            */
441           printf("\n");
442           nmseg = be32toh(res->ActualNumMemSegs);
443           printf("ActualNumMemSegs = %ld\n", nmseg);
444           mem_map = res->Segs;
445           for (i = 0; i < ((nmseg > MAX_MEM_SEGS) ? MAX_MEM_SEGS : nmseg); i++) {
446                     unsigned long pc;
447 
448                     printf("%d:\n", i);
449                     l = be32toh(mem_map[i].Usage);
450                     printf("  Usage = ");
451                     for (first = 1, j = 0; j < sizeof(unsigned long) * 8; j++) {
452                               if ((l & (1UL << j)) != 0) {
453                                         printf("%s%s", first ? "" : ", ",
454                                             j >= NELEMS(Usage) ? "Unknown" : Usage[j]);
455                                         first = 0;
456                               }
457                     }
458                     printf(" (0x%08lx)\n", l);
459                     printf("  BasePage  = 0x%05lx000\n",
460                         be32toh(mem_map[i].BasePage));
461                     pc = be32toh(mem_map[i].PageCount);
462                     printf("  PageCount = 0x%08lx (%ld page%s)\n",
463                         page_size * pc, pc, pc == 1 ? "" : "s");
464           }
465 
466           /*
467            * PPC_MEM
468            */
469           printf("\n");
470           nmem = be32toh(res->ActualNumMemories);
471           printf("ActualNumMemories = %ld\n", nmem);
472           ppc_mem = res->Memories;
473           for (i = 0; i < ((nmem > MAX_MEMS) ? MAX_MEMS : nmem); i++) {
474                     printf("%d:\n", i);
475                     printf("  SIMMSize = %ld MB\n", be32toh(ppc_mem[i].SIMMSize));
476           }
477 
478           /*
479            * PPC_DEVICE
480            */
481           printf("\n");
482           ndev = be32toh(res->ActualNumDevices);
483           printf("ActualNumDevices = %ld\n", ndev);
484           ppc_dev = res->Devices;
485           for (i = 0; i < ((ndev > MAX_DEVICES) ? MAX_DEVICES : ndev); i++) {
486                     DEVICE_ID *id = &ppc_dev[i].DeviceId;
487                     BUS_ACCESS *bus = &ppc_dev[i].BusAccess;
488 
489                     printf("\n%d:\n", i);
490 
491                     printf("  DEVICE_ID\n");
492                     l = be32toh(id->BusId);
493                     printf("    BusId = ");
494                     for (j = 0; j < sizeof(unsigned long) * 8; j++) {
495                               if ((l & (1UL << j)) != 0) {
496                                         printf("%s",
497                                             j >= NELEMS(BusId) ? "Unknown" : BusId[j]);
498                                         break;
499                               }
500                     }
501                     printf("\n");
502                     pnp_devid_to_string(id->DevId, deviceid);
503                     printf("    DevId = 0x%08lx (%s)\n", id->DevId, deviceid);
504                     printf("    SerialNum = 0x%08lx\n", be32toh(id->SerialNum));
505                     l = be32toh(id->Flags);
506                     printf("    Flags = 0x%08lx\n", l);
507                     for (first = 1, j = 0; j < sizeof(unsigned long) * 8; j++) {
508                               if ((l & (1UL << j)) != 0) {
509                                         printf("      : %s\n",
510                                             j >= NELEMS(Flags) ? "Unknown" : Flags[j]);
511                                         first = 0;
512                               }
513                     }
514                     if (first)
515                               printf("      : None\n");
516 
517                     bustype_subr(id);
518 
519                     printf("  BUS_ACCESS\n");
520                     printf("    info0 = %d\n", bus->PnPAccess.CSN);
521                     printf("    info1 = %d\n", bus->PnPAccess.LogicalDevNumber);
522 
523                     l = be32toh(ppc_dev[i].AllocatedOffset);
524                     printf("  AllocatedOffset  = 0x%08lx\n", l);
525                     make_pnp_device_tree(res->DevicePnPHeap + l);
526 
527                     l = be32toh(ppc_dev[i].PossibleOffset);
528                     printf("  PossibleOffset   = 0x%08lx\n", l);
529                     make_pnp_device_tree(res->DevicePnPHeap + l);
530 
531                     l = be32toh(ppc_dev[i].CompatibleOffset);
532                     printf("  CompatibleOffset = 0x%08lx\n", l);
533                     make_pnp_device_tree(res->DevicePnPHeap + l);
534           }
535 }
536 
537 enum {
538           TAG_SMALL = 0,
539           TAG_LARGE
540 };
541 
542 /*--
543  * pnp device
544  */
545 static int pnp_small_pkt(void *);
546 static int pnp_large_pkt(void *);
547 
548 static void
make_pnp_device_tree(void * v)549 make_pnp_device_tree(void *v)
550 {
551           unsigned char *p = v;
552           int size;
553 
554           if (p == NULL)
555                     return;
556 
557           for (; p[0] != END_TAG; p += size) {
558                     if (tag_type(p[0]) == TAG_SMALL)
559                               size = pnp_small_pkt(p);
560                     else
561                               size = pnp_large_pkt(p);
562           }
563 }
564 
small_vendor_chipid(void * v)565 static void small_vendor_chipid(void *v)
566 {
567           ChipIDPack *p = v;
568           char chipid[8];
569           int16_t id;
570           int i, j;
571           struct _svid {
572                     int16_t id;
573                     const char *name;
574                     int type;
575           } svid[] = {
576                     { Dakota, "IBM North/South Dakota", Chip_MemCont },
577                     { Idaho,  "IBM Idaho", Chip_MemCont },
578                     { Eagle,  "Motorola Eagle", Chip_MemCont },
579                     { Kauai_Lanai,      "IBM Kauai/Lanai", Chip_MemCont },
580                     { Montana_Nevada,"IBM Montana/Nevada", Chip_MemCont },
581                     { Union,  "IBM Union", Chip_MemCont },
582                     { Cobra_Viper,      "IBM Cobra/Viper", Chip_MemCont },
583                     { Grackle,          "Motorola Grackle", Chip_MemCont },
584                     { SIO_ZB, "Intel 82378ZB", Chip_ISABridge },
585                     { FireCoral,        "IBM FireCoral", Chip_ISABridge },
586                     { Python, "IBM Python", Chip_PCIBridge },
587                     { DEC21050,         "PCI-PCI (DEC 21050)", Chip_PCIBridge },
588                     { IBM2782351,       "PCI-PCI (IBM 2782351)", Chip_PCIBridge },
589                     { IBM2782352,       "PCI-PCI (IBM 2782352)", Chip_PCIBridge },
590                     { INTEL_8236SL,     "Intel 8236SL", Chip_PCMCIABridge },
591                     { RICOH_RF5C366C,"RICOH RF5C366C", Chip_PCMCIABridge },
592                     { INTEL_82374,      "Intel 82374/82375", Chip_EISABridge },
593                     { MCACoral,         "MCA Coral", Chip_MCABridge },
594                     { Cheyenne,         "IBM Cheyenne", Chip_L2Cache },
595                     { IDT,              "IDT", Chip_L2Cache },
596                     { Sony1PB,          "Sony1PB", Chip_L2Cache },
597                     { Mamba,  "IBM Mamba", Chip_L2Cache },
598                     { Alaska, "IBM Alaska", Chip_L2Cache },
599                     { Glance, "IBM Glance", Chip_L2Cache },
600                     { Ocelot, "IBM Ocelot", Chip_L2Cache },
601                     { Carrera,          "IBM Carrera", Chip_PM },
602                     { Sig750, "Signetics 87C750", Chip_PM },
603                     { MPIC_2, "IBM MPIC-2", Chip_IntrCont },
604                     { DallasRTC,        "Dallas 1385 compatible", Chip_MiscPlanar },
605                     { Dallas1585,       "Dallas 1585 compatible", Chip_MiscPlanar },
606                     { Timer8254,        "8254-compatible timer", Chip_MiscPlanar },
607                     { HarddiskLt,       "Op Panel HD light", Chip_MiscPlanar },
608                     { 0,                NULL, -1 },
609           };
610           const char *chiptype[] = {
611                     "Memory Controller",
612                     "ISA Bridge",
613                     "PCI Bridge",
614                     "PCMCIA Bridge",
615                     "EISA Bridge",
616                     "MCA Bridge",
617                     "L2 Cache Controller",
618                     "Power Management Controller",
619                     "Interrupt Controller",
620                     "Misc. Planar Device"
621           };
622 
623           id = le16dec(&p->Name[0]);
624           snprintf(chipid, 8, "%c%c%c%0hX",
625               ((p->VendorID0 >> 2) & 0x1f) + 'A' - 1,
626               (((p->VendorID0 & 3) << 3) | ((p->VendorID1 >> 5) & 7)) + 'A' - 1,
627               (p->VendorID1 & 0x1f) + 'A' - 1, id);
628           for (i = 0, j = -1; svid[i].name != NULL; i++) {
629                     if (id == svid[i].id) {
630                               j = i;
631                               break;
632                     }
633           }
634           printf("Chip ID: %s\n", chipid);
635           if (j == -1) {
636                     printf("      Unknown Chip Type\n");
637                     return;
638           }
639           printf("      %s: %s\n", chiptype[svid[j].type], svid[j].name);
640           return;
641 }
642 
643 static int
pnp_small_pkt(void * v)644 pnp_small_pkt(void *v)
645 {
646           int tag = *(unsigned char *)v;
647           int item, size;
648           int i, j;
649           int first;
650 
651           item = tag_small_item_name(tag);
652           size = tag_small_count(tag) + 1 /* tag */;
653 
654           switch (item) {
655           case CompatibleDevice: {
656                     struct _S3_Pack *p = v;
657                     unsigned char *q = p->CompatId;
658 
659                     printf("    CompatibleDevice = %c%c%c%c%c%c%c\n",
660                         ((q[0] >> 2) & 0x1f) + 'A' - 1,
661                         (((q[0] & 0x03) << 3) | ((q[1] >> 5) & 0x07)) + 'A' - 1,
662                         (q[1] & 0x1f) + 'A' - 1,
663                         HEXDIGITS[(q[2] >> 4) & 0xf], HEXDIGITS[q[2] & 0xf],
664                         HEXDIGITS[(q[3] >> 4) & 0xf], HEXDIGITS[q[3] & 0xf]);
665                     }
666                     break;
667 
668           case IRQFormat: {
669                     struct _S4_Pack *p = v;
670 
671                     printf("    IRQ: ");
672                     for (first = 1, j = 0; j < 2; j++) {
673                               for (i = 0; i < 8; i++) {
674                                         if (p->IRQMask[j] & (1 << i)) {
675                                                   printf("%s%d",
676                                                       first ? "" : ", ", j * 8 + i);
677                                                   first = 0;
678                                         }
679                               }
680                     }
681                     if (first)
682                               printf("None ");
683 
684                     if (size == 3) {
685                               static const char *IRQInfo[] = {
686                                         "high true edge sensitive",
687                                         "low true edge sensitive",
688                                         "high true level sensitive",
689                                         "low true level sensitive",
690                               };
691 
692                               if (p->IRQInfo & 0xf0)
693                                         goto IRQout;
694 
695                               for (first = 1, i = 0; i < NELEMS(IRQInfo); i++) {
696                                         if (p->IRQInfo & (1 << i)) {
697                                                   printf("%s%s", first ? " (" : ", ",
698                                                       IRQInfo[i]);
699                                                   first = 0;
700                                         }
701                               }
702                               if (!first)
703                                         printf(")");
704                     }
705 IRQout:
706                     printf("\n");
707                     }
708                     break;
709 
710           case DMAFormat: {
711                     struct _S5_Pack *p = v;
712 
713                     printf("    DMA: ");
714                     for (first = 1, i = 0; i < 8; i++) {
715                               if (p->DMAMask & (1 << i)) {
716                                         printf("%s%d", first ? "" : ", ", i);
717                                         first = 0;
718                               }
719                     }
720                     printf("%s", first ? "None" : "");
721 
722                     printf("\n");
723                     }
724                     break;
725 
726           case StartDepFunc:
727           case EndDepFunc:
728                     break;
729 
730           case IOPort: {
731                     struct _S8_Pack *p = v;
732                     unsigned short mask;
733                     unsigned short iomin, iomax;
734                     int align, len;
735 
736                     mask = p->IOInfo & ISAAddr16bit ? 0xffff : 0x03ff;
737                     iomin = (p->RangeMin[0] | (p->RangeMin[1] << 8)) & mask;
738                     iomax = (p->RangeMax[0] | (p->RangeMax[1] << 8)) & mask;
739                     align = p->IOAlign;
740                     len = p->IONum;
741 
742                     if (len != 1) {
743                               if (iomin == iomax)
744                                         printf("    IOPort: 0x%x-0x%x",
745                                             iomin, iomin + len-1);
746                               else
747                                         printf("    IOPort: min 0x%x-0x%x,"
748                                             " max 0x%x-0x%x (%d byte%s align)",
749                                               iomin, iomin + len-1,
750                                               iomax, iomax + len-1,
751                                               align, align != 1 ? "s" : "");
752                     } else {
753                               if (iomin == iomax)
754                                         printf("    IOPort: 0x%x", iomin);
755                               else
756                                         printf("    IOPort: min 0x%x, max 0x%x"
757                                             " (%d byte%s align)",
758                                               iomin, iomax,
759                                               align, align != 1 ? "s" : "");
760                     }
761                     printf("\n");
762                     }
763                     break;
764 
765           case FixedIOPort: {
766                     struct _S9_Pack *p = v;
767                     unsigned short ioport;
768                     int len;
769 
770                     ioport = (p->Range[0] | (p->Range[1] << 8)) & 0x3ff;
771                     len = p->IONum;
772 
773                     if (len != 1)
774                               printf("    FixedIOPort: 0x%x-0x%x",
775                                   ioport, ioport + len - 1);
776                     else
777                               printf("    FixedIOPort: 0x%x", ioport);
778                     printf("\n");
779                     }
780                     break;
781 
782           case SmallVendorItem: {
783                     unsigned char *p = v;
784 
785                     printf("    SmallVendorItem: ");
786                     switch (p[1]) {
787                     case 1:
788                               small_vendor_chipid(v);
789                               break;
790 
791                     case 3:
792                               printf("Processor Number: %d\n", p[2]);
793                               break;
794 
795                     default:
796                               printf("\n");
797                               for (i = 0; i < size - 1; i++) {
798                                         if ((i % 16) == 0)
799                                                   printf("      ");
800                                         printf("%02x ", p[i + 1]);
801                                         if ((i % 16) == 15)
802                                                   printf("\n");
803                               }
804                               if ((i % 16) != 0)
805                                         printf("\n");
806                               break;
807                     }
808                     break;
809           }
810           default: {
811                     unsigned char *p = v;
812 
813                     printf("small\n");
814                     printf("item = %d\n", item);
815                     printf("size = %d\n", size);
816 
817                     for (i = 1; i < size; i++)
818                               printf("%02x ", p[i]);
819                     printf("\n");
820                     }
821                     break;
822           }
823 
824           return size;
825 }
826 
827 /*
828  * large vendor items
829  */
830 
831 static void large_vendor_default_subr(struct _L4_PPCPack *p, void *v, int size);
832 static void large_vendor_floppy_subr(struct _L4_PPCPack *p, void *v, int size);
833 static void large_vendor_l2cache_subr(struct _L4_PPCPack *p, void *v, int size);
834 static void large_vendor_pcibridge_subr(struct _L4_PPCPack *p, void *v,
835     int size);
836 static void large_vendor_bat_subr(struct _L4_PPCPack *p, void *v, int size);
837 static void large_vendor_bba_subr(struct _L4_PPCPack *p, void *v, int size);
838 static void large_vendor_scsi_subr(struct _L4_PPCPack *p, void *v, int size);
839 static void large_vendor_pms_subr(struct _L4_PPCPack *p, void *v, int size);
840 static void large_vendor_gaddr_subr(struct _L4_PPCPack *p, void *v, int size);
841 static void large_vendor_isaintr_subr(struct _L4_PPCPack *p, void *v, int size);
842 
843 static void
large_vendor_default_subr(struct _L4_PPCPack * p,void * v,int size)844 large_vendor_default_subr(struct _L4_PPCPack *p, void *v, int size)
845 {
846           int i;
847 
848           for (i = 0; i < size - 3; i++) {
849                     if ((i % 16) == 0)
850                               printf("      ");
851                     printf("%02x ", p->PPCData[i]);
852                     if ((i % 16) == 15)
853                               printf("\n");
854           }
855           if ((i % 16) != 0)
856                     printf("\n");
857 }
858 
859 static void
large_vendor_floppy_subr(struct _L4_PPCPack * p,void * v,int size)860 large_vendor_floppy_subr(struct _L4_PPCPack *p, void *v, int size)
861 {
862           int i;
863           const char *str;
864 
865           for (i = 0; i < (size - 4) / 2; i++) {
866                     switch (p->PPCData[i*2]) {
867                     case 0:
868                               str = "Not present";
869                               break;
870                     case 1:
871                               str = "3.5\" 2MiB";
872                               break;
873                     case 2:
874                               str = "3.5\" 4MiB";
875                               break;
876                     case 3:
877                               str = "5.25\" 1.6MiB";
878                               break;
879                     default:
880                               str = "Unknown type";
881                               break;
882                     }
883                     printf("      Floppy drive %d, %s", i, str);
884                     if (p->PPCData[i*2 + 1] & 0x01)
885                               printf(", Media sense");
886                     if (p->PPCData[i*2 + 1] & 0x02)
887                               printf(", Auto eject");
888                     if (p->PPCData[i*2 + 1] & 0x04)
889                               printf(", Alt speed");
890                     printf("\n");
891           }
892 }
893 
894 static void
large_vendor_l2cache_subr(struct _L4_PPCPack * p,void * v,int size)895 large_vendor_l2cache_subr(struct _L4_PPCPack *p, void *v, int size)
896 {
897           static const unsigned char *L2type[] =
898               { "None", "WriteThru", "CopyBack" };
899           static const unsigned char *L2assoc[] =
900               { "None", "DirectMapped", "2-way set" };
901           static const unsigned char *L2hw[] =
902               { "None", "Invalidate", "Flush", "Unknown" };
903 
904           printf("      %u K %s %s %s L2 cache\n"
905               "\t%hd/%hd bytes line/sector size\n",
906               le32dec(&p->PPCData[0]), L2type[p->PPCData[10]],
907               L2assoc[le16dec(&p->PPCData[4])],
908               L2hw[p->PPCData[11]], le16dec(&p->PPCData[6]),
909               le16dec(&p->PPCData[8]));
910 }
911 
912 static void
large_vendor_pcibridge_subr(struct _L4_PPCPack * p,void * v,int size)913 large_vendor_pcibridge_subr(struct _L4_PPCPack *p, void *v, int size)
914 {
915           int i, numslots;
916           char tmpstr[30];
917           PCIInfoPack *pi = v;
918           static const unsigned char *intrtype[] =
919               { "8259", "MPIC", "RS6k BUID %d" };
920 
921           /* rev 0 residual has no valid pcibridge data */
922           if (res->Revision == 0) {
923                     large_vendor_default_subr(p, v, size);
924                     return;
925           }
926           numslots = (le16dec(&pi->count0)-21)/sizeof(IntrMap);
927 
928           printf("    PCI Bridge parameters\n"
929               "      ConfigBaseAddress 0x%0" PRIx64" \n"
930               "      ConfigBaseData 0x%0" PRIx64 "\n"
931               "      Bus number %d\n",
932               le64dec(&pi->configbaseaddr), le64dec(&pi->configbasedata),
933               pi->busnum);
934 
935           printf("    PCI Bridge Slot Data\n");
936           for (i = 0; i < numslots; i++) {
937                     int j, first, l;
938                     char *t;
939 
940                     if (pi->map[i].slotnum)
941                               printf("      PCI Slot %d", pi->map[i].slotnum);
942                     else
943                               printf("      Integrated PCI device");
944                     printf(" DevFunc 0x%02x\n", pi->map[i].devfunc);
945                     for (j = 0, first = 1, t = tmpstr; j < MAX_PCI_INTRS; j++) {
946                               if (pi->map[i].intr[j] != 0xFFFF) {
947                                         if (first)
948                                                   first = 0;
949                                         else
950                                                   *t++ = '/';
951                                         *t++ = 'A' + j;
952                               }
953                     }
954                     *t = '\0';
955                     if (first)
956                               continue; /* there were no valid intrs */
957                     printf("        interrupt line(s) %s routed to", tmpstr);
958                     snprintf(tmpstr, sizeof(tmpstr),
959                         intrtype[pi->map[i].intrctrltype - 1],
960                         pi->map[i].intrctrlnum);
961                     printf(" %s line(s) ", tmpstr);
962                     for (j = 0, first = 1, l = 0; j < MAX_PCI_INTRS; j++) {
963                               int line = bswap16(pi->map[i].intr[j]);
964 
965                               if (pi->map[i].intr[j] != 0xFFFF) {
966                                         l += snprintf(tmpstr + l, sizeof(tmpstr) - l,
967                                             "%s%d(%c)", l == 0 ? "/" : "",
968                                             line & 0x7fff, line & 0x8000 ? 'E' : 'L');
969                                         if (l > sizeof(tmpstr))
970                                                   break;
971                               }
972                     }
973                     printf("%s\n", tmpstr);
974           }
975 }
976 
977 static void
large_vendor_bat_subr(struct _L4_PPCPack * p,void * v,int size)978 large_vendor_bat_subr(struct _L4_PPCPack *p, void *v, int size)
979 {
980           static const unsigned char *convtype[] =
981               { "Bus Memory", "Bus I/O", "DMA" };
982           static const unsigned char *transtype[] =
983               { "direct", "mapped", "PPC special storage segment" };
984 
985           printf("      Bridge address translation, %s decoding:\n"
986               "      Parent Base\tBus Base\tRange\t   Conversion\tTranslation\n"
987               "      0x%8.8" PRIx64 "\t0x%8.8" PRIx64 "\t0x%8.8" PRIx64
988               " %s%s%s\n",
989               p->PPCData[0] & 1 ? "positive" : "subtractive",
990               le64dec(&p->PPCData[4]), le64dec(&p->PPCData[12]),
991               le64dec(&p->PPCData[20]), convtype[p->PPCData[2] - 1],
992               p->PPCData[2] == 3 ? "\t\t" : "\t",
993               transtype[p->PPCData[1] - 1]);
994 }
995 
996 static void
large_vendor_bba_subr(struct _L4_PPCPack * p,void * v,int size)997 large_vendor_bba_subr(struct _L4_PPCPack *p, void *v, int size)
998 {
999           printf("      Bus speed %ld Hz, %d slot(s)\n",
1000               (long)le32dec(&p->PPCData), p->PPCData[4]);
1001 }
1002 
1003 static void
large_vendor_scsi_subr(struct _L4_PPCPack * p,void * v,int size)1004 large_vendor_scsi_subr(struct _L4_PPCPack *p, void *v, int size)
1005 {
1006           int i;
1007 
1008           printf("    SCSI buses: %d id(s):", p->PPCData[0]);
1009           for (i = 1; i <= p->PPCData[0]; i++)
1010                     printf("\t\t\t%d%c", p->PPCData[i],
1011                         i == p->PPCData[0] ? '\n' : ',');
1012 }
1013 
1014 static void
large_vendor_pms_subr(struct _L4_PPCPack * p,void * v,int size)1015 large_vendor_pms_subr(struct _L4_PPCPack *p, void *v, int size)
1016 {
1017           unsigned int flags;
1018           int i;
1019           static const unsigned char *power[] = {
1020               "Hibernation", "Suspend", "Laptop lid events", "Laptop battery",
1021               "Modem-triggered resume from hibernation",
1022               "Modem-triggered resume from suspend",
1023               "Timer-triggered resume from hibernation",
1024               "Timer-triggered resume from suspend",
1025               "Timer-triggered hibernation from suspend",
1026               "Software-controlled power switch", "External resume trigger",
1027               "Software main power switch can be overridden by hardware",
1028               "Resume button", "Automatic transition between states is inhibited"
1029           };
1030 
1031           printf("      Power management attributes:");
1032           flags = le32dec(&p->PPCData);
1033           if (!flags) {
1034                     printf(" (none)\n");
1035                     return;
1036           }
1037           printf("\n");
1038           for (i = 0; i < 14; i++)
1039                     if (flags & 1 << i)
1040                               printf("\t%s\n", power[i]);
1041           if (flags & 0xffffc000)
1042                     printf("\tunknown flags (0x%8.8x)\n", flags);
1043 }
1044 
1045 static void
large_vendor_gaddr_subr(struct _L4_PPCPack * p,void * v,int size)1046 large_vendor_gaddr_subr(struct _L4_PPCPack *p, void *v, int size)
1047 {
1048           static const unsigned char *addrtype[] = { "I/O", "Memory", "System" };
1049 
1050           printf("      %s address (%d bits), at 0x%" PRIx64 " size 0x%"
1051               PRIx64 " bytes\n", addrtype[p->PPCData[0] - 1], p->PPCData[1],
1052               le64dec(&p->PPCData[4]), le64dec(&p->PPCData[12]));
1053 }
1054 
1055 static void
large_vendor_isaintr_subr(struct _L4_PPCPack * p,void * v,int size)1056 large_vendor_isaintr_subr(struct _L4_PPCPack *p, void *v, int size)
1057 {
1058           int i;
1059           char tmpstr[30];
1060           static const unsigned char *inttype[] =
1061               { "8259", "MPIC", "RS6k BUID %d" };
1062 
1063           snprintf(tmpstr, sizeof(tmpstr), inttype[p->PPCData[0] - 1],
1064               p->PPCData[1]);
1065           printf("      ISA interrupts routed to %s lines\n\t", tmpstr);
1066 
1067           for (i = 0; i < 16; i++) {
1068                     int line = le16dec(&p->PPCData[2 + 2*i]);
1069 
1070                     if (line != 0xffff)
1071                               printf(" %d(IRQ%d)", line, i);
1072                     if (i == 8)
1073                               printf("\n\t");
1074           }
1075           printf("\n");
1076 }
1077 
1078 static int
pnp_large_pkt(void * v)1079 pnp_large_pkt(void *v)
1080 {
1081           int tag = *(unsigned char *)v;
1082           unsigned char *q = v;
1083           int item, size;
1084           int i;
1085           static struct large_vendor_type {
1086                     const char          *str;
1087                     void      (*func)(struct _L4_PPCPack *p, void *vv, int sz);
1088           } Large_Vendor_Type[] = {
1089                     { "None",                     NULL },
1090                     { "Diskette Drive",           large_vendor_floppy_subr },
1091                     { "L2 Cache",                           large_vendor_l2cache_subr },
1092                     { "PCI Bridge",                         large_vendor_pcibridge_subr },
1093                     { "Display",                            large_vendor_default_subr },
1094                     { "Bridge Address Translation",         large_vendor_bat_subr },
1095                     { "Bus Bridge Attributes",    large_vendor_bba_subr },
1096                     { "SCSI Controller Information",large_vendor_scsi_subr },
1097                     { "Power Management Support", large_vendor_pms_subr },
1098                     { "Generic Address",                    large_vendor_gaddr_subr },
1099                     { "ISA Bridge Information",   large_vendor_isaintr_subr },
1100                     { "Video Channels",           large_vendor_default_subr },
1101                     { "Power Control",            large_vendor_default_subr },
1102                     { "Memory SIMM PD Data",      large_vendor_default_subr },
1103                     { "System Interrupts",                  large_vendor_default_subr },
1104                     { "Error Log",                          large_vendor_default_subr },
1105                     { "Extended VPD",             large_vendor_default_subr },
1106                     { "Timebase Control",                   large_vendor_default_subr },
1107           };
1108 
1109           item = tag_large_item_name(tag);
1110           size = (q[1] | (q[2] << 8)) + 3 /* tag + length */;
1111 
1112           switch (item) {
1113           case LargeVendorItem: {
1114                     struct _L4_Pack *pack = v;
1115                     struct _L4_PPCPack *p =  &pack->L4_Data.L4_PPCPack;
1116 
1117                     printf("    LargeVendorItem: %s\n",
1118                         Large_Vendor_Type[p->Type].str);
1119                     if (p->Type <= 17 && Large_Vendor_Type[p->Type].func != NULL)
1120                               (*Large_Vendor_Type[p->Type].func)(p, v, size);
1121                     break;
1122           }
1123           case MemoryRange: {
1124                     struct _L1_Pack *pack = v;
1125 
1126                     printf("    Memory Range:\n");
1127                     if (pack->Data[0] & L1_Shadow)
1128                               printf("      Memory is shadowable\n");
1129                     if (pack->Data[0] & L1_32bit_mem)
1130                               printf("      32-bit memory only\n");
1131                     if (pack->Data[0] & L1_8_16bit_mem)
1132                               printf("      8-bit and 16-bit supported\n");
1133                     if (pack->Data[0] & L1_Decode_Hi)
1134                               printf("      decode supports high address\n");
1135                     if (pack->Data[0] & L1_Cache)
1136                               printf("      read cacheable, write-through\n");
1137                     if (pack->Data[0] & L1_Writable)
1138                               printf("      Memory is writable\n");
1139 
1140                     if (pack->Count0 >= 0x9) {
1141                               printf("      minbase : 0x%x\n",
1142                                   (pack->Data[2] << 16) | (pack->Data[1] << 8));
1143                               printf("      maxbase : 0x%x\n",
1144                                   (pack->Data[4] << 16) | (pack->Data[3] << 8));
1145                               printf("      align   : 0x%x\n",
1146                                   (pack->Data[6] << 8) | pack->Data[5]);
1147                               printf("      length  : 0x%x\n",
1148                                   (pack->Data[8] << 16) | (pack->Data[7] << 8));
1149                     }
1150                     break;
1151           }
1152 
1153           default: {
1154                     unsigned char *p = v;
1155 
1156                     printf("large\n");
1157                     printf("item = %d\n", item);
1158                     printf("size = %d\n", size);
1159 
1160                     for (i = 3; i < size; i++)
1161                               printf("%02x ", p[i]);
1162                     printf("\n");
1163                     }
1164                     break;
1165           }
1166 
1167           return size;
1168 }
1169 
1170 /*--
1171  * bus type
1172  */
1173 static void mass_subr(DEVICE_ID *);
1174 static void nic_subr(DEVICE_ID *);
1175 static void display_subr(DEVICE_ID *);
1176 static void mm_subr(DEVICE_ID *);
1177 static void mem_subr(DEVICE_ID *);
1178 static void bridge_subr(DEVICE_ID *);
1179 static void comm_subr(DEVICE_ID *);
1180 static void sys_subr(DEVICE_ID *);
1181 static void input_subr(DEVICE_ID *);
1182 static void service_subr(DEVICE_ID *);
1183 
1184 static void
bustype_subr(DEVICE_ID * id)1185 bustype_subr(DEVICE_ID *id)
1186 {
1187           static struct bustype {
1188                     const char          *str;
1189                     void      (*func)(DEVICE_ID *);
1190           } BaseType[] = {
1191                     { "Reserved"                            , NULL },
1192                     { "MassStorageDevice"                   , mass_subr },
1193                     { "NetworkInterfaceController"          , nic_subr },
1194                     { "DisplayController"                   , display_subr },
1195                     { "MultimediaController"      , mm_subr },
1196                     { "MemoryController"                    , mem_subr },
1197                     { "BridgeController"                    , bridge_subr },
1198                     { "CommunicationsDevice"      , comm_subr },
1199                     { "SystemPeripheral"                    , sys_subr },
1200                     { "InputDevice"                         , input_subr },
1201                     { "ServiceProcessor"                    , service_subr },
1202           };
1203           int type;
1204 
1205           type = (id->BaseType >= NELEMS(BaseType)) ? 0 : id->BaseType;
1206 
1207           printf("    BaseType = %s (%d)\n", BaseType[type].str, id->BaseType);
1208           if (BaseType[type].func != NULL)
1209                     (*BaseType[type].func)(id);
1210 }
1211 
1212 static void
mass_subr(DEVICE_ID * id)1213 mass_subr(DEVICE_ID *id)
1214 {
1215           static const char *IDEController_tabel[] = {
1216                     "GeneralIDE",
1217                     "ATACompatible",
1218           };
1219           static const char *FloppyController_table[] = {
1220                     "GeneralFloppy",
1221                     "Compatible765",
1222                     "NS398_Floppy",
1223                     "NS26E_Floppy",
1224                     "NS15C_Floppy",
1225                     "NS2E_Floppy",
1226                     "CHRP_Floppy",
1227           };
1228           const char *p, *q = NULL;
1229 
1230           switch (id->SubType) {
1231           case SCSIController:
1232                     p = "SCSIController";
1233                     q = "GeneralSCSI";
1234                     break;
1235           case IDEController:
1236                     p = "IDEController";
1237                     q = id->Interface >= NELEMS(IDEController_tabel)
1238                         ? NULL : IDEController_tabel[id->Interface];
1239                     break;
1240           case FloppyController:
1241                     p = "FloppyController";
1242                     q = id->Interface >= NELEMS(FloppyController_table)
1243                         ? NULL : FloppyController_table[id->Interface];
1244                     break;
1245           case IPIController:
1246                     p = "IPIController";
1247                     q = "GeneralIPI";
1248                     break;
1249           case OtherMassStorageController:
1250                     p = "OtherMassStorageController";
1251                     break;
1252           default:
1253                     p = "UnknownStorageController";
1254                     break;
1255           }
1256 
1257           printf("    SubType = %s (%d)\n", p, id->SubType);
1258           printf("    Interface = %s (%d)\n", q ? q : "None", id->Interface);
1259 }
1260 
1261 static void
nic_subr(DEVICE_ID * id)1262 nic_subr(DEVICE_ID *id)
1263 {
1264           const char *p, *q = NULL;
1265 
1266           switch (id->SubType) {
1267           case EthernetController:
1268                     p = "EthernetController";
1269                     q = "GeneralEther";
1270                     break;
1271           case TokenRingController:
1272                     p = "TokenRingController";
1273                     q = "GeneralToken";
1274                     break;
1275           case FDDIController:
1276                     p = "FDDIController";
1277                     q = "GeneralFDDI";
1278                     break;
1279           case OtherNetworkController:
1280                     p = "OtherNetworkController";
1281                     break;
1282           default:
1283                     p = "UnknownNetworkController";
1284                     break;
1285           }
1286 
1287           printf("    SubType = %s (%d)\n", p, id->SubType);
1288           printf("    Interface = %s (%d)\n", q ? q : "None", id->Interface);
1289 }
1290 
1291 static void
display_subr(DEVICE_ID * id)1292 display_subr(DEVICE_ID *id)
1293 {
1294           const char *p, *q = NULL;
1295 
1296           switch (id->SubType) {
1297           case VGAController:
1298                     p = "VGAController";
1299                     q = "GeneralVGA";
1300                     break;
1301           case SVGAController:
1302                     p = "SVGAController";
1303                     q = "GeneralSVGA";
1304                     break;
1305           case XGAController:
1306                     p = "XGAController";
1307                     q = "GeneralXGA";
1308                     break;
1309           case OtherDisplayController:
1310                     p = "OtherDisplayController";
1311                     break;
1312           default:
1313                     p = "UnknownDisplayController";
1314                     break;
1315           }
1316 
1317           printf("    SubType = %s (%d)\n", p, id->SubType);
1318           printf("    Interface = %s (%d)\n", q ? q : "None", id->Interface);
1319 }
1320 
1321 static void
mm_subr(DEVICE_ID * id)1322 mm_subr(DEVICE_ID *id)
1323 {
1324           static const char *AudioController_table[] = {
1325                     "GeneralAudio",
1326                     "CS4232Audio",
1327           };
1328           const char *p, *q = NULL;
1329 
1330           switch (id->SubType) {
1331           case VideoController:
1332                     p = "VideoController";
1333                     q = "GeneralVideo";
1334                     break;
1335           case AudioController:
1336                     p = "AudioController";
1337                     q = id->Interface >= NELEMS(AudioController_table)
1338                         ? NULL : AudioController_table[id->Interface];
1339                     break;
1340           case OtherMultimediaController:
1341                     p = "OtherMultimediaController";
1342                     break;
1343           default:
1344                     p = "UnknownMultimediaController";
1345                     break;
1346           }
1347 
1348           printf("    SubType = %s (%d)\n", p, id->SubType);
1349           printf("    Interface = %s (%d)\n", q ? q : "None", id->Interface);
1350 }
1351 
1352 static void
mem_subr(DEVICE_ID * id)1353 mem_subr(DEVICE_ID *id)
1354 {
1355           const char *p, *q = NULL;
1356 
1357           switch (id->SubType) {
1358           case RAM:
1359                     p = "RAM";
1360                     q = "GeneralRAM";
1361                     break;
1362           case FLASH:
1363                     p = "FLASH";
1364                     q = "GeneralFLASH";
1365                     break;
1366           case OtherMemoryDevice:
1367                     p = "OtherMemoryDevice";
1368                     break;
1369           default:
1370                     p = "UnknownMemoryDevice";
1371                     break;
1372           }
1373 
1374           printf("    SubType = %s (%d)\n", p, id->SubType);
1375           printf("    Interface = %s (%d)\n", q ? q : "None", id->Interface);
1376 }
1377 
1378 static void
bridge_subr(DEVICE_ID * id)1379 bridge_subr(DEVICE_ID *id)
1380 {
1381           static const char *PCIBridge_table[] = {
1382                     "GeneralPCIBridge",
1383                     "PCIBridgeIndirect",
1384                     "PCIBridgeRS6K",
1385           };
1386           const char *p, *q = NULL;
1387 
1388           switch (id->SubType) {
1389           case HostProcessorBridge:
1390                     p = "HostProcessorBridge";
1391                     q = "GeneralHostBridge";
1392                     break;
1393           case ISABridge:
1394                     p = "ISABridge";
1395                     q = "GeneralISABridge";
1396                     break;
1397           case EISABridge:
1398                     p = "EISABridge";
1399                     q = "GeneralEISABridge";
1400                     break;
1401           case MicroChannelBridge:
1402                     p = "MicroChannelBridge";
1403                     q = "GeneralMCABridge";
1404                     break;
1405           case PCIBridge:
1406                     p = "PCIBridge";
1407                     q = id->Interface >= NELEMS(PCIBridge_table)
1408                         ? NULL : PCIBridge_table[id->Interface];
1409                     break;
1410           case PCMCIABridge:
1411                     p = "PCMCIABridge";
1412                     q = "GeneralPCMCIABridge";
1413                     break;
1414           case VMEBridge:
1415                     p = "VMEBridge";
1416                     q = "GeneralVMEBridge";
1417                     break;
1418           case OtherBridgeDevice:
1419                     p = "OtherBridgeDevice";
1420                     break;
1421           default:
1422                     p = "UnknownBridgeDevice";
1423                     break;
1424           }
1425 
1426           printf("    SubType = %s (%d)\n", p, id->SubType);
1427           printf("    Interface = %s (%d)\n", q ? q : "None", id->Interface);
1428 }
1429 
1430 static void
comm_subr(DEVICE_ID * id)1431 comm_subr(DEVICE_ID *id)
1432 {
1433           static const char *RS232Device_table[] = {
1434                     "GeneralRS232",
1435                     "COMx",
1436                     "Compatible16450",
1437                     "Compatible16550",
1438                     "NS398SerPort",
1439                     "NS26ESerPort",
1440                     "NS15CSerPort",
1441                     "NS2ESerPort",
1442           };
1443           static const char *ATCompatibleParallelPort_table[] = {
1444                     "GeneralParPort",
1445                     "LPTx",
1446                     "NS398ParPort",
1447                     "NS26EParPort",
1448                     "NS15CParPort",
1449                     "NS2EParPort",
1450           };
1451           const char *p, *q = NULL;
1452 
1453           switch (id->SubType) {
1454           case RS232Device:
1455                     p = "RS232Device";
1456                     q = id->Interface >= NELEMS(RS232Device_table)
1457                         ? NULL : RS232Device_table[id->Interface];
1458                     break;
1459           case ATCompatibleParallelPort:
1460                     p = "ATCompatibleParallelPort";
1461                     q = id->Interface >= NELEMS(ATCompatibleParallelPort_table)
1462                         ? NULL : ATCompatibleParallelPort_table[id->Interface];
1463                     break;
1464           case OtherCommunicationsDevice:
1465                     p = "OtherCommunicationsDevice";
1466                     break;
1467           default:
1468                     p = "UnknownCommunicationsDevice";
1469                     break;
1470           }
1471 
1472           printf("    SubType = %s (%d)\n", p, id->SubType);
1473           printf("    Interface = %s (%d)\n", q ? q : "None", id->Interface);
1474 }
1475 
1476 static void
sys_subr(DEVICE_ID * id)1477 sys_subr(DEVICE_ID *id)
1478 {
1479           static const char *PIC_table[] = {
1480                     "GeneralPIC",
1481                     "ISA_PIC",
1482                     "EISA_PIC",
1483                     "MPIC",
1484                     "RS6K_PIC",
1485           };
1486           static const char *DMAController_table[] = {
1487                     "GeneralDMA",
1488                     "ISA_DMA",
1489                     "EISA_DMA",
1490           };
1491           static const char *SystemTimer_table[] = {
1492                     "GeneralTimer",
1493                     "ISA_Timer",
1494                     "EISA_Timer",
1495           };
1496           static const char *RealTimeClock_table[] = {
1497                     "GeneralRTC",
1498                     "ISA_RTC",
1499           };
1500           static const char *L2Cache_table[] = {
1501                     "None",
1502                     "StoreThruOnly",
1503                     "StoreInEnabled",
1504                     "RS6KL2Cache",
1505           };
1506           static const char *NVRAM_table[] = {
1507                     "IndirectNVRAM",
1508                     "DirectNVRAM",
1509                     "IndirectNVRAM24",
1510           };
1511           static const char *PowerManagement_table[] = {
1512                     "GeneralPowerManagement",
1513                     "EPOWPowerManagement",
1514                     "PowerControl",
1515           };
1516           static const char *GraphicAssist_table[] = {
1517                     "Unknown",
1518                     "TransferData",
1519                     "IGMC32",
1520                     "IGMC64",
1521           };
1522           static const char *OperatorPanel_table[] = {
1523                     "GeneralOPPanel",
1524                     "HarddiskLight",
1525                     "CDROMLight",
1526                     "PowerLight",
1527                     "KeyLock",
1528                     "ANDisplay",
1529                     "SystemStatusLED",
1530                     "CHRP_SystemStatusLED",
1531           };
1532           const char *p, *q = NULL;
1533 
1534           switch (id->SubType) {
1535           case ProgrammableInterruptController:
1536                     p = "ProgrammableInterruptController";
1537                     q = id->Interface >= NELEMS(PIC_table)
1538                         ? NULL : PIC_table[id->Interface];
1539                     break;
1540           case DMAController:
1541                     p = "DMAController";
1542                     q = id->Interface >= NELEMS(DMAController_table)
1543                         ? NULL : DMAController_table[id->Interface];
1544                     break;
1545           case SystemTimer:
1546                     p = "SystemTimer";
1547                     q = id->Interface >= NELEMS(SystemTimer_table)
1548                         ? NULL : SystemTimer_table[id->Interface];
1549                     break;
1550           case RealTimeClock:
1551                     p = "RealTimeClock";
1552                     q = id->Interface >= NELEMS(RealTimeClock_table)
1553                         ? NULL : RealTimeClock_table[id->Interface];
1554                     break;
1555           case L2Cache:
1556                     p = "L2Cache";
1557                     q = id->Interface >= NELEMS(L2Cache_table)
1558                         ? NULL : L2Cache_table[id->Interface];
1559                     break;
1560           case NVRAM:
1561                     p = "NVRAM";
1562                     q = id->Interface >= NELEMS(NVRAM_table)
1563                         ? NULL : NVRAM_table[id->Interface];
1564                     break;
1565           case PowerManagement:
1566                     p = "PowerManagement";
1567                     q = id->Interface >= NELEMS(PowerManagement_table)
1568                         ? NULL : PowerManagement_table[id->Interface];
1569                     break;
1570           case CMOS:
1571                     p = "CMOS";
1572                     q = "GeneralCMOS";
1573                     break;
1574           case OperatorPanel:
1575                     p = "OperatorPanel";
1576                     q = id->Interface >= NELEMS(OperatorPanel_table)
1577                         ? NULL : OperatorPanel_table[id->Interface];
1578                     break;
1579           case ServiceProcessorClass1:
1580                     p = "ServiceProcessorClass1";
1581                     q = "GeneralServiceProcessor";
1582                     break;
1583           case ServiceProcessorClass2:
1584                     p = "ServiceProcessorClass2";
1585                     q = "GeneralServiceProcessor";
1586                     break;
1587           case ServiceProcessorClass3:
1588                     p = "ServiceProcessorClass3";
1589                     q = "GeneralServiceProcessor";
1590                     break;
1591           case GraphicAssist:
1592                     p = "GraphicAssist";
1593                     q = id->Interface >= NELEMS(GraphicAssist_table)
1594                         ? NULL : GraphicAssist_table[id->Interface];
1595                     break;
1596           case SystemPlanar:
1597                     p = "SystemPlanar";
1598                     q = "GeneralSystemPlanar";
1599                     break;
1600           case OtherSystemPeripheral:
1601                     p = "OtherSystemPeripheral";
1602                     break;
1603           default:
1604                     p = "UnknownSystemPeripheral";
1605                     break;
1606           }
1607 
1608           printf("    SubType = %s (%d)\n", p, id->SubType);
1609           printf("    Interface = %s (%d)\n", q ? q : "None", id->Interface);
1610 }
1611 
1612 static void
input_subr(DEVICE_ID * id)1613 input_subr(DEVICE_ID *id)
1614 {
1615           const char *p, *q = NULL;
1616 
1617           switch (id->SubType) {
1618           case KeyboardController:
1619                     p = "KeyboardController";
1620                     break;
1621           case Digitizer:
1622                     p = "Digitizer";
1623                     break;
1624           case MouseController:
1625                     p = "MouseController";
1626                     break;
1627           case TabletController:
1628                     p = "TabletController";
1629                     break;
1630           case OtherInputController:
1631                     p = "OtherInputController";
1632                     break;
1633           default:
1634                     p = "UnknownInputController";
1635                     break;
1636           }
1637 
1638           printf("    SubType = %s (%d)\n", p, id->SubType);
1639           printf("    Interface = %s (%d)\n", q ? q : "None", id->Interface);
1640 }
1641 
1642 static void
service_subr(DEVICE_ID * id)1643 service_subr(DEVICE_ID *id)
1644 {
1645           const char *p, *q = NULL;
1646 
1647           switch (id->SubType) {
1648           case ServiceProcessorClass1:
1649                     p = "ServiceProcessorClass1";
1650                     break;
1651           case ServiceProcessorClass2:
1652                     p = "ServiceProcessorClass2";
1653                     break;
1654           case ServiceProcessorClass3:
1655                     p = "ServiceProcessorClass3";
1656                     break;
1657           default:
1658                     p = "UnknownServiceProcessor";
1659                     break;
1660           }
1661 
1662           printf("    SubType = %s (%d)\n", p, id->SubType);
1663           printf("    Interface = %s (%d)\n", q ? q : "None", id->Interface);
1664 }
1665 
1666 #endif /* RESIDUAL_DATA_DUMP */
1667