docbook: fix fatal rapidio yet again (and more to come)
[linux/fpc-iii.git] / arch / ppc / platforms / residual.c
blob18495e754e3086be415af6e69f86f927fd4ce978
1 /*
2 * Code to deal with the PReP residual data.
4 * Written by: Cort Dougan (cort@cs.nmt.edu)
5 * Improved _greatly_ and rewritten by Gabriel Paubert (paubert@iram.es)
7 * This file is based on the following documentation:
9 * IBM Power Personal Systems Architecture
10 * Residual Data
11 * Document Number: PPS-AR-FW0001
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.
19 #include <linux/string.h>
20 #include <asm/residual.h>
21 #include <asm/pnp.h>
22 #include <asm/byteorder.h>
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>
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>
49 unsigned char __res[sizeof(RESIDUAL)] = {0,};
50 RESIDUAL *res = (RESIDUAL *)&__res;
52 char * 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"
66 /* Device Sub Type Codes */
68 unsigned 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
123 /* Device Interface Type Codes */
125 unsigned char * PnP_INTERFACES[] __initdata = {
126 "\000\000\000General",
127 "\001\000\000GeneralSCSI",
128 "\001\001\000GeneralIDE",
129 "\001\001\001ATACompatible",
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 */
141 "\001\003\000GeneralIPI",
143 "\002\000\000GeneralEther",
144 "\002\001\000GeneralToken",
145 "\002\002\000GeneralFDDI",
147 "\003\000\000GeneralVGA",
148 "\003\001\000GeneralSVGA",
149 "\003\002\000GeneralXGA",
151 "\004\000\000GeneralVideo",
152 "\004\001\000GeneralAudio",
153 "\004\001\001CS4232Audio", /* CS 4232 Plug 'n Play Configured */
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",
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",
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 */
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 */
192 "\010\000\000GeneralPIC",
193 "\010\000\001ISA_PIC",
194 "\010\000\002EISA_PIC",
195 "\010\000\003MPIC",
196 "\010\000\004RS6K_PIC",
198 "\010\001\000GeneralDMA",
199 "\010\001\001ISA_DMA",
200 "\010\001\002EISA_DMA",
202 "\010\002\000GeneralTimer",
203 "\010\002\001ISA_Timer",
204 "\010\002\002EISA_Timer",
205 "\010\003\000GeneralRTC",
206 "\010\003\001ISA_RTC",
208 "\010\004\001StoreThruOnly",
209 "\010\004\002StoreInEnabled",
210 "\010\004\003RS6KL2Cache",
212 "\010\005\000IndirectNVRAM", /* Indirectly addressed */
213 "\010\005\001DirectNVRAM", /* Memory Mapped */
214 "\010\005\002IndirectNVRAM24", /* Indirectly addressed - 24 bit */
216 "\010\006\000GeneralPowerManagement",
217 "\010\006\001EPOWPowerManagement",
218 "\010\006\002PowerControl", // d1378
220 "\010\007\000GeneralCMOS",
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 */
231 "\010\011\000GeneralServiceProcessor",
232 "\010\012\000GeneralServiceProcessor",
233 "\010\013\000GeneralServiceProcessor",
235 "\010\014\001TransferData",
236 "\010\014\002IGMC32",
237 "\010\014\003IGMC64",
239 "\010\017\000GeneralSystemPlanar", /* 10/5/95 */
240 NULL
243 static 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 !");
252 static 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;
263 static 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;
285 #undef p
288 static 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"};
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;
355 static 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"};
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;
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');
411 printk("%s\n",tmpstr);
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]);
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);
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
465 static 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;
477 static void __init printpackets(PnP_TAG_PACKET * pkt, const char * cat)
479 if (pkt->S1_Pack.Tag== END_TAG) {
480 printk(" No packets describing %s resources.\n", cat);
481 return;
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);
495 pkt = (PnP_TAG_PACKET *)((unsigned char *) pkt + size);
496 } while (pkt->S1_Pack.Tag != END_TAG);
499 void __init print_residual_device_info(void)
501 int i;
502 PPC_DEVICE *dev;
503 #define did dev->DeviceId
505 /* make sure we have residual data first */
506 if (!have_residual_data)
507 return;
509 printk("Residual: %ld devices\n", res->ActualNumDevices);
510 for ( i = 0;
511 i < res->ActualNumDevices ;
512 i++)
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;
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),
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");
567 #if 0
568 static 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"
577 static const unsigned char *FWMan[]={
578 "IBM", "Motorola", "FirmWorks", "Bull"
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"
585 static const unsigned char *ESM[]={
586 "Port92", "PCIConfigA8", "FF001030", "????????"
588 static const unsigned char *SIOM[]={
589 "Port850", "????????", "PCIConfigA8", "????????"
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');
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]);
626 printk("\n");
631 * Spit out some info about residual data
633 void print_residual_device_info(void)
635 int i;
636 union _PnP_TAG_PACKET *pkt;
637 PPC_DEVICE *dev;
638 #define did dev->DeviceId
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++)
648 dev = &res->Devices[i];
650 * pci devices
652 if ( did.BusId & PCIDEVICE )
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)
667 if ( did.BusId & PNPISADEVICE )
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++ )
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]);
683 printk("\n");
684 continue;
687 * isa devices
689 if ( did.BusId & ISADEVICE )
691 printk("ISA Device: basetype: %d subtype: %d",
692 did.BaseType, did.SubType);
693 printk("\n");
694 continue;
697 * eisa devices
699 if ( did.BusId & EISADEVICE )
701 printk("EISA Device: basetype: %d subtype: %d",
702 did.BaseType, did.SubType);
703 printk("\n");
704 continue;
707 * proc bus devices
709 if ( did.BusId & PROCESSORDEVICE )
711 printk("ProcBus Device: basetype: %d subtype: %d",
712 did.BaseType, did.SubType);
713 printk("\n");
714 continue;
717 * pcmcia devices
719 if ( did.BusId & PCMCIADEVICE )
721 printk("PCMCIA Device: basetype: %d subtype: %d",
722 did.BaseType, did.SubType);
723 printk("\n");
724 continue;
726 printk("Unknown bus access device: busid %lx\n",
727 did.BusId);
730 #endif
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 !
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,
744 2) i8259 = residual_find_device(~0, "PNP0000", -1, -1, -1, 0)
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.
761 /* devid are easier to uncompress than to compress, so to minimize bloat
762 in this rarely used area we unencode and compare */
764 /* in residual data number is big endian in the device table and
765 little endian in the heap, so we use two parameters to avoid writing
766 two very similar functions */
768 static int __init same_DevID(unsigned short vendor,
769 unsigned short Number,
770 char * str)
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;
784 PPC_DEVICE __init *residual_find_device(unsigned long BusMask,
785 unsigned char * DevID,
786 int BaseType,
787 int SubType,
788 int Interface,
789 int n)
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
804 return NULL;
807 PPC_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)
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
826 return NULL;
829 static int __init
830 residual_scan_pcibridge(PnP_TAG_PACKET * pkt, struct pci_dev *dev)
832 int irq = -1;
834 #define data pkt->L4_Pack.L4_Data.L4_PPCPack.PPCData
835 if (dev->bus->number == data[16]) {
836 int i, size;
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;
843 if (dev->devfn != data[i + 1])
844 continue;
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;
855 break;
858 #undef data
860 return irq;
863 int __init
864 residual_pcidev_irq(struct pci_dev *dev)
866 int i = 0;
867 int irq = -1;
868 PPC_DEVICE *bridge;
870 while ((bridge = residual_find_device
871 (-1, NULL, BridgeController, PCIBridge, -1, i++))) {
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;
880 irq = residual_scan_pcibridge(pkt, dev);
881 if (irq != -1)
882 break;
886 return (irq < 0) ? 0 : irq;
889 void __init residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
891 PPC_DEVICE *dev;
892 int i = 0;
893 unsigned short irq_mask = 0x000; /* default to edge */
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;
901 if (!offset)
902 continue;
904 pkt = PnP_find_packet(res->DevicePnPHeap + offset,
905 IRQFormat, 0);
906 if (!pkt)
907 continue;
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;
915 *irq_edge_mask_lo = irq_mask & 0xff;
916 *irq_edge_mask_hi = irq_mask >> 8;
919 unsigned int __init residual_isapic_addr(void)
921 PPC_DEVICE *isapic;
922 PnP_TAG_PACKET *pkt;
923 unsigned int addr;
925 isapic = residual_find_device(~0, NULL, SystemPeripheral,
926 ProgrammableInterruptController,
927 ISA_PIC, 0);
928 if (!isapic)
929 goto unknown;
931 pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
932 isapic->AllocatedOffset, 9, 0);
933 if (!pkt)
934 goto unknown;
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;
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;
945 addr = ld_le32((unsigned int *) (p.PPCData + 4));
946 #undef p
947 return addr;
948 unknown:
949 return 0;
952 PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
953 unsigned packet_tag,
954 int n)
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;
968 return NULL; /* not found */
971 PnP_TAG_PACKET __init *PnP_find_small_vendor_packet(unsigned char *p,
972 unsigned packet_type,
973 int n)
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;
982 return NULL; /* not found */
985 PnP_TAG_PACKET __init *PnP_find_large_vendor_packet(unsigned char *p,
986 unsigned packet_type,
987 int n)
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;
996 return NULL; /* not found */
999 #ifdef CONFIG_PROC_PREPRESIDUAL
1000 static int proc_prep_residual_read(char * buf, char ** start, off_t off,
1001 int count, int *eof, void *data)
1003 int n;
1005 n = res->ResidualLength - off;
1006 if (n < 0) {
1007 *eof = 1;
1008 n = 0;
1010 else {
1011 if (n > count)
1012 n = count;
1013 else
1014 *eof = 1;
1016 memcpy(buf, (char *)res + off, n);
1017 *start = buf;
1020 return n;
1023 int __init
1024 proc_prep_residual_init(void)
1026 if (have_residual_data)
1027 create_proc_read_entry("residual", S_IRUGO, NULL,
1028 proc_prep_residual_read, NULL);
1029 return 0;
1032 __initcall(proc_prep_residual_init);
1033 #endif