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
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
19 #include <linux/string.h>
20 #include <asm/residual.h>
22 #include <asm/byteorder.h>
24 #include <linux/errno.h>
25 #include <linux/sched.h>
26 #include <linux/kernel.h>
28 #include <linux/stddef.h>
29 #include <linux/unistd.h>
30 #include <linux/ptrace.h>
31 #include <linux/slab.h>
32 #include <linux/user.h>
33 #include <linux/a.out.h>
34 #include <linux/tty.h>
35 #include <linux/major.h>
36 #include <linux/interrupt.h>
37 #include <linux/reboot.h>
38 #include <linux/init.h>
39 #include <linux/ioport.h>
40 #include <linux/pci.h>
41 #include <linux/ide.h>
43 #include <asm/sections.h>
46 #include <asm/pgtable.h>
50 unsigned char __res[sizeof(RESIDUAL)] = {0,};
51 RESIDUAL *res = (RESIDUAL *)&__res;
53 char * PnP_BASE_TYPES[] __initdata = {
56 "NetworkInterfaceController",
58 "MultimediaController",
61 "CommunicationsDevice",
67 /* Device Sub Type Codes */
69 unsigned char * PnP_SUB_TYPES[] __initdata = {
70 "\001\000SCSIController",
71 "\001\001IDEController",
72 "\001\002FloppyController",
73 "\001\003IPIController",
74 "\001\200OtherMassStorageController",
75 "\002\000EthernetController",
76 "\002\001TokenRingController",
77 "\002\002FDDIController",
78 "\002\0x80OtherNetworkController",
79 "\003\000VGAController",
80 "\003\001SVGAController",
81 "\003\002XGAController",
82 "\003\200OtherDisplayController",
83 "\004\000VideoController",
84 "\004\001AudioController",
85 "\004\200OtherMultimediaController",
88 "\005\200OtherMemoryDevice",
89 "\006\000HostProcessorBridge",
92 "\006\003MicroChannelBridge",
94 "\006\005PCMCIABridge",
96 "\006\200OtherBridgeDevice",
97 "\007\000RS232Device",
98 "\007\001ATCompatibleParallelPort",
99 "\007\200OtherCommunicationsDevice",
100 "\010\000ProgrammableInterruptController",
101 "\010\001DMAController",
102 "\010\002SystemTimer",
103 "\010\003RealTimeClock",
106 "\010\006PowerManagement",
108 "\010\010OperatorPanel",
109 "\010\011ServiceProcessorClass1",
110 "\010\012ServiceProcessorClass2",
111 "\010\013ServiceProcessorClass3",
112 "\010\014GraphicAssist",
113 "\010\017SystemPlanar",
114 "\010\200OtherSystemPeripheral",
115 "\011\000KeyboardController",
117 "\011\002MouseController",
118 "\011\003TabletController",
119 "\011\0x80OtherInputController",
120 "\012\000GeneralMemoryController",
124 /* Device Interface Type Codes */
126 unsigned char * PnP_INTERFACES[] __initdata = {
127 "\000\000\000General",
128 "\001\000\000GeneralSCSI",
129 "\001\001\000GeneralIDE",
130 "\001\001\001ATACompatible",
132 "\001\002\000GeneralFloppy",
133 "\001\002\001Compatible765",
134 "\001\002\002NS398_Floppy", /* NS Super I/O wired to use index
135 register at port 398 and data
136 register at port 399 */
137 "\001\002\003NS26E_Floppy", /* Ports 26E and 26F */
138 "\001\002\004NS15C_Floppy", /* Ports 15C and 15D */
139 "\001\002\005NS2E_Floppy", /* Ports 2E and 2F */
140 "\001\002\006CHRP_Floppy", /* CHRP Floppy in PR*P system */
142 "\001\003\000GeneralIPI",
144 "\002\000\000GeneralEther",
145 "\002\001\000GeneralToken",
146 "\002\002\000GeneralFDDI",
148 "\003\000\000GeneralVGA",
149 "\003\001\000GeneralSVGA",
150 "\003\002\000GeneralXGA",
152 "\004\000\000GeneralVideo",
153 "\004\001\000GeneralAudio",
154 "\004\001\001CS4232Audio", /* CS 4232 Plug 'n Play Configured */
156 "\005\000\000GeneralRAM",
157 /* This one is obviously wrong ! */
158 "\005\000\000PCIMemoryController", /* PCI Config Method */
159 "\005\000\001RS6KMemoryController", /* RS6K Config Method */
160 "\005\001\000GeneralFLASH",
162 "\006\000\000GeneralHostBridge",
163 "\006\001\000GeneralISABridge",
164 "\006\002\000GeneralEISABridge",
165 "\006\003\000GeneralMCABridge",
166 /* GeneralPCIBridge = 0, */
167 "\006\004\000PCIBridgeDirect",
168 "\006\004\001PCIBridgeIndirect",
169 "\006\004\002PCIBridgeRS6K",
170 "\006\005\000GeneralPCMCIABridge",
171 "\006\006\000GeneralVMEBridge",
173 "\007\000\000GeneralRS232",
175 "\007\000\002Compatible16450",
176 "\007\000\003Compatible16550",
177 "\007\000\004NS398SerPort", /* NS Super I/O wired to use index
178 register at port 398 and data
179 register at port 399 */
180 "\007\000\005NS26ESerPort", /* Ports 26E and 26F */
181 "\007\000\006NS15CSerPort", /* Ports 15C and 15D */
182 "\007\000\007NS2ESerPort", /* Ports 2E and 2F */
184 "\007\001\000GeneralParPort",
186 "\007\001\002NS398ParPort", /* NS Super I/O wired to use index
187 register at port 398 and data
188 register at port 399 */
189 "\007\001\003NS26EParPort", /* Ports 26E and 26F */
190 "\007\001\004NS15CParPort", /* Ports 15C and 15D */
191 "\007\001\005NS2EParPort", /* Ports 2E and 2F */
193 "\010\000\000GeneralPIC",
194 "\010\000\001ISA_PIC",
195 "\010\000\002EISA_PIC",
197 "\010\000\004RS6K_PIC",
199 "\010\001\000GeneralDMA",
200 "\010\001\001ISA_DMA",
201 "\010\001\002EISA_DMA",
203 "\010\002\000GeneralTimer",
204 "\010\002\001ISA_Timer",
205 "\010\002\002EISA_Timer",
206 "\010\003\000GeneralRTC",
207 "\010\003\001ISA_RTC",
209 "\010\004\001StoreThruOnly",
210 "\010\004\002StoreInEnabled",
211 "\010\004\003RS6KL2Cache",
213 "\010\005\000IndirectNVRAM", /* Indirectly addressed */
214 "\010\005\001DirectNVRAM", /* Memory Mapped */
215 "\010\005\002IndirectNVRAM24", /* Indirectly addressed - 24 bit */
217 "\010\006\000GeneralPowerManagement",
218 "\010\006\001EPOWPowerManagement",
219 "\010\006\002PowerControl", // d1378
221 "\010\007\000GeneralCMOS",
223 "\010\010\000GeneralOPPanel",
224 "\010\010\001HarddiskLight",
225 "\010\010\002CDROMLight",
226 "\010\010\003PowerLight",
227 "\010\010\004KeyLock",
228 "\010\010\005ANDisplay", /* AlphaNumeric Display */
229 "\010\010\006SystemStatusLED", /* 3 digit 7 segment LED */
230 "\010\010\007CHRP_SystemStatusLED", /* CHRP LEDs in PR*P system */
232 "\010\011\000GeneralServiceProcessor",
233 "\010\012\000GeneralServiceProcessor",
234 "\010\013\000GeneralServiceProcessor",
236 "\010\014\001TransferData",
237 "\010\014\002IGMC32",
238 "\010\014\003IGMC64",
240 "\010\017\000GeneralSystemPlanar", /* 10/5/95 */
244 static const unsigned char __init *PnP_SUB_TYPE_STR(unsigned char BaseType,
245 unsigned char SubType) {
246 unsigned char ** s=PnP_SUB_TYPES;
247 while (*s && !((*s)[0]==BaseType
248 && (*s)[1]==SubType)) s++;
250 else return("Unknown !");
253 static const unsigned char __init *PnP_INTERFACE_STR(unsigned char BaseType,
254 unsigned char SubType,
255 unsigned char Interface) {
256 unsigned char ** s=PnP_INTERFACES;
257 while (*s && !((*s)[0]==BaseType
259 && (*s)[2]==Interface)) s++;
264 static void __init printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
267 #define p pkt->S14_Pack.S14_Data.S14_PPCPack
270 /* Decompress first 3 chars */
271 c = *(unsigned short *)p.PPCData;
272 decomp[0]='A'-1+((c>>10)&0x1F);
273 decomp[1]='A'-1+((c>>5)&0x1F);
274 decomp[2]='A'-1+(c&0x1F);
276 printk(" Chip identification: %s%4.4X\n",
277 decomp, ld_le16((unsigned short *)(p.PPCData+2)));
280 printk(" Small vendor item type 0x%2.2x, data (hex): ",
282 for(i=0; i<size-2; i++) printk("%2.2x ", p.PPCData[i]);
289 static void __init printsmallpacket(PnP_TAG_PACKET * pkt, int size) {
290 static const unsigned char * intlevel[] = {"high", "low"};
291 static const unsigned char * intsense[] = {"edge", "level"};
293 switch (tag_small_item_name(pkt->S1_Pack.Tag)) {
295 printk(" PnPversion 0x%x.%x\n",
296 pkt->S1_Pack.Version[0], /* How to interpret version ? */
297 pkt->S1_Pack.Version[1]);
299 // case Logicaldevice:
301 // case CompatibleDevice:
304 #define p pkt->S4_Pack
305 printk(" IRQ Mask 0x%4.4x, %s %s sensitive\n",
306 ld_le16((unsigned short *)p.IRQMask),
307 intlevel[(size>3) ? !(p.IRQInfo&0x05) : 0],
308 intsense[(size>3) ? !(p.IRQInfo&0x03) : 0]);
312 #define p pkt->S5_Pack
313 printk(" DMA channel mask 0x%2.2x, info 0x%2.2x\n",
314 p.DMAMask, p.DMAInfo);
318 printk("Start dependent function:\n");
321 printk("End dependent function\n");
324 #define p pkt->S8_Pack
325 printk(" Variable (%d decoded bits) I/O port\n"
326 " from 0x%4.4x to 0x%4.4x, alignment %d, %d ports\n",
327 p.IOInfo&ISAAddr16bit?16:10,
328 ld_le16((unsigned short *)p.RangeMin),
329 ld_le16((unsigned short *)p.RangeMax),
334 #define p pkt->S9_Pack
335 printk(" Fixed (10 decoded bits) I/O port from %3.3x to %3.3x\n",
336 (p.Range[1]<<8)|p.Range[0],
337 ((p.Range[1]<<8)|p.Range[0])+p.IONum-1);
343 printk(" Undefined packet type %d!\n",
344 tag_small_item_name(pkt->S1_Pack.Tag));
346 case SmallVendorItem:
347 printsmallvendor(pkt,size);
350 printk(" Type 0x2.2x%d, size=%d\n",
351 pkt->S1_Pack.Tag, size);
356 static void __init printlargevendor(PnP_TAG_PACKET * pkt, int size) {
357 static const unsigned char * addrtype[] = {"I/O", "Memory", "System"};
358 static const unsigned char * inttype[] = {"8259", "MPIC", "RS6k BUID %d"};
359 static const unsigned char * convtype[] = {"Bus Memory", "Bus I/O", "DMA"};
360 static const unsigned char * transtype[] = {"direct", "mapped", "direct-store segment"};
361 static const unsigned char * L2type[] = {"WriteThru", "CopyBack"};
362 static const unsigned char * L2assoc[] = {"DirectMapped", "2-way set"};
366 #define p pkt->L4_Pack.L4_Data.L4_PPCPack
369 printk(" %d K %s %s L2 cache, %d/%d bytes line/sector size\n",
370 ld_le32((unsigned int *)p.PPCData),
371 L2type[p.PPCData[10]-1],
372 L2assoc[p.PPCData[4]-1],
373 ld_le16((unsigned short *)p.PPCData+3),
374 ld_le16((unsigned short *)p.PPCData+4));
377 printk(" PCI Bridge parameters\n"
378 " ConfigBaseAddress %0x\n"
379 " ConfigBaseData %0x\n"
381 ld_le32((unsigned int *)p.PPCData),
382 ld_le32((unsigned int *)(p.PPCData+8)),
384 for(i=20; i<size-4; i+=12) {
386 if(p.PPCData[i]) printk(" PCI Slot %d", p.PPCData[i]);
387 else printk (" Integrated PCI device");
388 for(j=0, first=1, t=tmpstr; j<4; j++) {
389 int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
391 if(first) first=0; else *t++='/';
396 printk(" DevFunc 0x%x interrupt line(s) %s routed to",
397 p.PPCData[i+1],tmpstr);
399 inttype[p.PPCData[i+2]-1],
401 printk(" %s line(s) ",
403 for(j=0, first=1, t=tmpstr; j<4; j++) {
404 int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
406 if(first) first=0; else *t++='/';
407 t+=sprintf(t,"%d(%c)",
409 line&0x8000?'E':'L');
412 printk("%s\n",tmpstr);
416 printk(" Bridge address translation, %s decoding:\n"
417 " Processor Bus Size Conversion Translation\n"
418 " 0x%8.8x 0x%8.8x 0x%8.8x %s %s\n",
419 p.PPCData[0]&1 ? "positive" : "subtractive",
420 ld_le32((unsigned int *)p.PPCData+1),
421 ld_le32((unsigned int *)p.PPCData+3),
422 ld_le32((unsigned int *)p.PPCData+5),
423 convtype[p.PPCData[2]-1],
424 transtype[p.PPCData[1]-1]);
427 printk(" Bus speed %d Hz, %d slot(s)\n",
428 ld_le32((unsigned int *)p.PPCData),
432 printk(" SCSI buses: %d, id(s):", p.PPCData[0]);
433 for(i=1; i<=p.PPCData[0]; i++)
434 printk(" %d%c", p.PPCData[i], i==p.PPCData[0] ? '\n' : ',');
437 printk(" %s address (%d bits), at 0x%x size 0x%x bytes\n",
438 addrtype[p.PPCData[0]-1],
440 ld_le32((unsigned int *)(p.PPCData+4)),
441 ld_le32((unsigned int *)(p.PPCData+12)));
445 inttype[p.PPCData[0]-1],
448 printk(" ISA interrupts routed to %s\n"
451 for(i=0; i<16; i++) {
452 int line=ld_le16((unsigned short *)p.PPCData+i+1);
453 if (line!=0xffff) printk(" %d(IRQ%d)", line, i);
458 printk(" Large vendor item type 0x%2.2x\n Data (hex):",
460 for(i=0; i<size-4; i++) printk(" %2.2x", p.PPCData[i]);
466 static void __init printlargepacket(PnP_TAG_PACKET * pkt, int size) {
467 switch (tag_large_item_name(pkt->S1_Pack.Tag)) {
468 case LargeVendorItem:
469 printlargevendor(pkt, size);
472 printk(" Type 0x2.2x%d, size=%d\n",
473 pkt->S1_Pack.Tag, size);
478 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);
484 printk( " Packets describing %s resources:\n",cat);
487 if (tag_type(pkt->S1_Pack.Tag)) {
489 pkt->L1_Pack.Count0 +
490 pkt->L1_Pack.Count1*256;
491 printlargepacket(pkt, size);
493 size=tag_small_count(pkt->S1_Pack.Tag)+1;
494 printsmallpacket(pkt, size);
496 pkt = (PnP_TAG_PACKET *)((unsigned char *) pkt + size);
497 } while (pkt->S1_Pack.Tag != END_TAG);
500 void __init print_residual_device_info(void)
504 #define did dev->DeviceId
506 /* make sure we have residual data first */
507 if (!have_residual_data)
510 printk("Residual: %ld devices\n", res->ActualNumDevices);
512 i < res->ActualNumDevices ;
515 char decomp[4], sn[20];
517 dev = &res->Devices[i];
518 s = PnP_INTERFACE_STR(did.BaseType, did.SubType,
521 sprintf(sn, "interface %d", did.Interface);
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);
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),
552 if ( dev->AllocatedOffset )
553 printpackets( (union _PnP_TAG_PACKET *)
554 &res->DevicePnPHeap[dev->AllocatedOffset],
556 if ( dev->PossibleOffset )
557 printpackets( (union _PnP_TAG_PACKET *)
558 &res->DevicePnPHeap[dev->PossibleOffset],
560 if ( dev->CompatibleOffset )
561 printpackets( (union _PnP_TAG_PACKET *)
562 &res->DevicePnPHeap[dev->CompatibleOffset],
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"
578 static const unsigned char *FWMan[]={
579 "IBM", "Motorola", "FirmWorks", "Bull"
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"
586 static const unsigned char *ESM[]={
587 "Port92", "PCIConfigA8", "FF001030", "????????"
589 static const unsigned char *SIOM[]={
590 "Port850", "????????", "PCIConfigA8", "????????"
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');
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--) {
624 printk("%s", Usage[j]);
632 * Spit out some info about residual data
634 void print_residual_device_info(void)
637 union _PnP_TAG_PACKET *pkt;
639 #define did dev->DeviceId
641 /* make sure we have residual data first */
642 if (!have_residual_data)
644 printk("Residual: %ld devices\n", res->ActualNumDevices);
646 i < res->ActualNumDevices ;
649 dev = &res->Devices[i];
653 if ( did.BusId & PCIDEVICE )
655 printk("PCI Device:");
657 if ( !strncmp( "Unknown", pci_strvendor(did.DevId>>16), 7) )
658 printk(" id %08lx types %d/%d", did.DevId,
659 did.BaseType, did.SubType);
663 pci_strvendor(did.DevId>>16),
664 pci_strdev(did.DevId>>16,
668 if ( did.BusId & PNPISADEVICE )
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;
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]);
690 if ( did.BusId & ISADEVICE )
692 printk("ISA Device: basetype: %d subtype: %d",
693 did.BaseType, did.SubType);
700 if ( did.BusId & EISADEVICE )
702 printk("EISA Device: basetype: %d subtype: %d",
703 did.BaseType, did.SubType);
710 if ( did.BusId & PROCESSORDEVICE )
712 printk("ProcBus Device: basetype: %d subtype: %d",
713 did.BaseType, did.SubType);
720 if ( did.BusId & PCMCIADEVICE )
722 printk("PCMCIA Device: basetype: %d subtype: %d",
723 did.BaseType, did.SubType);
727 printk("Unknown bus access device: busid %lx\n",
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 !
738 - search for the Interrupt controller (8259 type), 2 methods:
739 1) i8259 = residual_find_device(~0,
742 ProgrammableInterruptController,
745 2) i8259 = residual_find_device(~0, "PNP0000", -1, -1, -1, 0)
747 - search for the first two serial devices, whatever their type)
748 iserial1 = residual_find_device(~0,NULL,
749 CommunicationsDevice,
752 iserial2 = residual_find_device(~0,NULL,
753 CommunicationsDevice,
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.
762 /* devid are easier to uncompress than to compress, so to minimize bloat
763 in this rarely used area we unencode and compare */
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 */
769 static int __init same_DevID(unsigned short vendor,
770 unsigned short Number,
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;
785 PPC_DEVICE __init *residual_find_device(unsigned long BusMask,
786 unsigned char * DevID,
793 if (!have_residual_data) 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;
808 PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask,
809 unsigned short DevID,
816 if (!have_residual_data) 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;
831 residual_scan_pcibridge(PnP_TAG_PACKET * pkt, struct pci_dev *dev)
835 #define data pkt->L4_Pack.L4_Data.L4_PPCPack.PPCData
836 if (dev->bus->number == data[16]) {
839 size = 3 + ld_le16((u_short *) (&pkt->L4_Pack.Count0));
840 for (i = 20; i < size - 4; i += 12) {
844 if (dev->devfn != data[i + 1])
847 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
849 line_irq = ld_le16((unsigned short *)
850 (&data[i + 4 + 2 * (pin - 1)]));
851 irq = (line_irq == 0xffff) ? 0
865 residual_pcidev_irq(struct pci_dev *dev)
871 while ((bridge = residual_find_device
872 (-1, NULL, BridgeController, PCIBridge, -1, i++))) {
875 if (bridge->AllocatedOffset) {
876 pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
877 bridge->AllocatedOffset, 3, 0);
881 irq = residual_scan_pcibridge(pkt, dev);
887 return (irq < 0) ? 0 : irq;
890 void __init residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
894 unsigned short irq_mask = 0x000; /* default to edge */
896 while ((dev = residual_find_device(-1, NULL, -1, -1, -1, i++))) {
900 int offset = dev->AllocatedOffset;
905 pkt = PnP_find_packet(res->DevicePnPHeap + offset,
910 size = tag_small_count(pkt->S1_Pack.Tag) + 1;
911 mask = ld_le16((unsigned short *)pkt->S4_Pack.IRQMask);
912 if (size > 3 && (pkt->S4_Pack.IRQInfo & 0x0c))
916 *irq_edge_mask_lo = irq_mask & 0xff;
917 *irq_edge_mask_hi = irq_mask >> 8;
920 unsigned int __init residual_isapic_addr(void)
926 isapic = residual_find_device(~0, NULL, SystemPeripheral,
927 ProgrammableInterruptController,
932 pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
933 isapic->AllocatedOffset, 9, 0);
937 #define p pkt->L4_Pack.L4_Data.L4_PPCPack
938 /* Must be 32-bit system address */
939 if (!((p.PPCData[0] == 3) && (p.PPCData[1] == 32)))
942 /* It doesn't seem to work where length != 1 (what can I say? :-/ ) */
943 if (ld_le32((unsigned int *)(p.PPCData + 12)) != 1)
946 addr = ld_le32((unsigned int *) (p.PPCData + 4));
953 PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
957 unsigned mask, masked_tag, size;
959 if (tag_type(packet_tag)) mask=0xff; else mask=0xF8;
960 masked_tag = packet_tag&mask;
961 for(; *p != END_TAG; p+=size) {
962 if ((*p & mask) == masked_tag && !(n--))
963 return (PnP_TAG_PACKET *) p;
965 size=ld_le16((unsigned short *)(p+1))+3;
967 size=tag_small_count(*p)+1;
969 return NULL; /* not found */
972 PnP_TAG_PACKET __init *PnP_find_small_vendor_packet(unsigned char *p,
973 unsigned packet_type,
978 p = (unsigned char *) PnP_find_packet(p, 0x70, next);
979 if (p && p[1]==packet_type && !(n--))
980 return (PnP_TAG_PACKET *) p;
983 return NULL; /* not found */
986 PnP_TAG_PACKET __init *PnP_find_large_vendor_packet(unsigned char *p,
987 unsigned packet_type,
992 p = (unsigned char *) PnP_find_packet(p, 0x84, next);
993 if (p && p[3]==packet_type && !(n--))
994 return (PnP_TAG_PACKET *) p;
997 return NULL; /* not found */
1000 #ifdef CONFIG_PROC_PREPRESIDUAL
1001 static int proc_prep_residual_read(char * buf, char ** start, off_t off,
1002 int count, int *eof, void *data)
1006 n = res->ResidualLength - off;
1017 memcpy(buf, (char *)res + off, n);
1025 proc_prep_residual_init(void)
1027 if (have_residual_data)
1028 create_proc_read_entry("residual", S_IRUGO, NULL,
1029 proc_prep_residual_read, NULL);
1033 __initcall(proc_prep_residual_init);