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