linux/arch/ppc/platforms/residual.c
<<
>>
Prefs
   1/*
   2 * Code to deal with the PReP residual data.
   3 *
   4 * Written by: Cort Dougan (cort@cs.nmt.edu)
   5 * Improved _greatly_ and rewritten by Gabriel Paubert (paubert@iram.es)
   6 *
   7 *  This file is based on the following documentation:
   8 *
   9 *      IBM Power Personal Systems Architecture
  10 *      Residual Data
  11 *      Document Number: PPS-AR-FW0001
  12 *
  13 *  This file is subject to the terms and conditions of the GNU General Public
  14 *  License.  See the file COPYING in the main directory of this archive
  15 *  for more details.
  16 *
  17 */
  18
  19#include <linux/string.h>
  20#include <asm/residual.h>
  21#include <asm/pnp.h>
  22#include <asm/byteorder.h>
  23
  24#include <linux/errno.h>
  25#include <linux/sched.h>
  26#include <linux/kernel.h>
  27#include <linux/mm.h>
  28#include <linux/stddef.h>
  29#include <linux/unistd.h>
  30#include <linux/ptrace.h>
  31#include <linux/slab.h>
  32#include <linux/user.h>
  33#include <linux/a.out.h>
  34#include <linux/tty.h>
  35#include <linux/major.h>
  36#include <linux/interrupt.h>
  37#include <linux/reboot.h>
  38#include <linux/init.h>
  39#include <linux/ioport.h>
  40#include <linux/pci.h>
  41#include <linux/ide.h>
  42
  43#include <asm/sections.h>
  44#include <asm/mmu.h>
  45#include <asm/io.h>
  46#include <asm/pgtable.h>
  47#include <asm/ide.h>
  48
  49
  50unsigned char __res[sizeof(RESIDUAL)] = {0,};
  51RESIDUAL *res = (RESIDUAL *)&__res;
  52
  53char * PnP_BASE_TYPES[] __initdata = {
  54  "Reserved",
  55  "MassStorageDevice",
  56  "NetworkInterfaceController",
  57  "DisplayController",
  58  "MultimediaController",
  59  "MemoryController",
  60  "BridgeController",
  61  "CommunicationsDevice",
  62  "SystemPeripheral",
  63  "InputDevice",
  64  "ServiceProcessor"
  65  };
  66
  67/* Device Sub Type Codes */
  68
  69unsigned char * PnP_SUB_TYPES[] __initdata = {
  70  "\001\000SCSIController",
  71  "\001\001IDEController",
  72  "\001\002FloppyController",
  73  "\001\003IPIController",
  74  "\001\200OtherMassStorageController",
  75  "\002\000EthernetController",
  76  "\002\001TokenRingController",
  77  "\002\002FDDIController",
  78  "\002\0x80OtherNetworkController",
  79  "\003\000VGAController",
  80  "\003\001SVGAController",
  81  "\003\002XGAController",
  82  "\003\200OtherDisplayController",
  83  "\004\000VideoController",
  84  "\004\001AudioController",
  85  "\004\200OtherMultimediaController",
  86  "\005\000RAM",
  87  "\005\001FLASH",
  88  "\005\200OtherMemoryDevice",
  89  "\006\000HostProcessorBridge",
  90  "\006\001ISABridge",
  91  "\006\002EISABridge",
  92  "\006\003MicroChannelBridge",
  93  "\006\004PCIBridge",
  94  "\006\005PCMCIABridge",
  95  "\006\006VMEBridge",
  96  "\006\200OtherBridgeDevice",
  97  "\007\000RS232Device",
  98  "\007\001ATCompatibleParallelPort",
  99  "\007\200OtherCommunicationsDevice",
 100  "\010\000ProgrammableInterruptController",
 101  "\010\001DMAController",
 102  "\010\002SystemTimer",
 103  "\010\003RealTimeClock",
 104  "\010\004L2Cache",
 105  "\010\005NVRAM",
 106  "\010\006PowerManagement",
 107  "\010\007CMOS",
 108  "\010\010OperatorPanel",
 109  "\010\011ServiceProcessorClass1",
 110  "\010\012ServiceProcessorClass2",
 111  "\010\013ServiceProcessorClass3",
 112  "\010\014GraphicAssist",
 113  "\010\017SystemPlanar",
 114  "\010\200OtherSystemPeripheral",
 115  "\011\000KeyboardController",
 116  "\011\001Digitizer",
 117  "\011\002MouseController",
 118  "\011\003TabletController",
 119  "\011\0x80OtherInputController",
 120  "\012\000GeneralMemoryController",
 121  NULL
 122};
 123
 124/* Device Interface Type Codes */
 125
 126unsigned char * PnP_INTERFACES[] __initdata = {
 127  "\000\000\000General",
 128  "\001\000\000GeneralSCSI",
 129  "\001\001\000GeneralIDE",
 130  "\001\001\001ATACompatible",
 131
 132  "\001\002\000GeneralFloppy",
 133  "\001\002\001Compatible765",
 134  "\001\002\002NS398_Floppy",         /* NS Super I/O wired to use index
 135                                         register at port 398 and data
 136                                         register at port 399               */
 137  "\001\002\003NS26E_Floppy",         /* Ports 26E and 26F                  */
 138  "\001\002\004NS15C_Floppy",         /* Ports 15C and 15D                  */
 139  "\001\002\005NS2E_Floppy",          /* Ports 2E and 2F                    */
 140  "\001\002\006CHRP_Floppy",          /* CHRP Floppy in PR*P system         */
 141
 142  "\001\003\000GeneralIPI",
 143
 144  "\002\000\000GeneralEther",
 145  "\002\001\000GeneralToken",
 146  "\002\002\000GeneralFDDI",
 147
 148  "\003\000\000GeneralVGA",
 149  "\003\001\000GeneralSVGA",
 150  "\003\002\000GeneralXGA",
 151
 152  "\004\000\000GeneralVideo",
 153  "\004\001\000GeneralAudio",
 154  "\004\001\001CS4232Audio",            /* CS 4232 Plug 'n Play Configured    */
 155
 156  "\005\000\000GeneralRAM",
 157  /* This one is obviously wrong ! */
 158  "\005\000\000PCIMemoryController",    /* PCI Config Method                  */
 159  "\005\000\001RS6KMemoryController",   /* RS6K Config Method                 */
 160  "\005\001\000GeneralFLASH",
 161
 162  "\006\000\000GeneralHostBridge",
 163  "\006\001\000GeneralISABridge",
 164  "\006\002\000GeneralEISABridge",
 165  "\006\003\000GeneralMCABridge",
 166  /* GeneralPCIBridge = 0, */
 167  "\006\004\000PCIBridgeDirect",
 168  "\006\004\001PCIBridgeIndirect",
 169  "\006\004\002PCIBridgeRS6K",
 170  "\006\005\000GeneralPCMCIABridge",
 171  "\006\006\000GeneralVMEBridge",
 172
 173  "\007\000\000GeneralRS232",
 174  "\007\000\001COMx",
 175  "\007\000\002Compatible16450",
 176  "\007\000\003Compatible16550",
 177  "\007\000\004NS398SerPort",         /* NS Super I/O wired to use index
 178                                         register at port 398 and data
 179                                         register at port 399               */
 180  "\007\000\005NS26ESerPort",         /* Ports 26E and 26F                  */
 181  "\007\000\006NS15CSerPort",         /* Ports 15C and 15D                  */
 182  "\007\000\007NS2ESerPort",          /* Ports 2E and 2F                    */
 183
 184  "\007\001\000GeneralParPort",
 185  "\007\001\001LPTx",
 186  "\007\001\002NS398ParPort",         /* NS Super I/O wired to use index
 187                                         register at port 398 and data
 188                                         register at port 399               */
 189  "\007\001\003NS26EParPort",         /* Ports 26E and 26F                  */
 190  "\007\001\004NS15CParPort",         /* Ports 15C and 15D                  */
 191  "\007\001\005NS2EParPort",          /* Ports 2E and 2F                    */
 192
 193  "\010\000\000GeneralPIC",
 194  "\010\000\001ISA_PIC",
 195  "\010\000\002EISA_PIC",
 196  "\010\000\003MPIC",
 197  "\010\000\004RS6K_PIC",
 198
 199  "\010\001\000GeneralDMA",
 200  "\010\001\001ISA_DMA",
 201  "\010\001\002EISA_DMA",
 202
 203  "\010\002\000GeneralTimer",
 204  "\010\002\001ISA_Timer",
 205  "\010\002\002EISA_Timer",
 206  "\010\003\000GeneralRTC",
 207  "\010\003\001ISA_RTC",
 208
 209  "\010\004\001StoreThruOnly",
 210  "\010\004\002StoreInEnabled",
 211  "\010\004\003RS6KL2Cache",
 212
 213  "\010\005\000IndirectNVRAM",        /* Indirectly addressed               */
 214  "\010\005\001DirectNVRAM",          /* Memory Mapped                      */
 215  "\010\005\002IndirectNVRAM24",      /* Indirectly addressed - 24 bit      */
 216
 217  "\010\006\000GeneralPowerManagement",
 218  "\010\006\001EPOWPowerManagement",
 219  "\010\006\002PowerControl",         // d1378
 220
 221  "\010\007\000GeneralCMOS",
 222
 223  "\010\010\000GeneralOPPanel",
 224  "\010\010\001HarddiskLight",
 225  "\010\010\002CDROMLight",
 226  "\010\010\003PowerLight",
 227  "\010\010\004KeyLock",
 228  "\010\010\005ANDisplay",            /* AlphaNumeric Display               */
 229  "\010\010\006SystemStatusLED",      /* 3 digit 7 segment LED              */
 230  "\010\010\007CHRP_SystemStatusLED", /* CHRP LEDs in PR*P system           */
 231
 232  "\010\011\000GeneralServiceProcessor",
 233  "\010\012\000GeneralServiceProcessor",
 234  "\010\013\000GeneralServiceProcessor",
 235
 236  "\010\014\001TransferData",
 237  "\010\014\002IGMC32",
 238  "\010\014\003IGMC64",
 239
 240  "\010\017\000GeneralSystemPlanar",   /* 10/5/95                            */
 241  NULL
 242  };
 243
 244static const unsigned char __init *PnP_SUB_TYPE_STR(unsigned char BaseType,
 245                                             unsigned char SubType) {
 246        unsigned char ** s=PnP_SUB_TYPES;
 247        while (*s && !((*s)[0]==BaseType
 248                       && (*s)[1]==SubType)) s++;
 249        if (*s) return *s+2;
 250        else return("Unknown !");
 251};
 252
 253static const unsigned char __init *PnP_INTERFACE_STR(unsigned char BaseType,
 254                                              unsigned char SubType,
 255                                              unsigned char Interface) {
 256        unsigned char ** s=PnP_INTERFACES;
 257        while (*s && !((*s)[0]==BaseType
 258                       && (*s)[1]==SubType
 259                       && (*s)[2]==Interface)) s++;
 260        if (*s) return *s+3;
 261        else return NULL;
 262};
 263
 264static void __init printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
 265        int i, c;
 266        char decomp[4];
 267#define p pkt->S14_Pack.S14_Data.S14_PPCPack
 268        switch(p.Type) {
 269        case 1:
 270          /* Decompress first 3 chars */
 271          c = *(unsigned short *)p.PPCData;
 272          decomp[0]='A'-1+((c>>10)&0x1F);
 273          decomp[1]='A'-1+((c>>5)&0x1F);
 274          decomp[2]='A'-1+(c&0x1F);
 275          decomp[3]=0;
 276          printk("    Chip identification: %s%4.4X\n",
 277                 decomp, ld_le16((unsigned short *)(p.PPCData+2)));
 278          break;
 279        default:
 280          printk("    Small vendor item type 0x%2.2x, data (hex): ",
 281                 p.Type);
 282          for(i=0; i<size-2; i++) printk("%2.2x ", p.PPCData[i]);
 283          printk("\n");
 284          break;
 285        }
 286#undef p
 287}
 288
 289static void __init printsmallpacket(PnP_TAG_PACKET * pkt, int size) {
 290        static const unsigned char * intlevel[] = {"high", "low"};
 291        static const unsigned char * intsense[] = {"edge", "level"};
 292
 293        switch (tag_small_item_name(pkt->S1_Pack.Tag)) {
 294        case PnPVersion:
 295          printk("    PnPversion 0x%x.%x\n",
 296                 pkt->S1_Pack.Version[0], /* How to interpret version ? */
 297                 pkt->S1_Pack.Version[1]);
 298          break;
 299//      case Logicaldevice:
 300          break;
 301//      case CompatibleDevice:
 302          break;
 303        case IRQFormat:
 304#define p pkt->S4_Pack
 305          printk("    IRQ Mask 0x%4.4x, %s %s sensitive\n",
 306                 ld_le16((unsigned short *)p.IRQMask),
 307                 intlevel[(size>3) ? !(p.IRQInfo&0x05) : 0],
 308                 intsense[(size>3) ? !(p.IRQInfo&0x03) : 0]);
 309#undef p
 310          break;
 311        case DMAFormat:
 312#define p pkt->S5_Pack
 313          printk("    DMA channel mask 0x%2.2x, info 0x%2.2x\n",
 314                 p.DMAMask, p.DMAInfo);
 315#undef p
 316          break;
 317        case StartDepFunc:
 318          printk("Start dependent function:\n");
 319          break;
 320        case EndDepFunc:
 321          printk("End dependent function\n");
 322          break;
 323        case IOPort:
 324#define p pkt->S8_Pack
 325          printk("    Variable (%d decoded bits) I/O port\n"
 326                 "      from 0x%4.4x to 0x%4.4x, alignment %d, %d ports\n",
 327                 p.IOInfo&ISAAddr16bit?16:10,
 328                 ld_le16((unsigned short *)p.RangeMin),
 329                 ld_le16((unsigned short *)p.RangeMax),
 330                 p.IOAlign, p.IONum);
 331#undef p
 332          break;
 333        case FixedIOPort:
 334#define p pkt->S9_Pack
 335          printk("    Fixed (10 decoded bits) I/O port from %3.3x to %3.3x\n",
 336                 (p.Range[1]<<8)|p.Range[0],
 337                 ((p.Range[1]<<8)|p.Range[0])+p.IONum-1);
 338#undef p
 339          break;
 340        case Res1:
 341        case Res2:
 342        case Res3:
 343          printk("    Undefined packet type %d!\n",
 344                 tag_small_item_name(pkt->S1_Pack.Tag));
 345          break;
 346        case SmallVendorItem:
 347          printsmallvendor(pkt,size);
 348          break;
 349        default:
 350          printk("    Type 0x2.2x%d, size=%d\n",
 351                 pkt->S1_Pack.Tag, size);
 352          break;
 353        }
 354}
 355
 356static void __init printlargevendor(PnP_TAG_PACKET * pkt, int size) {
 357        static const unsigned char * addrtype[] = {"I/O", "Memory", "System"};
 358        static const unsigned char * inttype[] = {"8259", "MPIC", "RS6k BUID %d"};
 359        static const unsigned char * convtype[] = {"Bus Memory", "Bus I/O", "DMA"};
 360        static const unsigned char * transtype[] = {"direct", "mapped", "direct-store segment"};
 361        static const unsigned char * L2type[] = {"WriteThru", "CopyBack"};
 362        static const unsigned char * L2assoc[] = {"DirectMapped", "2-way set"};
 363
 364        int i;
 365        char tmpstr[30], *t;
 366#define p pkt->L4_Pack.L4_Data.L4_PPCPack
 367        switch(p.Type) {
 368        case 2:
 369          printk("    %d K %s %s L2 cache, %d/%d bytes line/sector size\n",
 370                 ld_le32((unsigned int *)p.PPCData),
 371                 L2type[p.PPCData[10]-1],
 372                 L2assoc[p.PPCData[4]-1],
 373                 ld_le16((unsigned short *)p.PPCData+3),
 374                 ld_le16((unsigned short *)p.PPCData+4));
 375          break;
 376        case 3:
 377          printk("    PCI Bridge parameters\n"
 378                 "      ConfigBaseAddress %0x\n"
 379                 "      ConfigBaseData %0x\n"
 380                 "      Bus number %d\n",
 381                 ld_le32((unsigned int *)p.PPCData),
 382                 ld_le32((unsigned int *)(p.PPCData+8)),
 383                 p.PPCData[16]);
 384          for(i=20; i<size-4; i+=12) {
 385                int j, first;
 386                if(p.PPCData[i]) printk("      PCI Slot %d", p.PPCData[i]);
 387                else printk ("      Integrated PCI device");
 388                for(j=0, first=1, t=tmpstr; j<4; j++) {
 389                        int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
 390                        if(line!=0xffff){
 391                                if(first) first=0; else *t++='/';
 392                                *t++='A'+j;
 393                        }
 394                }
 395                *t='\0';
 396                printk(" DevFunc 0x%x interrupt line(s) %s routed to",
 397                       p.PPCData[i+1],tmpstr);
 398                sprintf(tmpstr,
 399                        inttype[p.PPCData[i+2]-1],
 400                        p.PPCData[i+3]);
 401                printk(" %s line(s) ",
 402                       tmpstr);
 403                for(j=0, first=1, t=tmpstr; j<4; j++) {
 404                        int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
 405                        if(line!=0xffff){
 406                                if(first) first=0; else *t++='/';
 407                                t+=sprintf(t,"%d(%c)",
 408                                           line&0x7fff,
 409                                           line&0x8000?'E':'L');
 410                        }
 411                }
 412                printk("%s\n",tmpstr);
 413          }
 414          break;
 415        case 5:
 416          printk("    Bridge address translation, %s decoding:\n"
 417                 "      Processor  Bus        Size       Conversion Translation\n"
 418                 "      0x%8.8x 0x%8.8x 0x%8.8x %s %s\n",
 419                 p.PPCData[0]&1 ? "positive" : "subtractive",
 420                 ld_le32((unsigned int *)p.PPCData+1),
 421                 ld_le32((unsigned int *)p.PPCData+3),
 422                 ld_le32((unsigned int *)p.PPCData+5),
 423                 convtype[p.PPCData[2]-1],
 424                 transtype[p.PPCData[1]-1]);
 425          break;
 426        case 6:
 427          printk("    Bus speed %d Hz, %d slot(s)\n",
 428                 ld_le32((unsigned int *)p.PPCData),
 429                 p.PPCData[4]);
 430          break;
 431        case 7:
 432          printk("    SCSI buses: %d, id(s):", p.PPCData[0]);
 433          for(i=1; i<=p.PPCData[0]; i++)
 434            printk(" %d%c", p.PPCData[i], i==p.PPCData[0] ? '\n' : ',');
 435          break;
 436        case 9:
 437          printk("    %s address (%d bits), at 0x%x size 0x%x bytes\n",
 438                 addrtype[p.PPCData[0]-1],
 439                 p.PPCData[1],
 440                 ld_le32((unsigned int *)(p.PPCData+4)),
 441                 ld_le32((unsigned int *)(p.PPCData+12)));
 442          break;
 443        case 10:
 444          sprintf(tmpstr,
 445                  inttype[p.PPCData[0]-1],
 446                  p.PPCData[1]);
 447
 448          printk("    ISA interrupts routed to %s\n"
 449                 "      lines",
 450                 tmpstr);
 451          for(i=0; i<16; i++) {
 452                int line=ld_le16((unsigned short *)p.PPCData+i+1);
 453                if (line!=0xffff) printk(" %d(IRQ%d)", line, i);
 454          }
 455          printk("\n");
 456          break;
 457        default:
 458          printk("    Large vendor item type 0x%2.2x\n      Data (hex):",
 459                 p.Type);
 460          for(i=0; i<size-4; i++) printk(" %2.2x", p.PPCData[i]);
 461          printk("\n");
 462#undef p
 463        }
 464}
 465
 466static void __init printlargepacket(PnP_TAG_PACKET * pkt, int size) {
 467        switch (tag_large_item_name(pkt->S1_Pack.Tag)) {
 468        case LargeVendorItem:
 469          printlargevendor(pkt, size);
 470          break;
 471        default:
 472          printk("    Type 0x2.2x%d, size=%d\n",
 473                 pkt->S1_Pack.Tag, size);
 474          break;
 475        }
 476}
 477
 478static void __init printpackets(PnP_TAG_PACKET * pkt, const char * cat)
 479{
 480        if (pkt->S1_Pack.Tag== END_TAG) {
 481                printk("  No packets describing %s resources.\n", cat);
 482                return;
 483        }
 484        printk(  "  Packets describing %s resources:\n",cat);
 485        do {
 486                int size;
 487                if (tag_type(pkt->S1_Pack.Tag)) {
 488                        size= 3 +
 489                          pkt->L1_Pack.Count0 +
 490                          pkt->L1_Pack.Count1*256;
 491                        printlargepacket(pkt, size);
 492                } else {
 493                        size=tag_small_count(pkt->S1_Pack.Tag)+1;
 494                        printsmallpacket(pkt, size);
 495                }
 496                pkt = (PnP_TAG_PACKET *)((unsigned char *) pkt + size);
 497        } while (pkt->S1_Pack.Tag != END_TAG);
 498}
 499
 500void __init print_residual_device_info(void)
 501{
 502        int i;
 503        PPC_DEVICE *dev;
 504#define did dev->DeviceId
 505
 506        /* make sure we have residual data first */
 507        if (!have_residual_data)
 508                return;
 509
 510        printk("Residual: %ld devices\n", res->ActualNumDevices);
 511        for ( i = 0;
 512              i < res->ActualNumDevices ;
 513              i++)
 514        {
 515                char decomp[4], sn[20];
 516                const char * s;
 517                dev = &res->Devices[i];
 518                s = PnP_INTERFACE_STR(did.BaseType, did.SubType,
 519                                      did.Interface);
 520                if(!s) {
 521                        sprintf(sn, "interface %d", did.Interface);
 522                        s=sn;
 523                }
 524                if ( did.BusId & PCIDEVICE )
 525                  printk("PCI Device, Bus %d, DevFunc 0x%x:",
 526                         dev->BusAccess.PCIAccess.BusNumber,
 527                         dev->BusAccess.PCIAccess.DevFuncNumber);
 528                if ( did.BusId & PNPISADEVICE ) printk("PNPISA Device:");
 529                if ( did.BusId & ISADEVICE )
 530                  printk("ISA Device, Slot %d, LogicalDev %d:",
 531                         dev->BusAccess.ISAAccess.SlotNumber,
 532                         dev->BusAccess.ISAAccess.LogicalDevNumber);
 533                if ( did.BusId & EISADEVICE ) printk("EISA Device:");
 534                if ( did.BusId & PROCESSORDEVICE )
 535                  printk("ProcBus Device, Bus %d, BUID %d: ",
 536                         dev->BusAccess.ProcBusAccess.BusNumber,
 537                         dev->BusAccess.ProcBusAccess.BUID);
 538                if ( did.BusId & PCMCIADEVICE ) printk("PCMCIA ");
 539                if ( did.BusId & VMEDEVICE ) printk("VME ");
 540                if ( did.BusId & MCADEVICE ) printk("MCA ");
 541                if ( did.BusId & MXDEVICE ) printk("MX ");
 542                /* Decompress first 3 chars */
 543                decomp[0]='A'-1+((did.DevId>>26)&0x1F);
 544                decomp[1]='A'-1+((did.DevId>>21)&0x1F);
 545                decomp[2]='A'-1+((did.DevId>>16)&0x1F);
 546                decomp[3]=0;
 547                printk(" %s%4.4lX, %s, %s, %s\n",
 548                       decomp, did.DevId&0xffff,
 549                       PnP_BASE_TYPES[did.BaseType],
 550                       PnP_SUB_TYPE_STR(did.BaseType,did.SubType),
 551                       s);
 552                if ( dev->AllocatedOffset )
 553                        printpackets( (union _PnP_TAG_PACKET *)
 554                                      &res->DevicePnPHeap[dev->AllocatedOffset],
 555                                      "allocated");
 556                if ( dev->PossibleOffset )
 557                        printpackets( (union _PnP_TAG_PACKET *)
 558                                      &res->DevicePnPHeap[dev->PossibleOffset],
 559                                      "possible");
 560                if ( dev->CompatibleOffset )
 561                        printpackets( (union _PnP_TAG_PACKET *)
 562                                      &res->DevicePnPHeap[dev->CompatibleOffset],
 563                                      "compatible");
 564        }
 565}
 566
 567
 568#if 0
 569static void __init printVPD(void) {
 570#define vpd res->VitalProductData
 571        int ps=vpd.PageSize, i, j;
 572        static const char* Usage[]={
 573          "FirmwareStack",  "FirmwareHeap",  "FirmwareCode", "BootImage",
 574          "Free", "Unpopulated", "ISAAddr", "PCIConfig",
 575          "IOMemory", "SystemIO", "SystemRegs", "PCIAddr",
 576          "UnPopSystemRom", "SystemROM", "ResumeBlock", "Other"
 577        };
 578        static const unsigned char *FWMan[]={
 579          "IBM", "Motorola", "FirmWorks", "Bull"
 580        };
 581        static const unsigned char *FWFlags[]={
 582          "Conventional", "OpenFirmware", "Diagnostics", "LowDebug",
 583          "MultiBoot", "LowClient", "Hex41", "FAT",
 584          "ISO9660", "SCSI_ID_Override", "Tape_Boot", "FW_Boot_Path"
 585        };
 586        static const unsigned char *ESM[]={
 587          "Port92", "PCIConfigA8", "FF001030", "????????"
 588        };
 589        static const unsigned char *SIOM[]={
 590          "Port850", "????????", "PCIConfigA8", "????????"
 591        };
 592
 593        printk("Model: %s\n",vpd.PrintableModel);
 594        printk("Serial: %s\n", vpd.Serial);
 595        printk("FirmwareSupplier: %s\n", FWMan[vpd.FirmwareSupplier]);
 596        printk("FirmwareFlags:");
 597        for(j=0; j<12; j++) {
 598                if (vpd.FirmwareSupports & (1<<j)) {
 599                        printk(" %s%c", FWFlags[j],
 600                               vpd.FirmwareSupports&(-2<<j) ? ',' : '\n');
 601                }
 602        }
 603        printk("NVRamSize: %ld\n", vpd.NvramSize);
 604        printk("SIMMslots: %ld\n", vpd.NumSIMMSlots);
 605        printk("EndianSwitchMethod: %s\n",
 606               ESM[vpd.EndianSwitchMethod>2 ? 2 : vpd.EndianSwitchMethod]);
 607        printk("SpreadIOMethod: %s\n",
 608               SIOM[vpd.SpreadIOMethod>3 ? 3 : vpd.SpreadIOMethod]);
 609        printk("Processor/Bus frequencies (Hz): %ld/%ld\n",
 610               vpd.ProcessorHz, vpd.ProcessorBusHz);
 611        printk("Time Base Divisor: %ld\n", vpd.TimeBaseDivisor);
 612        printk("WordWidth, PageSize: %ld, %d\n", vpd.WordWidth, ps);
 613        printk("Cache sector size, Lock granularity: %ld, %ld\n",
 614               vpd.CoherenceBlockSize, vpd.GranuleSize);
 615        for (i=0; i<res->ActualNumMemSegs; i++) {
 616                int mask=res->Segs[i].Usage, first, j;
 617                printk("%8.8lx-%8.8lx ",
 618                       res->Segs[i].BasePage*ps,
 619                       (res->Segs[i].PageCount+res->Segs[i].BasePage)*ps-1);
 620                for(j=15, first=1; j>=0; j--) {
 621                        if (mask&(1<<j)) {
 622                                if (first) first=0;
 623                                else printk(", ");
 624                                printk("%s", Usage[j]);
 625                        }
 626                }
 627                printk("\n");
 628        }
 629}
 630
 631/*
 632 * Spit out some info about residual data
 633 */
 634void print_residual_device_info(void)
 635{
 636        int i;
 637        union _PnP_TAG_PACKET *pkt;
 638        PPC_DEVICE *dev;
 639#define did dev->DeviceId
 640
 641        /* make sure we have residual data first */
 642        if (!have_residual_data)
 643                return;
 644        printk("Residual: %ld devices\n", res->ActualNumDevices);
 645        for ( i = 0;
 646              i < res->ActualNumDevices ;
 647              i++)
 648        {
 649                dev = &res->Devices[i];
 650                /*
 651                 * pci devices
 652                 */
 653                if ( did.BusId & PCIDEVICE )
 654                {
 655                        printk("PCI Device:");
 656                        /* unknown vendor */
 657                        if ( !strncmp( "Unknown", pci_strvendor(did.DevId>>16), 7) )
 658                                printk(" id %08lx types %d/%d", did.DevId,
 659                                       did.BaseType, did.SubType);
 660                        /* known vendor */
 661                        else
 662                                printk(" %s %s",
 663                                       pci_strvendor(did.DevId>>16),
 664                                       pci_strdev(did.DevId>>16,
 665                                                  did.DevId&0xffff)
 666                                        );
 667
 668                        if ( did.BusId & PNPISADEVICE )
 669                        {
 670                                printk(" pnp:");
 671                                /* get pnp info on the device */
 672                                pkt = (union _PnP_TAG_PACKET *)
 673                                        &res->DevicePnPHeap[dev->AllocatedOffset];
 674                                for (; pkt->S1_Pack.Tag != DF_END_TAG;
 675                                     pkt++ )
 676                                {
 677                                        if ( (pkt->S1_Pack.Tag == S4_Packet) ||
 678                                             (pkt->S1_Pack.Tag == S4_Packet_flags) )
 679                                                printk(" irq %02x%02x",
 680                                                       pkt->S4_Pack.IRQMask[0],
 681                                                       pkt->S4_Pack.IRQMask[1]);
 682                                }
 683                        }
 684                        printk("\n");
 685                        continue;
 686                }
 687                /*
 688                 * isa devices
 689                 */
 690                if ( did.BusId & ISADEVICE )
 691                {
 692                        printk("ISA Device: basetype: %d subtype: %d",
 693                               did.BaseType, did.SubType);
 694                        printk("\n");
 695                        continue;
 696                }
 697                /*
 698                 * eisa devices
 699                 */
 700                if ( did.BusId & EISADEVICE )
 701                {
 702                        printk("EISA Device: basetype: %d subtype: %d",
 703                               did.BaseType, did.SubType);
 704                        printk("\n");
 705                        continue;
 706                }
 707                /*
 708                 * proc bus devices
 709                 */
 710                if ( did.BusId & PROCESSORDEVICE )
 711                {
 712                        printk("ProcBus Device: basetype: %d subtype: %d",
 713                               did.BaseType, did.SubType);
 714                        printk("\n");
 715                        continue;
 716                }
 717                /*
 718                 * pcmcia devices
 719                 */
 720                if ( did.BusId & PCMCIADEVICE )
 721                {
 722                        printk("PCMCIA Device: basetype: %d subtype: %d",
 723                               did.BaseType, did.SubType);
 724                        printk("\n");
 725                        continue;
 726                }
 727                printk("Unknown bus access device: busid %lx\n",
 728                       did.BusId);
 729        }
 730}
 731#endif
 732
 733/* Returns the device index in the residual data,
 734   any of the search items may be set as -1 for wildcard,
 735   DevID number field (second halfword) is big endian !
 736
 737   Examples:
 738   - search for the Interrupt controller (8259 type), 2 methods:
 739     1) i8259 = residual_find_device(~0,
 740                                     NULL,
 741                                     SystemPeripheral,
 742                                     ProgrammableInterruptController,
 743                                     ISA_PIC,
 744                                     0);
 745     2) i8259 = residual_find_device(~0, "PNP0000", -1, -1, -1, 0)
 746
 747   - search for the first two serial devices, whatever their type)
 748     iserial1 = residual_find_device(~0,NULL,
 749                                     CommunicationsDevice,
 750                                     RS232Device,
 751                                     -1, 0)
 752     iserial2 = residual_find_device(~0,NULL,
 753                                     CommunicationsDevice,
 754                                     RS232Device,
 755                                     -1, 1)
 756   - but search for typical COM1 and COM2 is not easy due to the
 757     fact that the interface may be anything and the name "PNP0500" or
 758     "PNP0501". Quite bad.
 759
 760*/
 761
 762/* devid are easier to uncompress than to compress, so to minimize bloat
 763in this rarely used area we unencode and compare */
 764
 765/* in residual data number is big endian in the device table and
 766little endian in the heap, so we use two parameters to avoid writing
 767two very similar functions */
 768
 769static int __init same_DevID(unsigned short vendor,
 770               unsigned short Number,
 771               char * str)
 772{
 773        static unsigned const char hexdigit[]="0123456789ABCDEF";
 774        if (strlen(str)!=7) return 0;
 775        if ( ( ((vendor>>10)&0x1f)+'A'-1 == str[0])  &&
 776             ( ((vendor>>5)&0x1f)+'A'-1 == str[1])   &&
 777             ( (vendor&0x1f)+'A'-1 == str[2])        &&
 778             (hexdigit[(Number>>12)&0x0f] == str[3]) &&
 779             (hexdigit[(Number>>8)&0x0f] == str[4])  &&
 780             (hexdigit[(Number>>4)&0x0f] == str[5])  &&
 781             (hexdigit[Number&0x0f] == str[6]) ) return 1;
 782        return 0;
 783}
 784
 785PPC_DEVICE __init *residual_find_device(unsigned long BusMask,
 786                         unsigned char * DevID,
 787                         int BaseType,
 788                         int SubType,
 789                         int Interface,
 790                         int n)
 791{
 792        int i;
 793        if (!have_residual_data) return NULL;
 794        for (i=0; i<res->ActualNumDevices; i++) {
 795#define Dev res->Devices[i].DeviceId
 796                if ( (Dev.BusId&BusMask)                                  &&
 797                     (BaseType==-1 || Dev.BaseType==BaseType)             &&
 798                     (SubType==-1 || Dev.SubType==SubType)                &&
 799                     (Interface==-1 || Dev.Interface==Interface)          &&
 800                     (DevID==NULL || same_DevID((Dev.DevId>>16)&0xffff,
 801                                                Dev.DevId&0xffff, DevID)) &&
 802                     !(n--) ) return res->Devices+i;
 803#undef Dev
 804        }
 805        return NULL;
 806}
 807
 808PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask,
 809                         unsigned short DevID,
 810                         int BaseType,
 811                         int SubType,
 812                         int Interface,
 813                         int n)
 814{
 815        int i;
 816        if (!have_residual_data) return NULL;
 817        for (i=0; i<res->ActualNumDevices; i++) {
 818#define Dev res->Devices[i].DeviceId
 819                if ( (Dev.BusId&BusMask)                                  &&
 820                     (BaseType==-1 || Dev.BaseType==BaseType)             &&
 821                     (SubType==-1 || Dev.SubType==SubType)                &&
 822                     (Interface==-1 || Dev.Interface==Interface)          &&
 823                     (DevID==0xffff || (Dev.DevId&0xffff) == DevID)       &&
 824                     !(n--) ) return res->Devices+i;
 825#undef Dev
 826        }
 827        return NULL;
 828}
 829
 830static int __init
 831residual_scan_pcibridge(PnP_TAG_PACKET * pkt, struct pci_dev *dev)
 832{
 833        int irq = -1;
 834
 835#define data pkt->L4_Pack.L4_Data.L4_PPCPack.PPCData
 836        if (dev->bus->number == data[16]) {
 837                int i, size;
 838
 839                size = 3 + ld_le16((u_short *) (&pkt->L4_Pack.Count0));
 840                for (i = 20; i < size - 4; i += 12) {
 841                        unsigned char pin;
 842                        int line_irq;
 843
 844                        if (dev->devfn != data[i + 1])
 845                                continue;
 846
 847                        pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 848                        if (pin) {
 849                                line_irq = ld_le16((unsigned short *)
 850                                                (&data[i + 4 + 2 * (pin - 1)]));
 851                                irq = (line_irq == 0xffff) ? 0
 852                                                           : line_irq & 0x7fff;
 853                        } else
 854                                irq = 0;
 855
 856                        break;
 857                }
 858        }
 859#undef data
 860
 861        return irq;
 862}
 863
 864int __init
 865residual_pcidev_irq(struct pci_dev *dev)
 866{
 867        int i = 0;
 868        int irq = -1;
 869        PPC_DEVICE *bridge;
 870
 871        while ((bridge = residual_find_device
 872               (-1, NULL, BridgeController, PCIBridge, -1, i++))) {
 873
 874                PnP_TAG_PACKET *pkt;
 875                if (bridge->AllocatedOffset) {
 876                        pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
 877                                           bridge->AllocatedOffset, 3, 0);
 878                        if (!pkt)
 879                                continue;
 880
 881                        irq = residual_scan_pcibridge(pkt, dev);
 882                        if (irq != -1)
 883                                break;
 884                }
 885        }
 886
 887        return (irq < 0) ? 0 : irq;
 888}
 889
 890void __init residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
 891{
 892        PPC_DEVICE *dev;
 893        int i = 0;
 894        unsigned short irq_mask = 0x000; /* default to edge */
 895
 896        while ((dev = residual_find_device(-1, NULL, -1, -1, -1, i++))) {
 897                PnP_TAG_PACKET *pkt;
 898                unsigned short mask;
 899                int size;
 900                int offset = dev->AllocatedOffset;
 901
 902                if (!offset)
 903                        continue;
 904
 905                pkt = PnP_find_packet(res->DevicePnPHeap + offset,
 906                                              IRQFormat, 0);
 907                if (!pkt)
 908                        continue;
 909
 910                size = tag_small_count(pkt->S1_Pack.Tag) + 1;
 911                mask = ld_le16((unsigned short *)pkt->S4_Pack.IRQMask);
 912                if (size > 3 && (pkt->S4_Pack.IRQInfo & 0x0c))
 913                        irq_mask |= mask;
 914        }
 915
 916        *irq_edge_mask_lo = irq_mask & 0xff;
 917        *irq_edge_mask_hi = irq_mask >> 8;
 918}
 919
 920unsigned int __init residual_isapic_addr(void)
 921{
 922        PPC_DEVICE *isapic;
 923        PnP_TAG_PACKET *pkt;
 924        unsigned int addr;
 925
 926        isapic = residual_find_device(~0, NULL, SystemPeripheral,
 927                                      ProgrammableInterruptController,
 928                                      ISA_PIC, 0);
 929        if (!isapic)
 930                goto unknown;
 931
 932        pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
 933                                                isapic->AllocatedOffset, 9, 0);
 934        if (!pkt)
 935                goto unknown;
 936
 937#define p pkt->L4_Pack.L4_Data.L4_PPCPack
 938        /* Must be 32-bit system address */
 939        if (!((p.PPCData[0] == 3) && (p.PPCData[1] == 32)))
 940                goto unknown;
 941
 942        /* It doesn't seem to work where length != 1 (what can I say? :-/ ) */
 943        if (ld_le32((unsigned int *)(p.PPCData + 12)) != 1)
 944                goto unknown;
 945
 946        addr = ld_le32((unsigned int *) (p.PPCData + 4));
 947#undef p
 948        return addr;
 949unknown:
 950        return 0;
 951}
 952
 953PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
 954                                unsigned packet_tag,
 955                                int n)
 956{
 957        unsigned mask, masked_tag, size;
 958        if(!p) return NULL;
 959        if (tag_type(packet_tag)) mask=0xff; else mask=0xF8;
 960        masked_tag = packet_tag&mask;
 961        for(; *p != END_TAG; p+=size) {
 962                if ((*p & mask) == masked_tag && !(n--))
 963                        return (PnP_TAG_PACKET *) p;
 964                if (tag_type(*p))
 965                        size=ld_le16((unsigned short *)(p+1))+3;
 966                else
 967                        size=tag_small_count(*p)+1;
 968        }
 969        return NULL; /* not found */
 970}
 971
 972PnP_TAG_PACKET __init *PnP_find_small_vendor_packet(unsigned char *p,
 973                                             unsigned packet_type,
 974                                             int n)
 975{
 976        int next=0;
 977        while (p) {
 978                p = (unsigned char *) PnP_find_packet(p, 0x70, next);
 979                if (p && p[1]==packet_type && !(n--))
 980                        return (PnP_TAG_PACKET *) p;
 981                next = 1;
 982        };
 983        return NULL; /* not found */
 984}
 985
 986PnP_TAG_PACKET __init *PnP_find_large_vendor_packet(unsigned char *p,
 987                                           unsigned packet_type,
 988                                           int n)
 989{
 990        int next=0;
 991        while (p) {
 992                p = (unsigned char *) PnP_find_packet(p, 0x84, next);
 993                if (p && p[3]==packet_type && !(n--))
 994                        return (PnP_TAG_PACKET *) p;
 995                next = 1;
 996        };
 997        return NULL; /* not found */
 998}
 999
1000#ifdef CONFIG_PROC_PREPRESIDUAL
1001static int proc_prep_residual_read(char * buf, char ** start, off_t off,
1002                int count, int *eof, void *data)
1003{
1004        int n;
1005
1006        n = res->ResidualLength - off;
1007        if (n < 0) {
1008                *eof = 1;
1009                n = 0;
1010        }
1011        else {
1012                if (n > count)
1013                        n = count;
1014                else
1015                        *eof = 1;
1016
1017                memcpy(buf, (char *)res + off, n);
1018                *start = buf;
1019        }
1020
1021        return n;
1022}
1023
1024int __init
1025proc_prep_residual_init(void)
1026{
1027        if (have_residual_data)
1028                create_proc_read_entry("residual", S_IRUGO, NULL,
1029                                        proc_prep_residual_read, NULL);
1030        return 0;
1031}
1032
1033__initcall(proc_prep_residual_init);
1034#endif
1035