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>
42 #include <asm/sections.h>
45 #include <asm/pgtable.h>
49 unsigned char __res[sizeof(RESIDUAL)] = {0,};
50 RESIDUAL *res = (RESIDUAL *)&__res;
52 char * PnP_BASE_TYPES[] __initdata = {
55 "NetworkInterfaceController",
57 "MultimediaController",
60 "CommunicationsDevice",
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",
87 "\005\200OtherMemoryDevice",
88 "\006\000HostProcessorBridge",
91 "\006\003MicroChannelBridge",
93 "\006\005PCMCIABridge",
95 "\006\200OtherBridgeDevice",
96 "\007\000RS232Device",
97 "\007\001ATCompatibleParallelPort",
98 "\007\200OtherCommunicationsDevice",
99 "\010\000ProgrammableInterruptController",
100 "\010\001DMAController",
101 "\010\002SystemTimer",
102 "\010\003RealTimeClock",
105 "\010\006PowerManagement",
107 "\010\010OperatorPanel",
108 "\010\011ServiceProcessorClass1",
109 "\010\012ServiceProcessorClass2",
110 "\010\013ServiceProcessorClass3",
111 "\010\014GraphicAssist",
112 "\010\017SystemPlanar",
113 "\010\200OtherSystemPeripheral",
114 "\011\000KeyboardController",
116 "\011\002MouseController",
117 "\011\003TabletController",
118 "\011\0x80OtherInputController",
119 "\012\000GeneralMemoryController",
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",
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",
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",
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 */
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++;
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
258 && (*s)[2]==Interface)) s++;
263 static void __init printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
266 #define p pkt->S14_Pack.S14_Data.S14_PPCPack
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);
275 printk(" Chip identification: %s%4.4X\n",
276 decomp, ld_le16((unsigned short *)(p.PPCData+2)));
279 printk(" Small vendor item type 0x%2.2x, data (hex): ",
281 for(i=0; i<size-2; i++) printk("%2.2x ", p.PPCData[i]);
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)) {
294 printk(" PnPversion 0x%x.%x\n",
295 pkt->S1_Pack.Version[0], /* How to interpret version ? */
296 pkt->S1_Pack.Version[1]);
298 // case Logicaldevice:
300 // case CompatibleDevice:
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]);
311 #define p pkt->S5_Pack
312 printk(" DMA channel mask 0x%2.2x, info 0x%2.2x\n",
313 p.DMAMask, p.DMAInfo);
317 printk("Start dependent function:\n");
320 printk("End dependent function\n");
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),
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);
342 printk(" Undefined packet type %d!\n",
343 tag_small_item_name(pkt->S1_Pack.Tag));
345 case SmallVendorItem:
346 printsmallvendor(pkt,size);
349 printk(" Type 0x2.2x%d, size=%d\n",
350 pkt->S1_Pack.Tag, size);
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"};
365 #define p pkt->L4_Pack.L4_Data.L4_PPCPack
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));
376 printk(" PCI Bridge parameters\n"
377 " ConfigBaseAddress %0x\n"
378 " ConfigBaseData %0x\n"
380 ld_le32((unsigned int *)p.PPCData),
381 ld_le32((unsigned int *)(p.PPCData+8)),
383 for(i=20; i<size-4; i+=12) {
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);
390 if(first) first=0; else *t++='/';
395 printk(" DevFunc 0x%x interrupt line(s) %s routed to",
396 p.PPCData[i+1],tmpstr);
398 inttype[p.PPCData[i+2]-1],
400 printk(" %s line(s) ",
402 for(j=0, first=1, t=tmpstr; j<4; j++) {
403 int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
405 if(first) first=0; else *t++='/';
406 t+=sprintf(t,"%d(%c)",
408 line&0x8000?'E':'L');
411 printk("%s\n",tmpstr);
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]);
426 printk(" Bus speed %d Hz, %d slot(s)\n",
427 ld_le32((unsigned int *)p.PPCData),
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' : ',');
436 printk(" %s address (%d bits), at 0x%x size 0x%x bytes\n",
437 addrtype[p.PPCData[0]-1],
439 ld_le32((unsigned int *)(p.PPCData+4)),
440 ld_le32((unsigned int *)(p.PPCData+12)));
444 inttype[p.PPCData[0]-1],
447 printk(" ISA interrupts routed to %s\n"
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);
457 printk(" Large vendor item type 0x%2.2x\n Data (hex):",
459 for(i=0; i<size-4; i++) printk(" %2.2x", p.PPCData[i]);
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);
471 printk(" Type 0x2.2x%d, size=%d\n",
472 pkt->S1_Pack.Tag, size);
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);
483 printk( " Packets describing %s resources:\n",cat);
486 if (tag_type(pkt->S1_Pack.Tag)) {
488 pkt->L1_Pack.Count0 +
489 pkt->L1_Pack.Count1*256;
490 printlargepacket(pkt, size);
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)
503 #define did dev->DeviceId
505 /* make sure we have residual data first */
506 if (!have_residual_data)
509 printk("Residual: %ld devices\n", res->ActualNumDevices);
511 i < res->ActualNumDevices ;
514 char decomp[4], sn[20];
516 dev = &res->Devices[i];
517 s = PnP_INTERFACE_STR(did.BaseType, did.SubType,
520 sprintf(sn, "interface %d", did.Interface);
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);
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],
555 if ( dev->PossibleOffset )
556 printpackets( (union _PnP_TAG_PACKET *)
557 &res->DevicePnPHeap[dev->PossibleOffset],
559 if ( dev->CompatibleOffset )
560 printpackets( (union _PnP_TAG_PACKET *)
561 &res->DevicePnPHeap[dev->CompatibleOffset],
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--) {
623 printk("%s", Usage[j]);
631 * Spit out some info about residual data
633 void print_residual_device_info(void)
636 union _PnP_TAG_PACKET *pkt;
638 #define did dev->DeviceId
640 /* make sure we have residual data first */
641 if (!have_residual_data)
643 printk("Residual: %ld devices\n", res->ActualNumDevices);
645 i < res->ActualNumDevices ;
648 dev = &res->Devices[i];
652 if ( did.BusId & PCIDEVICE )
654 printk("PCI Device:");
656 if ( !strncmp( "Unknown", pci_strvendor(did.DevId>>16), 7) )
657 printk(" id %08lx types %d/%d", did.DevId,
658 did.BaseType, did.SubType);
662 pci_strvendor(did.DevId>>16),
663 pci_strdev(did.DevId>>16,
667 if ( did.BusId & PNPISADEVICE )
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;
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]);
689 if ( did.BusId & ISADEVICE )
691 printk("ISA Device: basetype: %d subtype: %d",
692 did.BaseType, did.SubType);
699 if ( did.BusId & EISADEVICE )
701 printk("EISA Device: basetype: %d subtype: %d",
702 did.BaseType, did.SubType);
709 if ( did.BusId & PROCESSORDEVICE )
711 printk("ProcBus Device: basetype: %d subtype: %d",
712 did.BaseType, did.SubType);
719 if ( did.BusId & PCMCIADEVICE )
721 printk("PCMCIA Device: basetype: %d subtype: %d",
722 did.BaseType, did.SubType);
726 printk("Unknown bus access device: busid %lx\n",
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 !
737 - search for the Interrupt controller (8259 type), 2 methods:
738 1) i8259 = residual_find_device(~0,
741 ProgrammableInterruptController,
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,
751 iserial2 = residual_find_device(~0,NULL,
752 CommunicationsDevice,
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,
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;
784 PPC_DEVICE __init *residual_find_device(unsigned long BusMask,
785 unsigned char * DevID,
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;
807 PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask,
808 unsigned short DevID,
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;
830 residual_scan_pcibridge(PnP_TAG_PACKET * pkt, struct pci_dev *dev)
834 #define data pkt->L4_Pack.L4_Data.L4_PPCPack.PPCData
835 if (dev->bus->number == data[16]) {
838 size = 3 + ld_le16((u_short *) (&pkt->L4_Pack.Count0));
839 for (i = 20; i < size - 4; i += 12) {
843 if (dev->devfn != data[i + 1])
846 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
848 line_irq = ld_le16((unsigned short *)
849 (&data[i + 4 + 2 * (pin - 1)]));
850 irq = (line_irq == 0xffff) ? 0
864 residual_pcidev_irq(struct pci_dev *dev)
870 while ((bridge = residual_find_device
871 (-1, NULL, BridgeController, PCIBridge, -1, i++))) {
874 if (bridge->AllocatedOffset) {
875 pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
876 bridge->AllocatedOffset, 3, 0);
880 irq = residual_scan_pcibridge(pkt, dev);
886 return (irq < 0) ? 0 : irq;
889 void __init residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
893 unsigned short irq_mask = 0x000; /* default to edge */
895 while ((dev = residual_find_device(-1, NULL, -1, -1, -1, i++))) {
899 int offset = dev->AllocatedOffset;
904 pkt = PnP_find_packet(res->DevicePnPHeap + offset,
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))
915 *irq_edge_mask_lo = irq_mask & 0xff;
916 *irq_edge_mask_hi = irq_mask >> 8;
919 unsigned int __init residual_isapic_addr(void)
925 isapic = residual_find_device(~0, NULL, SystemPeripheral,
926 ProgrammableInterruptController,
931 pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
932 isapic->AllocatedOffset, 9, 0);
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)))
941 /* It doesn't seem to work where length != 1 (what can I say? :-/ ) */
942 if (ld_le32((unsigned int *)(p.PPCData + 12)) != 1)
945 addr = ld_le32((unsigned int *) (p.PPCData + 4));
952 PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
956 unsigned mask, masked_tag, size;
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;
964 size=ld_le16((unsigned short *)(p+1))+3;
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,
977 p = (unsigned char *) PnP_find_packet(p, 0x70, next);
978 if (p && p[1]==packet_type && !(n--))
979 return (PnP_TAG_PACKET *) p;
982 return NULL; /* not found */
985 PnP_TAG_PACKET __init *PnP_find_large_vendor_packet(unsigned char *p,
986 unsigned packet_type,
991 p = (unsigned char *) PnP_find_packet(p, 0x84, next);
992 if (p && p[3]==packet_type && !(n--))
993 return (PnP_TAG_PACKET *) p;
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)
1005 n = res->ResidualLength - off;
1016 memcpy(buf, (char *)res + off, n);
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);
1032 __initcall(proc_prep_residual_init);