ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ppc / platforms / residual.c
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
50 unsigned char __res[sizeof(RESIDUAL)] __prepdata = {0,};
51 RESIDUAL *res = (RESIDUAL *)&__res;
52
53 char * 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
69 unsigned 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
126 unsigned 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
244 static 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
253 static 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
264 static 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
289 static 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
356 static 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
466 static 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
478 static 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
500 void __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
569 static 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  */
634 void 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
763 in this rarely used area we unencode and compare */
764
765 /* in residual data number is big endian in the device table and
766 little endian in the heap, so we use two parameters to avoid writing
767 two very similar functions */
768
769 static 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
785 PPC_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
808 PPC_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
830 PnP_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
849 PnP_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
863 PnP_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
878 static 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
901 int __init
902 proc_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         return 0;
908 }
909
910 __initcall(proc_prep_residual_init);
911 #endif