#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: residual.c,v 1.19 2023/11/24 16:49:59 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/inttypes.h>
#include <machine/residual.h>
#include <machine/pnp.h>
#include "opt_residual.h"
#ifdef RESIDUAL_DATA_DUMP
#include <machine/chpidpnp.h>
#include <machine/pcipnp.h>
static void make_pnp_device_tree(void *);
static void bustype_subr(DEVICE_ID *);
int dump_residual_data = 1;
#define NELEMS(array) ((size_t)(sizeof(array)/sizeof(array[0])))
static const char *FirmwareSupplier[] = {
"IBMFirmware",
"MotoFirmware",
"FirmWorks",
"Bull",
};
static const char *FirmwareSupports[] = {
"Conventional",
"OpenFirmware",
"Diagnostics",
"LowDebug",
"Multiboot",
"LowClient",
"Hex41",
"FAT",
"ISO9660",
"SCSI_InitiatorID_Override",
"Tape_Boot",
"FW_Boot_Path",
};
static const char *EndianSwitchMethod[] = {
"Unknown",
"UsePort92",
"UsePCIConfigA8",
"UseFF001030",
};
static const char *SpreadIOMethod[] = {
"UsePort850",
};
static const char *CacheAttrib[] = {
"No cache",
"Split cache",
"Combined cache",
};
static const char *TLBAttrib[] = {
"No TLB",
"Split TLB",
"Combined TLB",
};
static const char *Usage[] = {
"FirmwareStack",
"FirmwareHeap",
"FirmwareCode",
"BootImage",
"Free",
"Unpopulated",
"ISAAddr",
"PCIConfig",
"PCIAddr",
"SystemRegs",
"SystemIO",
"IOMemory",
"UnPopSystemROM",
"SystemROM",
"ResumeBlock",
"Other",
};
static const char *BusId[] = {
"ISA",
"EISA",
"PCI",
"PCMCIA",
"ISAPNP",
"MCA",
"MX",
"PROCESSOR",
"VME",
};
static const char *Flags[] = {
"Output",
"Input",
"ConsoleOut",
"ConsoleIn",
"Removable",
"ReadOnly",
"PowerManaged",
"Disableable",
"Configurable",
"Boot",
"Dock",
"Static",
"Failed",
"Integrated",
"Enabled",
};
#endif
void
pnp_devid_to_string(uint32_t devid, char *s)
{
uint8_t p[4];
uint32_t l;
if (res->Revision == 0)
l = le32toh(devid);
else
l = be32toh(devid);
p[0] = (l >> 24) & 0xff;
p[1] = (l >> 16) & 0xff;
p[2] = (l >> 8) & 0xff;
p[3] = l & 0xff;
*s++ = ((p[0] >> 2) & 0x1f) + 'A' - 1;
*s++ = (((p[0] & 0x03) << 3) | ((p[1] >> 5) & 0x07)) + 'A' - 1;
*s++ = (p[1] & 0x1f) + 'A' - 1;
*s++ = HEXDIGITS[(p[2] >> 4) & 0xf];
*s++ = HEXDIGITS[p[2] & 0xf];
*s++ = HEXDIGITS[(p[3] >> 4) & 0xf];
*s++ = HEXDIGITS[p[3] & 0xf];
*s = '\0';
}
int
count_pnp_devices(const char *devid)
{
PPC_DEVICE *ppc_dev;
int i, found=0;
uint32_t ndev;
char deviceid[8];
ndev = be32toh(res->ActualNumDevices);
ppc_dev = res->Devices;
for (i = 0; i < ((ndev > MAX_DEVICES) ? MAX_DEVICES : ndev); i++) {
DEVICE_ID *id = &ppc_dev[i].DeviceId;
pnp_devid_to_string(id->DevId, deviceid);
if (strcmp(deviceid, devid) == 0)
found++;
}
return found;
}
PPC_DEVICE *
find_nth_pnp_device(const char *devid, int busid, int n)
{
PPC_DEVICE *ppc_dev;
int i, found=0;
uint32_t ndev, l, bid = 0;
char deviceid[8];
ndev = be32toh(res->ActualNumDevices);
ppc_dev = res->Devices;
n++;
if (busid != 0)
bid = 1UL << busid;
for (i = 0; i < ((ndev > MAX_DEVICES) ? MAX_DEVICES : ndev); i++) {
DEVICE_ID *id = &ppc_dev[i].DeviceId;
if (bid) {
printf("???\n");
l = be32toh(id->BusId);
if ((l & bid) == 0)
continue;
}
pnp_devid_to_string(id->DevId, deviceid);
if (strcmp(deviceid, devid) == 0) {
found++;
if (found == n)
return &ppc_dev[i];
}
}
return NULL;
}
int
pnp_pci_busno(void *v, int *bus)
{
struct _L4_Pack *pack = v;
struct _L4_PPCPack *p = &pack->L4_Data.L4_PPCPack;
int item, size, tag = *(unsigned char *)v;
unsigned char *q = v;
item = tag_large_item_name(tag);
size = (q[1] | (q[2] << 8)) + 3 ;
*bus = -1;
if (res->Revision == 0)
return size;
if (item != LargeVendorItem)
return size;
if (p->Type != LV_PCIBridge)
return size;
*bus = p->PPCData[16];
return size;
}
int
pnp_pci_configbase(void *v, uint32_t *addr, uint32_t *data)
{
struct _L4_Pack *pack = v;
struct _L4_PPCPack *p = &pack->L4_Data.L4_PPCPack;
int item, size, tag = *(unsigned char *)v;
unsigned char *q = v;
item = tag_large_item_name(tag);
size = (q[1] | (q[2] << 8)) + 3 ;
*addr = 0;
*data = 0;
if (res->Revision == 0)
return size;
if (item != LargeVendorItem)
return size;
if (p->Type != LV_PCIBridge)
return size;
*addr = (uint32_t)le64dec(&p->PPCData[0]);
*data = (uint32_t)le64dec(&p->PPCData[8]);
return size;
}
#ifdef RESIDUAL_DATA_DUMP
void
print_residual_device_info(void)
{
VPD *vpd;
PPC_CPU *ppc_cpu;
MEM_MAP *mem_map;
PPC_MEM *ppc_mem;
PPC_DEVICE *ppc_dev;
const char *str;
unsigned long l;
unsigned short s;
unsigned long nmseg;
unsigned long nmem;
unsigned long ndev;
unsigned long page_size;
int ncpus;
int first;
int i, j;
char deviceid[9];
if (!dump_residual_data)
return;
if (be32toh(res->ResidualLength) == 0)
return;
printf("ResidualLength = %ld\n", be32toh(res->ResidualLength));
printf("Version = %d\n", res->Version);
printf("Revision = %d\n", res->Revision);
printf("EC = %d\n", be16toh(res->EC));
vpd = &res->VitalProductData;
printf("\nVPD\n");
printf(" PrintableModel = %-32s\n", vpd->PrintableModel);
printf(" Serial = %-16s\n", vpd->Serial);
l = be32toh(vpd->FirmwareSupplier);
printf(" FirmwareSupplier = %s\n",
(l >= NELEMS(FirmwareSupplier)) ? "Unknown" : FirmwareSupplier[l]);
l = be32toh(vpd->FirmwareSupports);
printf(" FirmwareSupports = 0x%08lx\n", l);
for (first = 1, i = 0; i < sizeof(unsigned long) * 8; i++) {
if ((l & (1UL << i)) != 0) {
printf(" : %s\n", i >= NELEMS(FirmwareSupports)
? "Unknown" : FirmwareSupports[i]);
first = 0;
}
}
if (first)
printf(" : None\n");
printf(" NvramSize = %ld\n", be32toh(vpd->NvramSize));
printf(" NumSIMMSlots = %ld\n", be32toh(vpd->NumSIMMSlots));
s = be16toh(vpd->EndianSwitchMethod);
printf(" EndianSwitchMethod = %s\n",
(s >= NELEMS(EndianSwitchMethod))
? "Unknown" : EndianSwitchMethod[s]);
s = be16toh(vpd->SpreadIOMethod);
printf(" SpreadIOMethod = %s\n",
(s >= NELEMS(SpreadIOMethod)) ? "Unknown" : SpreadIOMethod[s]);
printf(" SmpIar = %ld\n", be32toh(vpd->SmpIar));
printf(" RAMErrLogOffset = %ld\n", be32toh(vpd->RAMErrLogOffset));
printf(" ProcessorHz = %ld\n", be32toh(vpd->ProcessorHz));
printf(" ProcessorBusHz = %ld\n", be32toh(vpd->ProcessorBusHz));
printf(" TimeBaseDivisor = %ld\n", be32toh(vpd->TimeBaseDivisor));
printf(" WordWidth = %ld\n", be32toh(vpd->WordWidth));
page_size = be32toh(vpd->PageSize);
printf(" PageSize = %ld\n", page_size);
printf(" CoherenceBlockSize = %ld\n",be32toh(vpd->CoherenceBlockSize));
printf(" GranuleSize = %ld\n", be32toh(vpd->GranuleSize));
printf(" L1 Cache variables\n");
printf(" CacheSize = %ld\n", be32toh(vpd->CacheSize));
l = be32toh(vpd->CacheAttrib);
printf(" CacheAttrib = %s\n",
(l >= NELEMS(CacheAttrib)) ? "Unknown" : CacheAttrib[l]);
printf(" CacheAssoc = %ld\n", be32toh(vpd->CacheAssoc));
printf(" CacheLineSize = %ld\n", be32toh(vpd->CacheLineSize));
printf(" I-CacheSize = %ld\n", be32toh(vpd->I_CacheSize));
printf(" I-CacheAssoc = %ld\n", be32toh(vpd->I_CacheAssoc));
printf(" I-CacheLineSize = %ld\n", be32toh(vpd->I_CacheLineSize));
printf(" D-CacheSize = %ld\n", be32toh(vpd->D_CacheSize));
printf(" D-CacheAssoc = %ld\n", be32toh(vpd->D_CacheAssoc));
printf(" D-CacheLineSize = %ld\n", be32toh(vpd->D_CacheLineSize));
printf(" Translation Lookaside Buffer variables\n");
printf(" Number of TLB entries = %ld\n", be32toh(vpd->TLBSize));
l = be32toh(vpd->TLBAttrib);
printf(" TLBAttrib = %s\n",
(l >= NELEMS(TLBAttrib)) ? "Unknown" : TLBAttrib[l]);
printf(" TLBAssoc = %ld\n", be32toh(vpd->TLBAssoc));
printf(" I-TLBSize = %ld\n", be32toh(vpd->I_TLBSize));
printf(" I-TLBAssoc = %ld\n", be32toh(vpd->I_TLBAssoc));
printf(" D-TLBSize = %ld\n", be32toh(vpd->D_TLBSize));
printf(" D-TLBAssoc = %ld\n", be32toh(vpd->D_TLBAssoc));
printf(" ExtendedVPD = 0x%lx\n", be32toh(vpd->ExtendedVPD));
printf("\n");
printf("MaxNumCpus = %d\n", be16toh(res->MaxNumCpus));
ncpus = be16toh(res->ActualNumCpus);
printf("ActualNumCpus = %d\n", ncpus);
ppc_cpu = res->Cpus;
for (i = 0; i < ((ncpus > MAX_CPUS) ? MAX_CPUS : ncpus); i++) {
printf("%d:\n", i);
printf(" CpuType = %08lx\n", be32toh(ppc_cpu[i].CpuType));
printf(" CpuNumber = %d\n", ppc_cpu[i].CpuNumber);
switch (ppc_cpu[i].CpuState) {
case CPU_GOOD:
str = "CPU is present, and active";
break;
case CPU_GOOD_FW:
str = "CPU is present, and in firmware";
break;
case CPU_OFF:
str = "CPU is present, but inactive";
break;
case CPU_FAILED:
str = "CPU is present, but failed POST";
break;
case CPU_NOT_PRESENT:
str = "CPU not present";
break;
default:
str = "Unknown state";
break;
}
printf(" CpuState: %s (%d)\n", str, ppc_cpu[i].CpuState);
}
printf("\n");
printf("TotalMemory = %ld (0x%08lx)\n",
be32toh(res->TotalMemory) ,be32toh(res->TotalMemory));
printf("GoodMemory = %ld (0x%08lx)\n",
be32toh(res->GoodMemory), be32toh(res->GoodMemory));
printf("\n");
nmseg = be32toh(res->ActualNumMemSegs);
printf("ActualNumMemSegs = %ld\n", nmseg);
mem_map = res->Segs;
for (i = 0; i < ((nmseg > MAX_MEM_SEGS) ? MAX_MEM_SEGS : nmseg); i++) {
unsigned long pc;
printf("%d:\n", i);
l = be32toh(mem_map[i].Usage);
printf(" Usage = ");
for (first = 1, j = 0; j < sizeof(unsigned long) * 8; j++) {
if ((l & (1UL << j)) != 0) {
printf("%s%s", first ? "" : ", ",
j >= NELEMS(Usage) ? "Unknown" : Usage[j]);
first = 0;
}
}
printf(" (0x%08lx)\n", l);
printf(" BasePage = 0x%05lx000\n",
be32toh(mem_map[i].BasePage));
pc = be32toh(mem_map[i].PageCount);
printf(" PageCount = 0x%08lx (%ld page%s)\n",
page_size * pc, pc, pc == 1 ? "" : "s");
}
printf("\n");
nmem = be32toh(res->ActualNumMemories);
printf("ActualNumMemories = %ld\n", nmem);
ppc_mem = res->Memories;
for (i = 0; i < ((nmem > MAX_MEMS) ? MAX_MEMS : nmem); i++) {
printf("%d:\n", i);
printf(" SIMMSize = %ld MB\n", be32toh(ppc_mem[i].SIMMSize));
}
printf("\n");
ndev = be32toh(res->ActualNumDevices);
printf("ActualNumDevices = %ld\n", ndev);
ppc_dev = res->Devices;
for (i = 0; i < ((ndev > MAX_DEVICES) ? MAX_DEVICES : ndev); i++) {
DEVICE_ID *id = &ppc_dev[i].DeviceId;
BUS_ACCESS *bus = &ppc_dev[i].BusAccess;
printf("\n%d:\n", i);
printf(" DEVICE_ID\n");
l = be32toh(id->BusId);
printf(" BusId = ");
for (j = 0; j < sizeof(unsigned long) * 8; j++) {
if ((l & (1UL << j)) != 0) {
printf("%s",
j >= NELEMS(BusId) ? "Unknown" : BusId[j]);
break;
}
}
printf("\n");
pnp_devid_to_string(id->DevId, deviceid);
printf(" DevId = 0x%08lx (%s)\n", id->DevId, deviceid);
printf(" SerialNum = 0x%08lx\n", be32toh(id->SerialNum));
l = be32toh(id->Flags);
printf(" Flags = 0x%08lx\n", l);
for (first = 1, j = 0; j < sizeof(unsigned long) * 8; j++) {
if ((l & (1UL << j)) != 0) {
printf(" : %s\n",
j >= NELEMS(Flags) ? "Unknown" : Flags[j]);
first = 0;
}
}
if (first)
printf(" : None\n");
bustype_subr(id);
printf(" BUS_ACCESS\n");
printf(" info0 = %d\n", bus->PnPAccess.CSN);
printf(" info1 = %d\n", bus->PnPAccess.LogicalDevNumber);
l = be32toh(ppc_dev[i].AllocatedOffset);
printf(" AllocatedOffset = 0x%08lx\n", l);
make_pnp_device_tree(res->DevicePnPHeap + l);
l = be32toh(ppc_dev[i].PossibleOffset);
printf(" PossibleOffset = 0x%08lx\n", l);
make_pnp_device_tree(res->DevicePnPHeap + l);
l = be32toh(ppc_dev[i].CompatibleOffset);
printf(" CompatibleOffset = 0x%08lx\n", l);
make_pnp_device_tree(res->DevicePnPHeap + l);
}
}
enum {
TAG_SMALL = 0,
TAG_LARGE
};
static int pnp_small_pkt(void *);
static int pnp_large_pkt(void *);
static void
make_pnp_device_tree(void *v)
{
unsigned char *p = v;
int size;
if (p == NULL)
return;
for (; p[0] != END_TAG; p += size) {
if (tag_type(p[0]) == TAG_SMALL)
size = pnp_small_pkt(p);
else
size = pnp_large_pkt(p);
}
}
static void small_vendor_chipid(void *v)
{
ChipIDPack *p = v;
char chipid[8];
int16_t id;
int i, j;
struct _svid {
int16_t id;
const char *name;
int type;
} svid[] = {
{ Dakota, "IBM North/South Dakota", Chip_MemCont },
{ Idaho, "IBM Idaho", Chip_MemCont },
{ Eagle, "Motorola Eagle", Chip_MemCont },
{ Kauai_Lanai, "IBM Kauai/Lanai", Chip_MemCont },
{ Montana_Nevada,"IBM Montana/Nevada", Chip_MemCont },
{ Union, "IBM Union", Chip_MemCont },
{ Cobra_Viper, "IBM Cobra/Viper", Chip_MemCont },
{ Grackle, "Motorola Grackle", Chip_MemCont },
{ SIO_ZB, "Intel 82378ZB", Chip_ISABridge },
{ FireCoral, "IBM FireCoral", Chip_ISABridge },
{ Python, "IBM Python", Chip_PCIBridge },
{ DEC21050, "PCI-PCI (DEC 21050)", Chip_PCIBridge },
{ IBM2782351, "PCI-PCI (IBM 2782351)", Chip_PCIBridge },
{ IBM2782352, "PCI-PCI (IBM 2782352)", Chip_PCIBridge },
{ INTEL_8236SL, "Intel 8236SL", Chip_PCMCIABridge },
{ RICOH_RF5C366C,"RICOH RF5C366C", Chip_PCMCIABridge },
{ INTEL_82374, "Intel 82374/82375", Chip_EISABridge },
{ MCACoral, "MCA Coral", Chip_MCABridge },
{ Cheyenne, "IBM Cheyenne", Chip_L2Cache },
{ IDT, "IDT", Chip_L2Cache },
{ Sony1PB, "Sony1PB", Chip_L2Cache },
{ Mamba, "IBM Mamba", Chip_L2Cache },
{ Alaska, "IBM Alaska", Chip_L2Cache },
{ Glance, "IBM Glance", Chip_L2Cache },
{ Ocelot, "IBM Ocelot", Chip_L2Cache },
{ Carrera, "IBM Carrera", Chip_PM },
{ Sig750, "Signetics 87C750", Chip_PM },
{ MPIC_2, "IBM MPIC-2", Chip_IntrCont },
{ DallasRTC, "Dallas 1385 compatible", Chip_MiscPlanar },
{ Dallas1585, "Dallas 1585 compatible", Chip_MiscPlanar },
{ Timer8254, "8254-compatible timer", Chip_MiscPlanar },
{ HarddiskLt, "Op Panel HD light", Chip_MiscPlanar },
{ 0, NULL, -1 },
};
const char *chiptype[] = {
"Memory Controller",
"ISA Bridge",
"PCI Bridge",
"PCMCIA Bridge",
"EISA Bridge",
"MCA Bridge",
"L2 Cache Controller",
"Power Management Controller",
"Interrupt Controller",
"Misc. Planar Device"
};
id = le16dec(&p->Name[0]);
snprintf(chipid, 8, "%c%c%c%0hX",
((p->VendorID0 >> 2) & 0x1f) + 'A' - 1,
(((p->VendorID0 & 3) << 3) | ((p->VendorID1 >> 5) & 7)) + 'A' - 1,
(p->VendorID1 & 0x1f) + 'A' - 1, id);
for (i = 0, j = -1; svid[i].name != NULL; i++) {
if (id == svid[i].id) {
j = i;
break;
}
}
printf("Chip ID: %s\n", chipid);
if (j == -1) {
printf(" Unknown Chip Type\n");
return;
}
printf(" %s: %s\n", chiptype[svid[j].type], svid[j].name);
return;
}
static int
pnp_small_pkt(void *v)
{
int tag = *(unsigned char *)v;
int item, size;
int i, j;
int first;
item = tag_small_item_name(tag);
size = tag_small_count(tag) + 1 ;
switch (item) {
case CompatibleDevice: {
struct _S3_Pack *p = v;
unsigned char *q = p->CompatId;
printf(" CompatibleDevice = %c%c%c%c%c%c%c\n",
((q[0] >> 2) & 0x1f) + 'A' - 1,
(((q[0] & 0x03) << 3) | ((q[1] >> 5) & 0x07)) + 'A' - 1,
(q[1] & 0x1f) + 'A' - 1,
HEXDIGITS[(q[2] >> 4) & 0xf], HEXDIGITS[q[2] & 0xf],
HEXDIGITS[(q[3] >> 4) & 0xf], HEXDIGITS[q[3] & 0xf]);
}
break;
case IRQFormat: {
struct _S4_Pack *p = v;
printf(" IRQ: ");
for (first = 1, j = 0; j < 2; j++) {
for (i = 0; i < 8; i++) {
if (p->IRQMask[j] & (1 << i)) {
printf("%s%d",
first ? "" : ", ", j * 8 + i);
first = 0;
}
}
}
if (first)
printf("None ");
if (size == 3) {
static const char *IRQInfo[] = {
"high true edge sensitive",
"low true edge sensitive",
"high true level sensitive",
"low true level sensitive",
};
if (p->IRQInfo & 0xf0)
goto IRQout;
for (first = 1, i = 0; i < NELEMS(IRQInfo); i++) {
if (p->IRQInfo & (1 << i)) {
printf("%s%s", first ? " (" : ", ",
IRQInfo[i]);
first = 0;
}
}
if (!first)
printf(")");
}
IRQout:
printf("\n");
}
break;
case DMAFormat: {
struct _S5_Pack *p = v;
printf(" DMA: ");
for (first = 1, i = 0; i < 8; i++) {
if (p->DMAMask & (1 << i)) {
printf("%s%d", first ? "" : ", ", i);
first = 0;
}
}
printf("%s", first ? "None" : "");
printf("\n");
}
break;
case StartDepFunc:
case EndDepFunc:
break;
case IOPort: {
struct _S8_Pack *p = v;
unsigned short mask;
unsigned short iomin, iomax;
int align, len;
mask = p->IOInfo & ISAAddr16bit ? 0xffff : 0x03ff;
iomin = (p->RangeMin[0] | (p->RangeMin[1] << 8)) & mask;
iomax = (p->RangeMax[0] | (p->RangeMax[1] << 8)) & mask;
align = p->IOAlign;
len = p->IONum;
if (len != 1) {
if (iomin == iomax)
printf(" IOPort: 0x%x-0x%x",
iomin, iomin + len-1);
else
printf(" IOPort: min 0x%x-0x%x,"
" max 0x%x-0x%x (%d byte%s align)",
iomin, iomin + len-1,
iomax, iomax + len-1,
align, align != 1 ? "s" : "");
} else {
if (iomin == iomax)
printf(" IOPort: 0x%x", iomin);
else
printf(" IOPort: min 0x%x, max 0x%x"
" (%d byte%s align)",
iomin, iomax,
align, align != 1 ? "s" : "");
}
printf("\n");
}
break;
case FixedIOPort: {
struct _S9_Pack *p = v;
unsigned short ioport;
int len;
ioport = (p->Range[0] | (p->Range[1] << 8)) & 0x3ff;
len = p->IONum;
if (len != 1)
printf(" FixedIOPort: 0x%x-0x%x",
ioport, ioport + len - 1);
else
printf(" FixedIOPort: 0x%x", ioport);
printf("\n");
}
break;
case SmallVendorItem: {
unsigned char *p = v;
printf(" SmallVendorItem: ");
switch (p[1]) {
case 1:
small_vendor_chipid(v);
break;
case 3:
printf("Processor Number: %d\n", p[2]);
break;
default:
printf("\n");
for (i = 0; i < size - 1; i++) {
if ((i % 16) == 0)
printf(" ");
printf("%02x ", p[i + 1]);
if ((i % 16) == 15)
printf("\n");
}
if ((i % 16) != 0)
printf("\n");
break;
}
break;
}
default: {
unsigned char *p = v;
printf("small\n");
printf("item = %d\n", item);
printf("size = %d\n", size);
for (i = 1; i < size; i++)
printf("%02x ", p[i]);
printf("\n");
}
break;
}
return size;
}
static void large_vendor_default_subr(struct _L4_PPCPack *p, void *v, int size);
static void large_vendor_floppy_subr(struct _L4_PPCPack *p, void *v, int size);
static void large_vendor_l2cache_subr(struct _L4_PPCPack *p, void *v, int size);
static void large_vendor_pcibridge_subr(struct _L4_PPCPack *p, void *v,
int size);
static void large_vendor_bat_subr(struct _L4_PPCPack *p, void *v, int size);
static void large_vendor_bba_subr(struct _L4_PPCPack *p, void *v, int size);
static void large_vendor_scsi_subr(struct _L4_PPCPack *p, void *v, int size);
static void large_vendor_pms_subr(struct _L4_PPCPack *p, void *v, int size);
static void large_vendor_gaddr_subr(struct _L4_PPCPack *p, void *v, int size);
static void large_vendor_isaintr_subr(struct _L4_PPCPack *p, void *v, int size);
static void
large_vendor_default_subr(struct _L4_PPCPack *p, void *v, int size)
{
int i;
for (i = 0; i < size - 3; i++) {
if ((i % 16) == 0)
printf(" ");
printf("%02x ", p->PPCData[i]);
if ((i % 16) == 15)
printf("\n");
}
if ((i % 16) != 0)
printf("\n");
}
static void
large_vendor_floppy_subr(struct _L4_PPCPack *p, void *v, int size)
{
int i;
const char *str;
for (i = 0; i < (size - 4) / 2; i++) {
switch (p->PPCData[i*2]) {
case 0:
str = "Not present";
break;
case 1:
str = "3.5\" 2MiB";
break;
case 2:
str = "3.5\" 4MiB";
break;
case 3:
str = "5.25\" 1.6MiB";
break;
default:
str = "Unknown type";
break;
}
printf(" Floppy drive %d, %s", i, str);
if (p->PPCData[i*2 + 1] & 0x01)
printf(", Media sense");
if (p->PPCData[i*2 + 1] & 0x02)
printf(", Auto eject");
if (p->PPCData[i*2 + 1] & 0x04)
printf(", Alt speed");
printf("\n");
}
}
static void
large_vendor_l2cache_subr(struct _L4_PPCPack *p, void *v, int size)
{
static const unsigned char *L2type[] =
{ "None", "WriteThru", "CopyBack" };
static const unsigned char *L2assoc[] =
{ "None", "DirectMapped", "2-way set" };
static const unsigned char *L2hw[] =
{ "None", "Invalidate", "Flush", "Unknown" };
printf(" %u K %s %s %s L2 cache\n"
"\t%hd/%hd bytes line/sector size\n",
le32dec(&p->PPCData[0]), L2type[p->PPCData[10]],
L2assoc[le16dec(&p->PPCData[4])],
L2hw[p->PPCData[11]], le16dec(&p->PPCData[6]),
le16dec(&p->PPCData[8]));
}
static void
large_vendor_pcibridge_subr(struct _L4_PPCPack *p, void *v, int size)
{
int i, numslots;
char tmpstr[30];
PCIInfoPack *pi = v;
static const unsigned char *intrtype[] =
{ "8259", "MPIC", "RS6k BUID %d" };
if (res->Revision == 0) {
large_vendor_default_subr(p, v, size);
return;
}
numslots = (le16dec(&pi->count0)-21)/sizeof(IntrMap);
printf(" PCI Bridge parameters\n"
" ConfigBaseAddress 0x%0" PRIx64" \n"
" ConfigBaseData 0x%0" PRIx64 "\n"
" Bus number %d\n",
le64dec(&pi->configbaseaddr), le64dec(&pi->configbasedata),
pi->busnum);
printf(" PCI Bridge Slot Data\n");
for (i = 0; i < numslots; i++) {
int j, first, l;
char *t;
if (pi->map[i].slotnum)
printf(" PCI Slot %d", pi->map[i].slotnum);
else
printf(" Integrated PCI device");
printf(" DevFunc 0x%02x\n", pi->map[i].devfunc);
for (j = 0, first = 1, t = tmpstr; j < MAX_PCI_INTRS; j++) {
if (pi->map[i].intr[j] != 0xFFFF) {
if (first)
first = 0;
else
*t++ = '/';
*t++ = 'A' + j;
}
}
*t = '\0';
if (first)
continue;
printf(" interrupt line(s) %s routed to", tmpstr);
snprintf(tmpstr, sizeof(tmpstr),
intrtype[pi->map[i].intrctrltype - 1],
pi->map[i].intrctrlnum);
printf(" %s line(s) ", tmpstr);
for (j = 0, first = 1, l = 0; j < MAX_PCI_INTRS; j++) {
int line = bswap16(pi->map[i].intr[j]);
if (pi->map[i].intr[j] != 0xFFFF) {
l += snprintf(tmpstr + l, sizeof(tmpstr) - l,
"%s%d(%c)", l == 0 ? "/" : "",
line & 0x7fff, line & 0x8000 ? 'E' : 'L');
if (l > sizeof(tmpstr))
break;
}
}
printf("%s\n", tmpstr);
}
}
static void
large_vendor_bat_subr(struct _L4_PPCPack *p, void *v, int size)
{
static const unsigned char *convtype[] =
{ "Bus Memory", "Bus I/O", "DMA" };
static const unsigned char *transtype[] =
{ "direct", "mapped", "PPC special storage segment" };
printf(" Bridge address translation, %s decoding:\n"
" Parent Base\tBus Base\tRange\t Conversion\tTranslation\n"
" 0x%8.8" PRIx64 "\t0x%8.8" PRIx64 "\t0x%8.8" PRIx64
" %s%s%s\n",
p->PPCData[0] & 1 ? "positive" : "subtractive",
le64dec(&p->PPCData[4]), le64dec(&p->PPCData[12]),
le64dec(&p->PPCData[20]), convtype[p->PPCData[2] - 1],
p->PPCData[2] == 3 ? "\t\t" : "\t",
transtype[p->PPCData[1] - 1]);
}
static void
large_vendor_bba_subr(struct _L4_PPCPack *p, void *v, int size)
{
printf(" Bus speed %ld Hz, %d slot(s)\n",
(long)le32dec(&p->PPCData), p->PPCData[4]);
}
static void
large_vendor_scsi_subr(struct _L4_PPCPack *p, void *v, int size)
{
int i;
printf(" SCSI buses: %d id(s):", p->PPCData[0]);
for (i = 1; i <= p->PPCData[0]; i++)
printf("\t\t\t%d%c", p->PPCData[i],
i == p->PPCData[0] ? '\n' : ',');
}
static void
large_vendor_pms_subr(struct _L4_PPCPack *p, void *v, int size)
{
unsigned int flags;
int i;
static const unsigned char *power[] = {
"Hibernation", "Suspend", "Laptop lid events", "Laptop battery",
"Modem-triggered resume from hibernation",
"Modem-triggered resume from suspend",
"Timer-triggered resume from hibernation",
"Timer-triggered resume from suspend",
"Timer-triggered hibernation from suspend",
"Software-controlled power switch", "External resume trigger",
"Software main power switch can be overridden by hardware",
"Resume button", "Automatic transition between states is inhibited"
};
printf(" Power management attributes:");
flags = le32dec(&p->PPCData);
if (!flags) {
printf(" (none)\n");
return;
}
printf("\n");
for (i = 0; i < 14; i++)
if (flags & 1 << i)
printf("\t%s\n", power[i]);
if (flags & 0xffffc000)
printf("\tunknown flags (0x%8.8x)\n", flags);
}
static void
large_vendor_gaddr_subr(struct _L4_PPCPack *p, void *v, int size)
{
static const unsigned char *addrtype[] = { "I/O", "Memory", "System" };
printf(" %s address (%d bits), at 0x%" PRIx64 " size 0x%"
PRIx64 " bytes\n", addrtype[p->PPCData[0] - 1], p->PPCData[1],
le64dec(&p->PPCData[4]), le64dec(&p->PPCData[12]));
}
static void
large_vendor_isaintr_subr(struct _L4_PPCPack *p, void *v, int size)
{
int i;
char tmpstr[30];
static const unsigned char *inttype[] =
{ "8259", "MPIC", "RS6k BUID %d" };
snprintf(tmpstr, sizeof(tmpstr), inttype[p->PPCData[0] - 1],
p->PPCData[1]);
printf(" ISA interrupts routed to %s lines\n\t", tmpstr);
for (i = 0; i < 16; i++) {
int line = le16dec(&p->PPCData[2 + 2*i]);
if (line != 0xffff)
printf(" %d(IRQ%d)", line, i);
if (i == 8)
printf("\n\t");
}
printf("\n");
}
static int
pnp_large_pkt(void *v)
{
int tag = *(unsigned char *)v;
unsigned char *q = v;
int item, size;
int i;
static struct large_vendor_type {
const char *str;
void (*func)(struct _L4_PPCPack *p, void *vv, int sz);
} Large_Vendor_Type[] = {
{ "None", NULL },
{ "Diskette Drive", large_vendor_floppy_subr },
{ "L2 Cache", large_vendor_l2cache_subr },
{ "PCI Bridge", large_vendor_pcibridge_subr },
{ "Display", large_vendor_default_subr },
{ "Bridge Address Translation", large_vendor_bat_subr },
{ "Bus Bridge Attributes", large_vendor_bba_subr },
{ "SCSI Controller Information",large_vendor_scsi_subr },
{ "Power Management Support", large_vendor_pms_subr },
{ "Generic Address", large_vendor_gaddr_subr },
{ "ISA Bridge Information", large_vendor_isaintr_subr },
{ "Video Channels", large_vendor_default_subr },
{ "Power Control", large_vendor_default_subr },
{ "Memory SIMM PD Data", large_vendor_default_subr },
{ "System Interrupts", large_vendor_default_subr },
{ "Error Log", large_vendor_default_subr },
{ "Extended VPD", large_vendor_default_subr },
{ "Timebase Control", large_vendor_default_subr },
};
item = tag_large_item_name(tag);
size = (q[1] | (q[2] << 8)) + 3 ;
switch (item) {
case LargeVendorItem: {
struct _L4_Pack *pack = v;
struct _L4_PPCPack *p = &pack->L4_Data.L4_PPCPack;
printf(" LargeVendorItem: %s\n",
Large_Vendor_Type[p->Type].str);
if (p->Type <= 17 && Large_Vendor_Type[p->Type].func != NULL)
(*Large_Vendor_Type[p->Type].func)(p, v, size);
break;
}
case MemoryRange: {
struct _L1_Pack *pack = v;
printf(" Memory Range:\n");
if (pack->Data[0] & L1_Shadow)
printf(" Memory is shadowable\n");
if (pack->Data[0] & L1_32bit_mem)
printf(" 32-bit memory only\n");
if (pack->Data[0] & L1_8_16bit_mem)
printf(" 8-bit and 16-bit supported\n");
if (pack->Data[0] & L1_Decode_Hi)
printf(" decode supports high address\n");
if (pack->Data[0] & L1_Cache)
printf(" read cacheable, write-through\n");
if (pack->Data[0] & L1_Writable)
printf(" Memory is writable\n");
if (pack->Count0 >= 0x9) {
printf(" minbase : 0x%x\n",
(pack->Data[2] << 16) | (pack->Data[1] << 8));
printf(" maxbase : 0x%x\n",
(pack->Data[4] << 16) | (pack->Data[3] << 8));
printf(" align : 0x%x\n",
(pack->Data[6] << 8) | pack->Data[5]);
printf(" length : 0x%x\n",
(pack->Data[8] << 16) | (pack->Data[7] << 8));
}
break;
}
default: {
unsigned char *p = v;
printf("large\n");
printf("item = %d\n", item);
printf("size = %d\n", size);
for (i = 3; i < size; i++)
printf("%02x ", p[i]);
printf("\n");
}
break;
}
return size;
}
static void mass_subr(DEVICE_ID *);
static void nic_subr(DEVICE_ID *);
static void display_subr(DEVICE_ID *);
static void mm_subr(DEVICE_ID *);
static void mem_subr(DEVICE_ID *);
static void bridge_subr(DEVICE_ID *);
static void comm_subr(DEVICE_ID *);
static void sys_subr(DEVICE_ID *);
static void input_subr(DEVICE_ID *);
static void service_subr(DEVICE_ID *);
static void
bustype_subr(DEVICE_ID *id)
{
static struct bustype {
const char *str;
void (*func)(DEVICE_ID *);
} BaseType[] = {
{ "Reserved" , NULL },
{ "MassStorageDevice" , mass_subr },
{ "NetworkInterfaceController" , nic_subr },
{ "DisplayController" , display_subr },
{ "MultimediaController" , mm_subr },
{ "MemoryController" , mem_subr },
{ "BridgeController" , bridge_subr },
{ "CommunicationsDevice" , comm_subr },
{ "SystemPeripheral" , sys_subr },
{ "InputDevice" , input_subr },
{ "ServiceProcessor" , service_subr },
};
int type;
type = (id->BaseType >= NELEMS(BaseType)) ? 0 : id->BaseType;
printf(" BaseType = %s (%d)\n", BaseType[type].str, id->BaseType);
if (BaseType[type].func != NULL)
(*BaseType[type].func)(id);
}
static void
mass_subr(DEVICE_ID *id)
{
static const char *IDEController_tabel[] = {
"GeneralIDE",
"ATACompatible",
};
static const char *FloppyController_table[] = {
"GeneralFloppy",
"Compatible765",
"NS398_Floppy",
"NS26E_Floppy",
"NS15C_Floppy",
"NS2E_Floppy",
"CHRP_Floppy",
};
const char *p, *q = NULL;
switch (id->SubType) {
case SCSIController:
p = "SCSIController";
q = "GeneralSCSI";
break;
case IDEController:
p = "IDEController";
q = id->Interface >= NELEMS(IDEController_tabel)
? NULL : IDEController_tabel[id->Interface];
break;
case FloppyController:
p = "FloppyController";
q = id->Interface >= NELEMS(FloppyController_table)
? NULL : FloppyController_table[id->Interface];
break;
case IPIController:
p = "IPIController";
q = "GeneralIPI";
break;
case OtherMassStorageController:
p = "OtherMassStorageController";
break;
default:
p = "UnknownStorageController";
break;
}
printf(" SubType = %s (%d)\n", p, id->SubType);
printf(" Interface = %s (%d)\n", q ? q : "None", id->Interface);
}
static void
nic_subr(DEVICE_ID *id)
{
const char *p, *q = NULL;
switch (id->SubType) {
case EthernetController:
p = "EthernetController";
q = "GeneralEther";
break;
case TokenRingController:
p = "TokenRingController";
q = "GeneralToken";
break;
case FDDIController:
p = "FDDIController";
q = "GeneralFDDI";
break;
case OtherNetworkController:
p = "OtherNetworkController";
break;
default:
p = "UnknownNetworkController";
break;
}
printf(" SubType = %s (%d)\n", p, id->SubType);
printf(" Interface = %s (%d)\n", q ? q : "None", id->Interface);
}
static void
display_subr(DEVICE_ID *id)
{
const char *p, *q = NULL;
switch (id->SubType) {
case VGAController:
p = "VGAController";
q = "GeneralVGA";
break;
case SVGAController:
p = "SVGAController";
q = "GeneralSVGA";
break;
case XGAController:
p = "XGAController";
q = "GeneralXGA";
break;
case OtherDisplayController:
p = "OtherDisplayController";
break;
default:
p = "UnknownDisplayController";
break;
}
printf(" SubType = %s (%d)\n", p, id->SubType);
printf(" Interface = %s (%d)\n", q ? q : "None", id->Interface);
}
static void
mm_subr(DEVICE_ID *id)
{
static const char *AudioController_table[] = {
"GeneralAudio",
"CS4232Audio",
};
const char *p, *q = NULL;
switch (id->SubType) {
case VideoController:
p = "VideoController";
q = "GeneralVideo";
break;
case AudioController:
p = "AudioController";
q = id->Interface >= NELEMS(AudioController_table)
? NULL : AudioController_table[id->Interface];
break;
case OtherMultimediaController:
p = "OtherMultimediaController";
break;
default:
p = "UnknownMultimediaController";
break;
}
printf(" SubType = %s (%d)\n", p, id->SubType);
printf(" Interface = %s (%d)\n", q ? q : "None", id->Interface);
}
static void
mem_subr(DEVICE_ID *id)
{
const char *p, *q = NULL;
switch (id->SubType) {
case RAM:
p = "RAM";
q = "GeneralRAM";
break;
case FLASH:
p = "FLASH";
q = "GeneralFLASH";
break;
case OtherMemoryDevice:
p = "OtherMemoryDevice";
break;
default:
p = "UnknownMemoryDevice";
break;
}
printf(" SubType = %s (%d)\n", p, id->SubType);
printf(" Interface = %s (%d)\n", q ? q : "None", id->Interface);
}
static void
bridge_subr(DEVICE_ID *id)
{
static const char *PCIBridge_table[] = {
"GeneralPCIBridge",
"PCIBridgeIndirect",
"PCIBridgeRS6K",
};
const char *p, *q = NULL;
switch (id->SubType) {
case HostProcessorBridge:
p = "HostProcessorBridge";
q = "GeneralHostBridge";
break;
case ISABridge:
p = "ISABridge";
q = "GeneralISABridge";
break;
case EISABridge:
p = "EISABridge";
q = "GeneralEISABridge";
break;
case MicroChannelBridge:
p = "MicroChannelBridge";
q = "GeneralMCABridge";
break;
case PCIBridge:
p = "PCIBridge";
q = id->Interface >= NELEMS(PCIBridge_table)
? NULL : PCIBridge_table[id->Interface];
break;
case PCMCIABridge:
p = "PCMCIABridge";
q = "GeneralPCMCIABridge";
break;
case VMEBridge:
p = "VMEBridge";
q = "GeneralVMEBridge";
break;
case OtherBridgeDevice:
p = "OtherBridgeDevice";
break;
default:
p = "UnknownBridgeDevice";
break;
}
printf(" SubType = %s (%d)\n", p, id->SubType);
printf(" Interface = %s (%d)\n", q ? q : "None", id->Interface);
}
static void
comm_subr(DEVICE_ID *id)
{
static const char *RS232Device_table[] = {
"GeneralRS232",
"COMx",
"Compatible16450",
"Compatible16550",
"NS398SerPort",
"NS26ESerPort",
"NS15CSerPort",
"NS2ESerPort",
};
static const char *ATCompatibleParallelPort_table[] = {
"GeneralParPort",
"LPTx",
"NS398ParPort",
"NS26EParPort",
"NS15CParPort",
"NS2EParPort",
};
const char *p, *q = NULL;
switch (id->SubType) {
case RS232Device:
p = "RS232Device";
q = id->Interface >= NELEMS(RS232Device_table)
? NULL : RS232Device_table[id->Interface];
break;
case ATCompatibleParallelPort:
p = "ATCompatibleParallelPort";
q = id->Interface >= NELEMS(ATCompatibleParallelPort_table)
? NULL : ATCompatibleParallelPort_table[id->Interface];
break;
case OtherCommunicationsDevice:
p = "OtherCommunicationsDevice";
break;
default:
p = "UnknownCommunicationsDevice";
break;
}
printf(" SubType = %s (%d)\n", p, id->SubType);
printf(" Interface = %s (%d)\n", q ? q : "None", id->Interface);
}
static void
sys_subr(DEVICE_ID *id)
{
static const char *PIC_table[] = {
"GeneralPIC",
"ISA_PIC",
"EISA_PIC",
"MPIC",
"RS6K_PIC",
};
static const char *DMAController_table[] = {
"GeneralDMA",
"ISA_DMA",
"EISA_DMA",
};
static const char *SystemTimer_table[] = {
"GeneralTimer",
"ISA_Timer",
"EISA_Timer",
};
static const char *RealTimeClock_table[] = {
"GeneralRTC",
"ISA_RTC",
};
static const char *L2Cache_table[] = {
"None",
"StoreThruOnly",
"StoreInEnabled",
"RS6KL2Cache",
};
static const char *NVRAM_table[] = {
"IndirectNVRAM",
"DirectNVRAM",
"IndirectNVRAM24",
};
static const char *PowerManagement_table[] = {
"GeneralPowerManagement",
"EPOWPowerManagement",
"PowerControl",
};
static const char *GraphicAssist_table[] = {
"Unknown",
"TransferData",
"IGMC32",
"IGMC64",
};
static const char *OperatorPanel_table[] = {
"GeneralOPPanel",
"HarddiskLight",
"CDROMLight",
"PowerLight",
"KeyLock",
"ANDisplay",
"SystemStatusLED",
"CHRP_SystemStatusLED",
};
const char *p, *q = NULL;
switch (id->SubType) {
case ProgrammableInterruptController:
p = "ProgrammableInterruptController";
q = id->Interface >= NELEMS(PIC_table)
? NULL : PIC_table[id->Interface];
break;
case DMAController:
p = "DMAController";
q = id->Interface >= NELEMS(DMAController_table)
? NULL : DMAController_table[id->Interface];
break;
case SystemTimer:
p = "SystemTimer";
q = id->Interface >= NELEMS(SystemTimer_table)
? NULL : SystemTimer_table[id->Interface];
break;
case RealTimeClock:
p = "RealTimeClock";
q = id->Interface >= NELEMS(RealTimeClock_table)
? NULL : RealTimeClock_table[id->Interface];
break;
case L2Cache:
p = "L2Cache";
q = id->Interface >= NELEMS(L2Cache_table)
? NULL : L2Cache_table[id->Interface];
break;
case NVRAM:
p = "NVRAM";
q = id->Interface >= NELEMS(NVRAM_table)
? NULL : NVRAM_table[id->Interface];
break;
case PowerManagement:
p = "PowerManagement";
q = id->Interface >= NELEMS(PowerManagement_table)
? NULL : PowerManagement_table[id->Interface];
break;
case CMOS:
p = "CMOS";
q = "GeneralCMOS";
break;
case OperatorPanel:
p = "OperatorPanel";
q = id->Interface >= NELEMS(OperatorPanel_table)
? NULL : OperatorPanel_table[id->Interface];
break;
case ServiceProcessorClass1:
p = "ServiceProcessorClass1";
q = "GeneralServiceProcessor";
break;
case ServiceProcessorClass2:
p = "ServiceProcessorClass2";
q = "GeneralServiceProcessor";
break;
case ServiceProcessorClass3:
p = "ServiceProcessorClass3";
q = "GeneralServiceProcessor";
break;
case GraphicAssist:
p = "GraphicAssist";
q = id->Interface >= NELEMS(GraphicAssist_table)
? NULL : GraphicAssist_table[id->Interface];
break;
case SystemPlanar:
p = "SystemPlanar";
q = "GeneralSystemPlanar";
break;
case OtherSystemPeripheral:
p = "OtherSystemPeripheral";
break;
default:
p = "UnknownSystemPeripheral";
break;
}
printf(" SubType = %s (%d)\n", p, id->SubType);
printf(" Interface = %s (%d)\n", q ? q : "None", id->Interface);
}
static void
input_subr(DEVICE_ID *id)
{
const char *p, *q = NULL;
switch (id->SubType) {
case KeyboardController:
p = "KeyboardController";
break;
case Digitizer:
p = "Digitizer";
break;
case MouseController:
p = "MouseController";
break;
case TabletController:
p = "TabletController";
break;
case OtherInputController:
p = "OtherInputController";
break;
default:
p = "UnknownInputController";
break;
}
printf(" SubType = %s (%d)\n", p, id->SubType);
printf(" Interface = %s (%d)\n", q ? q : "None", id->Interface);
}
static void
service_subr(DEVICE_ID *id)
{
const char *p, *q = NULL;
switch (id->SubType) {
case ServiceProcessorClass1:
p = "ServiceProcessorClass1";
break;
case ServiceProcessorClass2:
p = "ServiceProcessorClass2";
break;
case ServiceProcessorClass3:
p = "ServiceProcessorClass3";
break;
default:
p = "UnknownServiceProcessor";
break;
}
printf(" SubType = %s (%d)\n", p, id->SubType);
printf(" Interface = %s (%d)\n", q ? q : "None", id->Interface);
}
#endif