Back to index

lshw  02.16
parisc.cc
Go to the documentation of this file.
00001 /*
00002  * parisc.cc
00003  *
00004  * This module parses the PA-RISC device tree (published under /sys
00005  * by the kernel).
00006  *
00007  *
00008  *
00009  *
00010  */
00011 
00012 #include "version.h"
00013 #include "device-tree.h"
00014 #include "osutils.h"
00015 #include "heuristics.h"
00016 #include <sys/types.h>
00017 #include <sys/stat.h>
00018 #include <fcntl.h>
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <unistd.h>
00023 #include <dirent.h>
00024 
00025 __ID("@(#) $Id: parisc.cc 2433 2012-01-10 22:01:30Z lyonel $");
00026 
00027 #define DEVICESPARISC "/sys/devices/parisc"
00028 
00029 #define TP_NPROC  0x00
00030 #define TP_MEMORY 0x01
00031 #define TP_B_DMA  0x02
00032 #define TP_OBSOLETE 0x03
00033 #define TP_A_DMA  0x04
00034 #define TP_A_DIRECT 0x05
00035 #define TP_OTHER  0x06
00036 #define TP_BCPORT 0x07
00037 #define TP_CIO    0x08
00038 #define TP_CONSOLE  0x09
00039 #define TP_FIO    0x0a
00040 #define TP_BA   0x0b
00041 #define TP_IOA    0x0c
00042 #define TP_BRIDGE 0x0d
00043 #define TP_FABRIC 0x0e
00044 #define TP_MC   0x0f
00045 #define TP_FAULTY 0x1f
00046 
00047 struct parisc_device
00048 {
00049   long sversion;
00050   const char * id;
00051   hw::hwClass device_class;
00052   const char * description;
00053 };
00054 
00055 static struct parisc_device parisc_device_list[] =
00056 {
00057   {0x00004, "cpu", hw::processor, "Processor"},
00058   {0x0000d, "mux", hw::communication, "MUX"},
00059   {0x0000e, "serial", hw::communication, "RS-232 Serial Interface"},
00060   {0x0000f, "display", hw::display, "Graphics Display"},
00061   {0x00014, "input", hw::input, "HIL"},
00062   {0x00015, "display", hw::display, "Graphics Display"},
00063   {0x0003a, "printer", hw::printer, "Centronics Parallel interface"},
00064   {0x000a8, "input", hw::input, "Keyboard"},
00065   {0x00039, "scsi", hw::storage, "Core SCSI controller"},
00066   {0x0003b, "scsi", hw::storage, "FW-SCSI controller"},
00067   {0x0005e, "network", hw::network, "Token Ring Interface"},
00068   {0x00089, "scsi", hw::storage, "FW-SCSI controller"},
00069   {0x00091, "fc", hw::storage, "Fibre Channel controller"},
00070   {0x0009a, "network", hw::network, "ATM Interface"},
00071   {0x000a7, "fc", hw::storage, "Fibre Channel controller"},
00072   {0x00070, "core", hw::bus, "Core Bus"},
00073   {0x00076, "eisa", hw::bus, "EISA Bus"},
00074   {0x00078, "vme", hw::bus, "VME Bus"},
00075   {0x00081, "core", hw::bus, "Core Bus"},
00076   {0x0008e, "wax", hw::bus, "Wax Bus"},
00077   {0x00090, "eisa", hw::bus, "Wax EISA Bus"},
00078   {0x00093, "bus", hw::bus, "TIMI Bus"},
00079   {0x0000c, "bridge", hw::bridge, "Bus Converter"},
00080   {0x0000a, "pci", hw::bridge, "PCI Bridge"},
00081   {0x000a5, "pci", hw::bridge, "PCI Bridge"},
00082   {0x00052, "lanconsole", hw::network, "LAN/Console"},
00083   {0x00060, "lanconsole", hw::network, "LAN/Console"},
00084   {0x00071, "scsi", hw::storage, "Core SCSI controller"},
00085   {0x00072, "network", hw::network, "Core Ethernet Interface"},
00086   {0x00072, "input", hw::input, "Core HIL"},
00087   {0x00074, "printer", hw::printer, "Core Centronics Parallel interface"},
00088   {0x00075, "serial", hw::communication, "Core RS-232 Serial Interface"},
00089   {0x00077, "display", hw::display, "Graphics Display"},
00090   {0x0007a, "audio", hw::multimedia, "Audio"},
00091   {0x0007b, "audio", hw::multimedia, "Audio"},
00092   {0x0007c, "scsi", hw::storage, "FW-SCSI controller"},
00093   {0x0007d, "network", hw::network, "FDDI Interface"},
00094   {0x0007e, "audio", hw::multimedia, "Audio"},
00095   {0x0007f, "audio", hw::multimedia, "Audio"},
00096   {0x00082, "scsi", hw::storage, "SCSI controller"},
00097   {0x00083, "floppy", hw::storage, "Floppy"},
00098   {0x00084, "input", hw::input, "PS/2 port"},
00099   {0x00085, "display", hw::display, "Graphics Display"},
00100   {0x00086, "network", hw::network, "Token Ring Interface"},
00101   {0x00087, "communication", hw::communication, "ISDN"},
00102   {0x00088, "network", hw::network, "VME Networking Interface"},
00103   {0x0008a, "network", hw::network, "Core Ethernet Interface"},
00104   {0x0008c, "serial", hw::communication, "RS-232 Serial Interface"},
00105   {0x0008d, "unknown", hw::communication, "RJ-16"},
00106   {0x0008f, "firmware", hw::memory, "Boot ROM"},
00107   {0x00096, "input", hw::input, "PS/2 port"},
00108   {0x00097, "network", hw::network, "100VG LAN Interface"},
00109   {0x000a2, "network", hw::network, "10/100BT LAN Interface"},
00110   {0x000a3, "scsi", hw::storage, "Ultra2 SCSI controller"},
00111   {0x00000, "generic", hw::generic, NULL},
00112 };
00113 
00114 enum cpu_type
00115 {
00116   pcx     = 0,                                    /* pa7000          pa 1.0  */
00117   pcxs    = 1,                                    /* pa7000          pa 1.1a */
00118   pcxt    = 2,                                    /* pa7100          pa 1.1b */
00119   pcxt_   = 3,                                    /* pa7200  (t')    pa 1.1c */
00120   pcxl    = 4,                                    /* pa7100lc        pa 1.1d */
00121   pcxl2   = 5,                                    /* pa7300lc        pa 1.1e */
00122   pcxu    = 6,                                    /* pa8000          pa 2.0  */
00123   pcxu_   = 7,                                    /* pa8200  (u+)    pa 2.0  */
00124   pcxw    = 8,                                    /* pa8500          pa 2.0  */
00125   pcxw_   = 9,                                    /* pa8600  (w+)    pa 2.0  */
00126   pcxw2   = 10,                                   /* pa8700         pa 2.0  */
00127   mako    = 11                                    /* pa8800         pa 2.0  */
00128 };
00129 
00130 static struct hp_cpu_type_mask
00131 {
00132   unsigned short model;
00133   unsigned short mask;
00134   enum cpu_type cpu;
00135 }
00136 
00137 
00138 hp_cpu_type_mask_list[] =
00139 {
00140 
00141   {                                               /* 0x0000 - 0x000f */
00142     0x0000, 0x0ff0, pcx
00143   },
00144   {                                               /* 0x0040 - 0x004f */
00145     0x0048, 0x0ff0, pcxl
00146   },
00147   {                                               /* 0x0080 - 0x008f */
00148     0x0080, 0x0ff0, pcx
00149   },
00150   {                                               /* 0x0100 - 0x010f */
00151     0x0100, 0x0ff0, pcx
00152   },
00153   {                                               /* 0x0182 - 0x0183 */
00154     0x0182, 0x0ffe, pcx
00155   },
00156   {                                               /* 0x0182 - 0x0183 */
00157     0x0182, 0x0ffe, pcxt
00158   },
00159   {                                               /* 0x0184 - 0x0184 */
00160     0x0184, 0x0fff, pcxu
00161   },
00162   {                                               /* 0x0200 - 0x0201 */
00163     0x0200, 0x0ffe, pcxs
00164   },
00165   {                                               /* 0x0202 - 0x0202 */
00166     0x0202, 0x0fff, pcxs
00167   },
00168   {                                               /* 0x0203 - 0x0203 */
00169     0x0203, 0x0fff, pcxt
00170   },
00171   {                                               /* 0x0204 - 0x0207 */
00172     0x0204, 0x0ffc, pcxt
00173   },
00174   {                                               /* 0x0280 - 0x0283 */
00175     0x0280, 0x0ffc, pcxs
00176   },
00177   {                                               /* 0x0284 - 0x0287 */
00178     0x0284, 0x0ffc, pcxt
00179   },
00180   {                                               /* 0x0288 - 0x0288 */
00181     0x0288, 0x0fff, pcxt
00182   },
00183   {                                               /* 0x0300 - 0x0303 */
00184     0x0300, 0x0ffc, pcxs
00185   },
00186   {                                               /* 0x0310 - 0x031f */
00187     0x0310, 0x0ff0, pcxt
00188   },
00189   {                                               /* 0x0320 - 0x032f */
00190     0x0320, 0x0ff0, pcxt
00191   },
00192   {                                               /* 0x0400 - 0x040f */
00193     0x0400, 0x0ff0, pcxt
00194   },
00195   {                                               /* 0x0480 - 0x048f */
00196     0x0480, 0x0ff0, pcxl
00197   },
00198   {                                               /* 0x0500 - 0x050f */
00199     0x0500, 0x0ff0, pcxl2
00200   },
00201   {                                               /* 0x0510 - 0x051f */
00202     0x0510, 0x0ff0, pcxl2
00203   },
00204   {                                               /* 0x0580 - 0x0587 */
00205     0x0580, 0x0ff8, pcxt_
00206   },
00207   {                                               /* 0x0588 - 0x058b */
00208     0x0588, 0x0ffc, pcxt_
00209   },
00210   {                                               /* 0x058c - 0x058d */
00211     0x058c, 0x0ffe, pcxt_
00212   },
00213   {                                               /* 0x058e - 0x058e */
00214     0x058e, 0x0fff, pcxt_
00215   },
00216   {                                               /* 0x058f - 0x058f */
00217     0x058f, 0x0fff, pcxu
00218   },
00219   {                                               /* 0x0590 - 0x0591 */
00220     0x0590, 0x0ffe, pcxu
00221   },
00222   {                                               /* 0x0592 - 0x0592 */
00223     0x0592, 0x0fff, pcxt_
00224   },
00225   {                                               /* 0x0593 - 0x0593 */
00226     0x0593, 0x0fff, pcxu
00227   },
00228   {                                               /* 0x0594 - 0x0597 */
00229     0x0594, 0x0ffc, pcxu
00230   },
00231   {                                               /* 0x0598 - 0x0599 */
00232     0x0598, 0x0ffe, pcxu_
00233   },
00234   {                                               /* 0x059a - 0x059b */
00235     0x059a, 0x0ffe, pcxu
00236   },
00237   {                                               /* 0x059c - 0x059c */
00238     0x059c, 0x0fff, pcxu
00239   },
00240   {                                               /* 0x059d - 0x059d */
00241     0x059d, 0x0fff, pcxu_
00242   },
00243   {                                               /* 0x059e - 0x059e */
00244     0x059e, 0x0fff, pcxt_
00245   },
00246   {                                               /* 0x059f - 0x059f */
00247     0x059f, 0x0fff, pcxu
00248   },
00249   {                                               /* 0x05a0 - 0x05a1 */
00250     0x05a0, 0x0ffe, pcxt_
00251   },
00252   {                                               /* 0x05a2 - 0x05a3 */
00253     0x05a2, 0x0ffe, pcxu
00254   },
00255   {                                               /* 0x05a4 - 0x05a7 */
00256     0x05a4, 0x0ffc, pcxu
00257   },
00258   {                                               /* 0x05a8 - 0x05ab */
00259     0x05a8, 0x0ffc, pcxu
00260   },
00261   {                                               /* 0x05ad - 0x05ad */
00262     0x05ad, 0x0fff, pcxu_
00263   },
00264   {                                               /* 0x05ae - 0x05af */
00265     0x05ae, 0x0ffe, pcxu_
00266   },
00267   {                                               /* 0x05b0 - 0x05b1 */
00268     0x05b0, 0x0ffe, pcxu_
00269   },
00270   {                                               /* 0x05b2 - 0x05b2 */
00271     0x05b2, 0x0fff, pcxu_
00272   },
00273   {                                               /* 0x05b3 - 0x05b3 */
00274     0x05b3, 0x0fff, pcxu
00275   },
00276   {                                               /* 0x05b4 - 0x05b4 */
00277     0x05b4, 0x0fff, pcxw
00278   },
00279   {                                               /* 0x05b5 - 0x05b5 */
00280     0x05b5, 0x0fff, pcxu_
00281   },
00282   {                                               /* 0x05b6 - 0x05b7 */
00283     0x05b6, 0x0ffe, pcxu_
00284   },
00285   {                                               /* 0x05b8 - 0x05b9 */
00286     0x05b8, 0x0ffe, pcxu_
00287   },
00288   {                                               /* 0x05ba - 0x05ba */
00289     0x05ba, 0x0fff, pcxu_
00290   },
00291   {                                               /* 0x05bb - 0x05bb */
00292     0x05bb, 0x0fff, pcxw
00293   },
00294   {                                               /* 0x05bc - 0x05bf */
00295     0x05bc, 0x0ffc, pcxw
00296   },
00297   {                                               /* 0x05c0 - 0x05c3 */
00298     0x05c0, 0x0ffc, pcxw
00299   },
00300   {                                               /* 0x05c4 - 0x05c5 */
00301     0x05c4, 0x0ffe, pcxw
00302   },
00303   {                                               /* 0x05c6 - 0x05c6 */
00304     0x05c6, 0x0fff, pcxw
00305   },
00306   {                                               /* 0x05c7 - 0x05c7 */
00307     0x05c7, 0x0fff, pcxw_
00308   },
00309   {                                               /* 0x05c8 - 0x05cb */
00310     0x05c8, 0x0ffc, pcxw
00311   },
00312   {                                               /* 0x05cc - 0x05cd */
00313     0x05cc, 0x0ffe, pcxw
00314   },
00315   {                                               /* 0x05ce - 0x05cf */
00316     0x05ce, 0x0ffe, pcxw_
00317   },
00318   {                                               /* 0x05d0 - 0x05d3 */
00319     0x05d0, 0x0ffc, pcxw_
00320   },
00321   {                                               /* 0x05d4 - 0x05d5 */
00322     0x05d4, 0x0ffe, pcxw_
00323   },
00324   {                                               /* 0x05d6 - 0x05d6 */
00325     0x05d6, 0x0fff, pcxw
00326   },
00327   {                                               /* 0x05d7 - 0x05d7 */
00328     0x05d7, 0x0fff, pcxw_
00329   },
00330   {                                               /* 0x05d8 - 0x05db */
00331     0x05d8, 0x0ffc, pcxw_
00332   },
00333   {                                               /* 0x05dc - 0x05dd */
00334     0x05dc, 0x0ffe, pcxw2
00335   },
00336   {                                               /* 0x05de - 0x05de */
00337     0x05de, 0x0fff, pcxw_
00338   },
00339   {                                               /* 0x05df - 0x05df */
00340     0x05df, 0x0fff, pcxw2
00341   },
00342   {                                               /* 0x05e0 - 0x05e3 */
00343     0x05e0, 0x0ffc, pcxw2
00344   },
00345   {                                               /* 0x05e4 - 0x05e4 */
00346     0x05e4, 0x0fff, pcxw2
00347   },
00348   {                                               /* 0x05e5 - 0x05e5 */
00349     0x05e5, 0x0fff, pcxw_
00350   },
00351   {                                               /* 0x05e6 - 0x05e7 */
00352     0x05e6, 0x0ffe, pcxw2
00353   },
00354   {                                               /* 0x05e8 - 0x05ef */
00355     0x05e8, 0x0ff8, pcxw2
00356   },
00357   {                                               /* 0x05f0 - 0x05ff */
00358     0x05f0, 0x0ff0, pcxw2
00359   },
00360   {                                               /* 0x0600 - 0x061f */
00361     0x0600, 0x0fe0, pcxl
00362   },
00363   {                                               /* 0x0880 - 0x088f */
00364     0x0880, 0x0ff0, mako
00365   },
00366   {                                               /* terminate table */
00367     0x0000, 0x0000, pcx
00368   }
00369 };
00370 
00371 static const char *cpu_name_version[][2] =
00372 {
00373   { "PA7000 (PCX)",     "1.0" },
00374   { "PA7000 (PCX-S)",   "1.1a" },
00375   { "PA7100 (PCX-T)",   "1.1b" },
00376   { "PA7200 (PCX-T')",  "1.1c" },
00377   { "PA7100LC (PCX-L)", "1.1d" },
00378   { "PA7300LC (PCX-L2)",        "1.1e" },
00379   { "PA8000 (PCX-U)",   "2.0" },
00380   { "PA8200 (PCX-U+)",  "2.0" },
00381   { "PA8500 (PCX-W)",   "2.0" },
00382   { "PA8600 (PCX-W+)",  "2.0" },
00383   { "PA8700 (PCX-W2)",  "2.0" },
00384   { "PA8800 (Mako)",    "2.0" }
00385 };
00386 
00387 static long get_long(const string & path)
00388 {
00389   long result = -1;
00390   FILE * in = fopen(path.c_str(), "r");
00391 
00392   if (in)
00393   {
00394     if(fscanf(in, "%lx", &result) != 1)
00395       result = -1;
00396     fclose(in);
00397   }
00398 
00399   return result;
00400 }
00401 
00402 
00403 static string cpubusinfo(int cpu)
00404 {
00405   char buffer[10];
00406 
00407   snprintf(buffer, sizeof(buffer), "cpu@%d", cpu);
00408 
00409   return string(buffer);
00410 }
00411 
00412 
00413 enum cpu_type parisc_get_cpu_type(long hversion)
00414 {
00415   struct hp_cpu_type_mask *ptr;
00416 
00417   for (ptr = hp_cpu_type_mask_list; 0 != ptr->mask; ptr++)
00418   {
00419     if (ptr->model == (hversion & ptr->mask))
00420       return ptr->cpu;
00421   }
00422 
00423   return pcx;                                     /* not reached: */
00424 }
00425 
00426 
00427 static int currentcpu = 0;
00428 
00429 static hwNode get_device(long hw_type, long sversion, long hversion)
00430 {
00431   hwNode newnode("generic");
00432 
00433   for(unsigned i=0; parisc_device_list[i].description!=NULL; i++)
00434   {
00435     if(sversion == parisc_device_list[i].sversion)
00436     {
00437       newnode = hwNode(parisc_device_list[i].id, parisc_device_list[i].device_class);
00438       newnode.setDescription(parisc_device_list[i].description);
00439       if(hw_type == TP_NPROC)
00440       {
00441         enum cpu_type cpu = parisc_get_cpu_type(hversion);
00442         newnode.setBusInfo(cpubusinfo(currentcpu++));
00443         newnode.setProduct(cpu_name_version[cpu][0]);
00444         newnode.setVersion(cpu_name_version[cpu][1]);
00445       }
00446 
00447       return newnode;
00448     }
00449   }
00450 
00451   switch(hw_type)
00452   {
00453     case TP_NPROC:
00454       newnode = hwNode("cpu", hw::processor);
00455       newnode.setDescription("Processor");
00456       newnode.setBusInfo(cpubusinfo(currentcpu++));
00457       break;
00458     case TP_MEMORY:
00459       newnode = hwNode("memory", hw::memory);
00460       newnode.setDescription("Memory");
00461       break;
00462     case TP_B_DMA:
00463       newnode.addCapability("b-dma", "Type B DMA I/O");
00464       break;
00465     case TP_A_DMA:
00466       newnode.addCapability("a-dma", "Type A DMA I/O");
00467       break;
00468     case TP_A_DIRECT:
00469       switch (sversion)
00470       {
00471         case 0x0D:
00472           newnode = hwNode("serial", hw::communication);
00473           newnode.setDescription("MUX port");
00474           break;
00475         case 0x0E:
00476           newnode = hwNode("serial", hw::communication);
00477           newnode.setDescription("RS-232 port");
00478           break;
00479       }
00480 
00481       newnode.addCapability("a-direct", "Type A Direct I/O");
00482       break;
00483     case TP_BCPORT:
00484       newnode = hwNode("busconverter", hw::bridge);
00485       newnode.setDescription("Bus converter port");
00486       break;
00487     case TP_CIO:
00488       newnode.setDescription("HP-CIO adapter");
00489       break;
00490     case TP_CONSOLE:
00491       newnode = hwNode("console", hw::input);
00492       newnode.setDescription("Console");
00493       break;
00494     case TP_FIO:
00495       newnode.setDescription("Foreign I/O module");
00496       break;
00497     case TP_BA:
00498       newnode = hwNode("bus", hw::bus);
00499       newnode.setDescription("Bus adapter");
00500       break;
00501     case TP_IOA:
00502       newnode.setDescription("I/O adapter");
00503       break;
00504     case TP_BRIDGE:
00505       newnode = hwNode("bridge", hw::bridge);
00506       newnode.setDescription("Bus bridge to foreign bus");
00507       break;
00508     case TP_FABRIC:
00509       newnode.setDescription("Fabric ASIC");
00510       break;
00511     case TP_FAULTY:
00512       newnode.disable();
00513       newnode.setDescription("Faulty module");
00514       break;
00515   }
00516 
00517   return newnode;
00518 }
00519 
00520 
00521 static bool scan_device(hwNode & node, string name = "")
00522 {
00523   struct dirent **namelist;
00524   int n;
00525   hwNode * curnode = NULL;
00526 
00527   if(name != "")
00528   {
00529     size_t colon = name.rfind(":");
00530     long hw_type = get_long("hw_type");
00531     long sversion = get_long("sversion");
00532     long hversion = get_long("hversion");
00533     long rev = get_long("rev");
00534     hwNode newnode = get_device(hw_type, sversion, hversion);
00535 
00536     if((rev>0) && (newnode.getVersion() == ""))
00537     {
00538       char buffer[20];
00539       snprintf(buffer, sizeof(buffer), "%ld", rev);
00540       newnode.setVersion(buffer);
00541     }
00542     if(newnode.getBusInfo()=="")
00543       newnode.setBusInfo(guessBusInfo(name));
00544     if(exists("driver"))
00545     {
00546       string driver = readlink("driver");
00547       size_t slash = driver.rfind("/");
00548       newnode.setConfig("driver", driver.substr(slash==driver.npos?0:slash+1));
00549       newnode.claim();
00550     }
00551     if(colon!=name.npos)
00552       newnode.setPhysId(name.substr(colon+1));
00553     else
00554       newnode.setPhysId(name);
00555     curnode = node.addChild(newnode);
00556   }
00557 
00558   n = scandir(".", &namelist, selectdir, alphasort);
00559   if (n < 0)
00560     return false;
00561   else
00562   {
00563     for (int i = 0; i < n; i++)
00564       if(matches(namelist[i]->d_name, "^[0-9]+(:[0-9]+)*$"))
00565     {
00566       pushd(namelist[i]->d_name);
00567       scan_device(curnode?*curnode:node, namelist[i]->d_name);
00568       popd();
00569       free(namelist[i]);
00570     }
00571     free(namelist);
00572   }
00573 
00574   return true;
00575 }
00576 
00577 
00578 bool scan_parisc(hwNode & node)
00579 {
00580   hwNode *core = node.getChild("core");
00581 
00582   currentcpu = 0;
00583 
00584   if (!core)
00585   {
00586     core = node.addChild(hwNode("core", hw::bus));
00587   }
00588 
00589   if (!core)
00590     return false;
00591 
00592   if(core->getDescription()=="")
00593     core->setDescription("Motherboard");
00594   pushd(DEVICESPARISC);
00595   scan_device(*core);
00596   popd();
00597 
00598   return true;
00599 }