linux-old/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/blk.h>
  40#include <linux/ioport.h>
  41#include <linux/pci.h>
  42#include <linux/ide.h>
  43
  44#include <asm/sections.h>
  45#include <asm/mmu.h>
  46#include <asm/processor.h>
  47#include <asm/io.h>
  48#include <asm/pgtable.h>
  49#include <asm/ide.h>
  50
  51
  52unsigned char __res[sizeof(RESIDUAL)] __prepdata = {0,};
  53RESIDUAL *res = (RESIDUAL *)&__res;
  54
  55char * PnP_BASE_TYPES[] __initdata = {
  56  "Reserved",
  57  "MassStorageDevice",
  58  "NetworkInterfaceController",
  59  "DisplayController",
  60  "MultimediaController",
  61  "MemoryController",
  62  "BridgeController",
  63  "CommunicationsDevice",
  64  "SystemPeripheral",
  65  "InputDevice",
  66  "ServiceProcessor"
  67  };
  68
  69/* Device Sub Type Codes */
  70
  71unsigned char * PnP_SUB_TYPES[] __initdata = {
  72  "\001\000SCSIController",
  73  "\001\001IDEController",
  74  "\001\002FloppyController",
  75  "\001\003IPIController",
  76  "\001\200OtherMassStorageController",
  77  "\002\000EthernetController",
  78  "\002\001TokenRingController",
  79  "\002\002FDDIController",
  80  "\002\0x80OtherNetworkController",
  81  "\003\000VGAController",
  82  "\003\001SVGAController",
  83  "\003\002XGAController",
  84  "\003\200OtherDisplayController",
  85  "\004\000VideoController",
  86  "\004\001AudioController",
  87  "\004\200OtherMultimediaController",
  88  "\005\000RAM",
  89  "\005\001FLASH",
  90  "\005\200OtherMemoryDevice",
  91  "\006\000HostProcessorBridge",
  92  "\006\001ISABridge",
  93  "\006\002EISABridge",
  94  "\006\003MicroChannelBridge",
  95  "\006\004PCIBridge",
  96  "\006\005PCMCIABridge",
  97  "\006\006VMEBridge",
  98  "\006\200OtherBridgeDevice",
  99  "\007\000RS232Device",
 100  "\007\001ATCompatibleParallelPort",
 101  "\007\200OtherCommunicationsDevice",
 102  "\010\000ProgrammableInterruptController",
 103  "\010\001DMAController",
 104  "\010\002SystemTimer",
 105  "\010\003RealTimeClock",
 106  "\010\004L2Cache",
 107  "\010\005NVRAM",
 108  "\010\006PowerManagement",
 109  "\010\007CMOS",
 110  "\010\010OperatorPanel",
 111  "\010\011ServiceProcessorClass1",
 112  "\010\012ServiceProcessorClass2",
 113  "\010\013ServiceProcessorClass3",
 114  "\010\014GraphicAssist",
 115  "\010\017SystemPlanar",
 116  "\010\200OtherSystemPeripheral",
 117  "\011\000KeyboardController",
 118  "\011\001Digitizer",
 119  "\011\002MouseController",
 120  "\011\003TabletController",
 121  "\011\0x80OtherInputController",
 122  "\012\000GeneralMemoryController",
 123  NULL
 124};
 125
 126/* Device Interface Type Codes */
 127
 128unsigned char * PnP_INTERFACES[] __initdata = {
 129  "\000\000\000General",
 130  "\001\000\000GeneralSCSI",
 131  "\001\001\000GeneralIDE",
 132  "\001\001\001ATACompatible",
 133
 134  "\001\002\000GeneralFloppy",
 135  "\001\002\001Compatible765",
 136  "\001\002\002NS398_Floppy",         /* NS Super I/O wired to use index
 137                                         register at port 398 and data
 138                                         register at port 399               */
 139  "\001\002\003NS26E_Floppy",         /* Ports 26E and 26F                  */
 140  "\001\002\004NS15C_Floppy",         /* Ports 15C and 15D                  */
 141  "\001\002\005NS2E_Floppy",          /* Ports 2E and 2F                    */
 142  "\001\002\006CHRP_Floppy",          /* CHRP Floppy in PR*P system         */
 143
 144  "\001\003\000GeneralIPI",
 145
 146  "\002\000\000GeneralEther",
 147  "\002\001\000GeneralToken",
 148  "\002\002\000GeneralFDDI",
 149
 150  "\003\000\000GeneralVGA",
 151  "\003\001\000GeneralSVGA",
 152  "\003\002\000GeneralXGA",
 153
 154  "\004\000\000GeneralVideo",
 155  "\004\001\000GeneralAudio",
 156  "\004\001\001CS4232Audio",            /* CS 4232 Plug 'n Play Configured    */
 157
 158  "\005\000\000GeneralRAM",
 159  /* This one is obviously wrong ! */
 160  "\005\000\000PCIMemoryController",    /* PCI Config Method                  */
 161  "\005\000\001RS6KMemoryController",   /* RS6K Config Method                 */
 162  "\005\001\000GeneralFLASH",
 163
 164  "\006\000\000GeneralHostBridge",
 165  "\006\001\000GeneralISABridge",
 166  "\006\002\000GeneralEISABridge",
 167  "\006\003\000GeneralMCABridge",
 168  /* GeneralPCIBridge = 0, */
 169  "\006\004\000PCIBridgeDirect",
 170  "\006\004\001PCIBridgeIndirect",
 171  "\006\004\002PCIBridgeRS6K",
 172  "\006\005\000GeneralPCMCIABridge",
 173  "\006\006\000GeneralVMEBridge",
 174
 175  "\007\000\000GeneralRS232",
 176  "\007\000\001COMx",
 177  "\007\000\002Compatible16450",
 178  "\007\000\003Compatible16550",
 179  "\007\000\004NS398SerPort",         /* NS Super I/O wired to use index
 180                                         register at port 398 and data
 181                                         register at port 399               */
 182  "\007\000\005NS26ESerPort",         /* Ports 26E and 26F                  */
 183  "\007\000\006NS15CSerPort",         /* Ports 15C and 15D                  */
 184  "\007\000\007NS2ESerPort",          /* Ports 2E and 2F                    */
 185
 186  "\007\001\000GeneralParPort",
 187  "\007\001\001LPTx",
 188  "\007\001\002NS398ParPort",         /* NS Super I/O wired to use index
 189                                         register at port 398 and data
 190                                         register at port 399               */
 191  "\007\001\003NS26EParPort",         /* Ports 26E and 26F                  */
 192  "\007\001\004NS15CParPort",         /* Ports 15C and 15D                  */
 193  "\007\001\005NS2EParPort",          /* Ports 2E and 2F                    */
 194
 195  "\010\000\000GeneralPIC",
 196  "\010\000\001ISA_PIC",
 197  "\010\000\002EISA_PIC",
 198  "\010\000\003MPIC",
 199  "\010\000\004RS6K_PIC",
 200
 201  "\010\001\000GeneralDMA",
 202  "\010\001\001ISA_DMA",
 203  "\010\001\002EISA_DMA",
 204
 205  "\010\002\000GeneralTimer",
 206  "\010\002\001ISA_Timer",
 207  "\010\002\002EISA_Timer",
 208  "\010\003\000GeneralRTC",
 209  "\010\003\001ISA_RTC",
 210
 211  "\010\004\001StoreThruOnly",
 212  "\010\004\002StoreInEnabled",
 213  "\010\004\003RS6KL2Cache",
 214
 215  "\010\005\000IndirectNVRAM",        /* Indirectly addressed               */
 216  "\010\005\001DirectNVRAM",          /* Memory Mapped                      */
 217  "\010\005\002IndirectNVRAM24",      /* Indirectly addressed - 24 bit      */
 218
 219  "\010\006\000GeneralPowerManagement",
 220  "\010\006\001EPOWPowerManagement",
 221  "\010\006\002PowerControl",         // d1378
 222
 223  "\010\007\000GeneralCMOS",
 224
 225  "\010\010\000GeneralOPPanel",
 226  "\010\010\001HarddiskLight",
 227  "\010\010\002CDROMLight",
 228  "\010\010\003PowerLight",
 229  "\010\010\004KeyLock",
 230  "\010\010\005ANDisplay",            /* AlphaNumeric Display               */
 231  "\010\010\006SystemStatusLED",      /* 3 digit 7 segment LED              */
 232  "\010\010\007CHRP_SystemStatusLED", /* CHRP LEDs in PR*P system           */
 233
 234  "\010\011\000GeneralServiceProcessor",
 235  "\010\012\000GeneralServiceProcessor",
 236  "\010\013\000GeneralServiceProcessor",
 237
 238  "\010\014\001TransferData",
 239  "\010\014\002IGMC32",
 240  "\010\014\003IGMC64",
 241
 242  "\010\017\000GeneralSystemPlanar",   /* 10/5/95                            */
 243  NULL
 244  };
 245
 246static const unsigned char __init *PnP_SUB_TYPE_STR(unsigned char BaseType,
 247                                             unsigned char SubType) {
 248        unsigned char ** s=PnP_SUB_TYPES;
 249        while (*s && !((*s)[0]==BaseType
 250                       && (*s)[1]==SubType)) s++;
 251        if (*s) return *s+2;
 252        else return("Unknown !");
 253};
 254
 255static const unsigned char __init *PnP_INTERFACE_STR(unsigned char BaseType,
 256                                              unsigned char SubType,
 257                                              unsigned char Interface) {
 258        unsigned char ** s=PnP_INTERFACES;
 259        while (*s && !((*s)[0]==BaseType
 260                       && (*s)[1]==SubType
 261                       && (*s)[2]==Interface)) s++;
 262        if (*s) return *s+3;
 263        else return NULL;
 264};
 265
 266static void __init printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
 267        int i, c;
 268        char decomp[4];
 269#define p pkt->S14_Pack.S14_Data.S14_PPCPack
 270        switch(p.Type) {
 271        case 1:
 272          /* Decompress first 3 chars */
 273          c = *(unsigned short *)p.PPCData;
 274          decomp[0]='A'-1+((c>>10)&0x1F);
 275          decomp[1]='A'-1+((c>>5)&0x1F);
 276          decomp[2]='A'-1+(c&0x1F);
 277          decomp[3]=0;
 278          printk("    Chip identification: %s%4.4X\n",
 279                 decomp, ld_le16((unsigned short *)(p.PPCData+2)));
 280          break;
 281        default:
 282          printk("    Small vendor item type 0x%2.2x, data (hex): ",
 283                 p.Type);
 284          for(i=0; i<size-2; i++) printk("%2.2x ", p.PPCData[i]);
 285          printk("\n");
 286          break;
 287        }
 288#undef p
 289}
 290
 291static void __init printsmallpacket(PnP_TAG_PACKET * pkt, int size) {
 292        static const unsigned char * intlevel[] = {"high", "low"};
 293        static const unsigned char * intsense[] = {"edge", "level"};
 294
 295        switch (tag_small_item_name(pkt->S1_Pack.Tag)) {
 296        case PnPVersion:
 297          printk("    PnPversion 0x%x.%x\n",
 298                 pkt->S1_Pack.Version[0], /* How to interpret version ? */
 299                 pkt->S1_Pack.Version[1]);
 300          break;
 301//      case Logicaldevice:
 302          break;
 303//      case CompatibleDevice:
 304          break;
 305        case IRQFormat:
 306#define p pkt->S4_Pack
 307          printk("    IRQ Mask 0x%4.4x, %s %s sensitive\n",
 308                 ld_le16((unsigned short *)p.IRQMask),
 309                 intlevel[(size>3) ? !(p.IRQInfo&0x05) : 0],
 310                 intsense[(size>3) ? !(p.IRQInfo&0x03) : 0]);
 311#undef p
 312          break;
 313        case DMAFormat:
 314#define p pkt->S5_Pack
 315          printk("    DMA channel mask 0x%2.2x, info 0x%2.2x\n",
 316                 p.DMAMask, p.DMAInfo);
 317#undef p
 318          break;
 319        case StartDepFunc:
 320          printk("Start dependent function:\n");
 321          break;
 322        case EndDepFunc:
 323          printk("End dependent function\n");
 324          break;
 325        case IOPort:
 326#define p pkt->S8_Pack
 327          printk("    Variable (%d decoded bits) I/O port\n"
 328                 "      from 0x%4.4x to 0x%4.4x, alignment %d, %d ports\n",
 329                 p.IOInfo&ISAAddr16bit?16:10,
 330                 ld_le16((unsigned short *)p.RangeMin),
 331                 ld_le16((unsigned short *)p.RangeMax),
 332                 p.IOAlign, p.IONum);
 333#undef p
 334          break;
 335        case FixedIOPort:
 336#define p pkt->S9_Pack
 337          printk("    Fixed (10 decoded bits) I/O port from %3.3x to %3.3x\n",
 338                 (p.Range[1]<<8)|p.Range[0],
 339                 ((p.Range[1]<<8)|p.Range[0])+p.IONum-1);
 340#undef p
 341          break;
 342        case Res1:
 343        case Res2:
 344        case Res3:
 345          printk("    Undefined packet type %d!\n",
 346                 tag_small_item_name(pkt->S1_Pack.Tag));
 347          break;
 348        case SmallVendorItem:
 349          printsmallvendor(pkt,size);
 350          break;
 351        default:
 352          printk("    Type 0x2.2x%d, size=%d\n",
 353                 pkt->S1_Pack.Tag, size);
 354          break;
 355        }
 356}
 357
 358static void __init printlargevendor(PnP_TAG_PACKET * pkt, int size) {
 359        static const unsigned char * addrtype[] = {"I/O", "Memory", "System"};
 360        static const unsigned char * inttype[] = {"8259", "MPIC", "RS6k BUID %d"};
 361        static const unsigned char * convtype[] = {"Bus Memory", "Bus I/O", "DMA"};
 362        static const unsigned char * transtype[] = {"direct", "mapped", "direct-store segment"};
 363        static const unsigned char * L2type[] = {"WriteThru", "CopyBack"};
 364        static const unsigned char * L2assoc[] = {"DirectMapped", "2-way set"};
 365
 366        int i;
 367        char tmpstr[30], *t;
 368#define p pkt->L4_Pack.L4_Data.L4_PPCPack
 369        switch(p.Type) {
 370        case 2:
 371          printk("    %d K %s %s L2 cache, %d/%d bytes line/sector size\n",
 372                 ld_le32((unsigned int *)p.PPCData),
 373                 L2type[p.PPCData[10]-1],
 374                 L2assoc[p.PPCData[4]-1],
 375                 ld_le16((unsigned short *)p.PPCData+3),
 376                 ld_le16((unsigned short *)p.PPCData+4));
 377          break;
 378        case 3:
 379          printk("    PCI Bridge parameters\n"
 380                 "      ConfigBaseAddress %0x\n"
 381                 "      ConfigBaseData %0x\n"
 382                 "      Bus number %d\n",
 383                 ld_le32((unsigned int *)p.PPCData),
 384                 ld_le32((unsigned int *)(p.PPCData+8)),
 385                 p.PPCData[16]);
 386          for(i=20; i<size-4; i+=12) {
 387                int j, first;
 388                if(p.PPCData[i]) printk("      PCI Slot %d", p.PPCData[i]);
 389                else printk ("      Integrated PCI device");
 390                for(j=0, first=1, t=tmpstr; j<4; j++) {
 391                        int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
 392                        if(line!=0xffff){
 393                                if(first) first=0; else *t++='/';
 394                                *t++='A'+j;
 395                        }
 396                }
 397                *t='\0';
 398                printk(" DevFunc 0x%x interrupt line(s) %s routed to",
 399                       p.PPCData[i+1],tmpstr);
 400                sprintf(tmpstr,
 401                        inttype[p.PPCData[i+2]-1],
 402                        p.PPCData[i+3]);
 403                printk(" %s line(s) ",
 404                       tmpstr);
 405                for(j=0, first=1, t=tmpstr; j<4; j++) {
 406                        int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
 407                        if(line!=0xffff){
 408                                if(first) first=0; else *t++='/';
 409                                t+=sprintf(t,"%d(%c)",
 410                                           line&0x7fff,
 411                                           line&0x8000?'E':'L');
 412                        }
 413                }
 414                printk("%s\n",tmpstr);
 415          }
 416          break;
 417        case 5:
 418          printk("    Bridge address translation, %s decoding:\n"
 419                 "      Processor  Bus        Size       Conversion Translation\n"
 420                 "      0x%8.8x 0x%8.8x 0x%8.8x %s %s\n",
 421                 p.PPCData[0]&1 ? "positive" : "subtractive",
 422                 ld_le32((unsigned int *)p.PPCData+1),
 423                 ld_le32((unsigned int *)p.PPCData+3),
 424                 ld_le32((unsigned int *)p.PPCData+5),
 425                 convtype[p.PPCData[2]-1],
 426                 transtype[p.PPCData[1]-1]);
 427          break;
 428        case 6:
 429          printk("    Bus speed %d Hz, %d slot(s)\n",
 430                 ld_le32((unsigned int *)p.PPCData),
 431                 p.PPCData[4]);
 432          break;
 433        case 7:
 434          printk("    SCSI buses: %d, id(s):", p.PPCData[0]);
 435          for(i=1; i<=p.PPCData[0]; i++)
 436            printk(" %d%c", p.PPCData[i], i==p.PPCData[0] ? '\n' : ',');
 437          break;
 438        case 9:
 439          printk("    %s address (%d bits), at 0x%x size 0x%x bytes\n",
 440                 addrtype[p.PPCData[0]-1],
 441                 p.PPCData[1],
 442                 ld_le32((unsigned int *)(p.PPCData+4)),
 443                 ld_le32((unsigned int *)(p.PPCData+12)));
 444          break;
 445        case 10:
 446          sprintf(tmpstr,
 447                  inttype[p.PPCData[0]-1],
 448                  p.PPCData[1]);
 449
 450          printk("    ISA interrupts routed to %s\n"
 451                 "      lines",
 452                 tmpstr);
 453          for(i=0; i<16; i++) {
 454                int line=ld_le16((unsigned short *)p.PPCData+i+1);
 455                if (line!=0xffff) printk(" %d(IRQ%d)", line, i);
 456          }
 457          printk("\n");
 458          break;
 459        default:
 460          printk("    Large vendor item type 0x%2.2x\n      Data (hex):",
 461                 p.Type);
 462          for(i=0; i<size-4; i++) printk(" %2.2x", p.PPCData[i]);
 463          printk("\n");
 464#undef p
 465        }
 466}
 467
 468static void __init printlargepacket(PnP_TAG_PACKET * pkt, int size) {
 469        switch (tag_large_item_name(pkt->S1_Pack.Tag)) {
 470        case LargeVendorItem:
 471          printlargevendor(pkt, size);
 472          break;
 473        default:
 474          printk("    Type 0x2.2x%d, size=%d\n",
 475                 pkt->S1_Pack.Tag, size);
 476          break;
 477        }
 478}
 479static void __init printpackets(PnP_TAG_PACKET * pkt, const char * cat) {
 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 ( res->ResidualLength == 0 )
 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 ( res->ResidualLength == 0 )
 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 ( !res->ResidualLength ) 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 0;
 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 ( !res->ResidualLength ) 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 0;
 828}
 829
 830PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
 831                                unsigned packet_tag,
 832                                int n)
 833{
 834        unsigned mask, masked_tag, size;
 835        if(!p) return 0;
 836        if (tag_type(packet_tag)) mask=0xff; else mask=0xF8;
 837        masked_tag = packet_tag&mask;
 838        for(; *p != END_TAG; p+=size) {
 839                if ((*p & mask) == masked_tag && !(n--))
 840                        return (PnP_TAG_PACKET *) p;
 841                if (tag_type(*p))
 842                        size=ld_le16((unsigned short *)(p+1))+3;
 843                else
 844                        size=tag_small_count(*p)+1;
 845        }
 846        return 0; /* not found */
 847}
 848
 849PnP_TAG_PACKET __init *PnP_find_small_vendor_packet(unsigned char *p,
 850                                             unsigned packet_type,
 851                                             int n)
 852{
 853        int next=0;
 854        while (p) {
 855                p = (unsigned char *) PnP_find_packet(p, 0x70, next);
 856                if (p && p[1]==packet_type && !(n--))
 857                        return (PnP_TAG_PACKET *) p;
 858                next = 1;
 859        };
 860        return 0; /* not found */
 861}
 862
 863PnP_TAG_PACKET __init *PnP_find_large_vendor_packet(unsigned char *p,
 864                                           unsigned packet_type,
 865                                           int n)
 866{
 867        int next=0;
 868        while (p) {
 869                p = (unsigned char *) PnP_find_packet(p, 0x84, next);
 870                if (p && p[3]==packet_type && !(n--))
 871                        return (PnP_TAG_PACKET *) p;
 872                next = 1;
 873        };
 874        return 0; /* not found */
 875}
 876
 877#ifdef CONFIG_PROC_PREPRESIDUAL
 878static int proc_prep_residual_read(char * buf, char ** start, off_t off,
 879                int count, int *eof, void *data)
 880{
 881        int n;
 882
 883        n = res->ResidualLength - off;
 884        if (n < 0) {
 885                *eof = 1;
 886                n = 0;
 887        }
 888        else {
 889                if (n > count)
 890                        n = count;
 891                else
 892                        *eof = 1;
 893
 894                memcpy(buf, (char *)res + off, n);
 895                *start = buf;
 896        }
 897
 898        return n;
 899}
 900
 901void __init
 902proc_prep_residual_init(void)
 903{
 904        if (res->ResidualLength)
 905                create_proc_read_entry("residual", S_IRUGO, NULL,
 906                                        proc_prep_residual_read, NULL);
 907}
 908
 909__initcall(proc_prep_residual_init);
 910#endif
 911
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.