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 
PnP_SUB_TYPE_STR(unsigned char BaseType,unsigned char SubType)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 
PnP_INTERFACE_STR(unsigned char BaseType,unsigned char SubType,unsigned char Interface)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 
printsmallvendor(PnP_TAG_PACKET * pkt,int size)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 
printsmallpacket(PnP_TAG_PACKET * pkt,int size)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 
printlargevendor(PnP_TAG_PACKET * pkt,int size)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 
printlargepacket(PnP_TAG_PACKET * pkt,int size)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 }
printpackets(PnP_TAG_PACKET * pkt,const char * cat)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 
print_residual_device_info(void)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 
same_DevID(unsigned short vendor,unsigned short Number,char * str)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 
residual_find_device(unsigned long BusMask,unsigned char * DevID,int BaseType,int SubType,int Interface,int n)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 
residual_find_device_id(unsigned long BusMask,unsigned short DevID,int BaseType,int SubType,int Interface,int n)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 
PnP_find_packet(unsigned char * p,unsigned packet_tag,int n)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 
PnP_find_small_vendor_packet(unsigned char * p,unsigned packet_type,int n)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 
PnP_find_large_vendor_packet(unsigned char * p,unsigned packet_type,int n)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
proc_prep_residual_read(char * buf,char ** start,off_t off,int count,int * eof,void * data)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
proc_prep_residual_init(void)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
911