more changes on original files
[linux-2.4.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/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
52 unsigned char __res[sizeof(RESIDUAL)] __prepdata = {0,};
53 RESIDUAL *res = (RESIDUAL *)&__res;
54
55 char * 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
71 unsigned 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
128 unsigned 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
246 static 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
255 static 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
266 static 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
291 static 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
358 static 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
468 static 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 }
479 static 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
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 void __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 }
908
909 __initcall(proc_prep_residual_init);
910 #endif