home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume26 / sysinfo-1.0 / part01 / devices.c < prev    next >
C/C++ Source or Header  |  1993-04-10  |  23KB  |  943 lines

  1. /*
  2.  * Copyright (c) 1992 Michael A. Cooper.
  3.  * This software may be freely distributed provided it is not sold for 
  4.  * profit and the author is credited appropriately.
  5.  */
  6.  
  7. #ifndef lint
  8. static char *RCSid = "$Header: /src/common/usc/bin/sysinfo/RCS/devices.c,v 1.18 1992/04/26 23:32:06 mcooper Exp $";
  9. #endif
  10.  
  11. /*
  12.  * $Log: devices.c,v $
  13.  * Revision 1.18  1992/04/26  23:32:06  mcooper
  14.  * Add Copyright notice
  15.  *
  16.  * Revision 1.17  1992/04/17  01:07:59  mcooper
  17.  * More de-linting
  18.  *
  19.  * Revision 1.16  1992/04/16  02:25:39  mcooper
  20.  * Bug fixes, de-linting, and other changes found with CodeCenter.
  21.  *
  22.  * Revision 1.15  1992/04/15  02:41:37  mcooper
  23.  * Change AddDevice() to check to make sure device doesn't already exist.
  24.  *
  25.  * Revision 1.14  1992/04/12  22:01:11  mcooper
  26.  * Remove kludge for "id".
  27.  *
  28.  * Revision 1.12  1992/03/22  02:03:31  mcooper
  29.  * Call BuildDevicesNeXT().
  30.  *
  31.  * Revision 1.11  1992/03/22  00:20:10  mcooper
  32.  * Major cleanup and re-org.
  33.  *
  34.  * Revision 1.10  1992/03/09  01:25:24  mcooper
  35.  * Print device description on first line if no other info is available.
  36.  *
  37.  * Revision 1.9  1992/03/08  04:57:36  mcooper
  38.  * - Add support for multiple address per netif.
  39.  * - Move probe_generic() here for os-sunos.c.
  40.  *
  41.  * Revision 1.8  1992/03/06  18:36:55  mcooper
  42.  * Move some general functions here from sunos.c.
  43.  *
  44.  * Revision 1.7  1992/03/05  22:36:35  mcooper
  45.  * Cleanup format.
  46.  *
  47.  * Revision 1.6  1992/03/01  21:30:37  mcooper
  48.  * Use dd_secsize from DISKDRIVE instead of SECSIZE macro.
  49.  *
  50.  * Revision 1.5  1992/02/25  00:16:14  mcooper
  51.  * - Major cleanup of printing.
  52.  * - Init new device int's to -1.
  53.  * - Add new device type's.
  54.  *
  55.  * Revision 1.4  1992/02/22  02:20:19  mcooper
  56.  * Major changes to support scanning kernel mainbus and
  57.  * openprom data for device's.
  58.  *
  59.  * Revision 1.3  1992/02/16  23:50:47  mcooper
  60.  * Cleanup newline printing and add verbosity level checking.
  61.  *
  62.  * Revision 1.2  1992/02/16  22:46:03  mcooper
  63.  * Add network interface support.
  64.  *
  65.  * Revision 1.1  1991/11/30  23:28:53  mcooper
  66.  * Initial revision
  67.  *
  68.  */
  69.  
  70.  
  71. #include <stdio.h>
  72. #include "system.h"
  73. #include "defs.h"
  74.  
  75. #define OFFSET 4
  76.  
  77. static void PrintDiskdrive();
  78. static void PrintFrameBuffer();
  79. static void PrintNetIf();
  80. static void PrintDevice();
  81. static void PrintGeneric();
  82.  
  83. struct devicetype {
  84.     int                 dt_dtype;    /* Device type */
  85.     char            *dt_desc;    /* Description */
  86.     void               (*dt_prfunc)();    /* Print function */
  87. };
  88. typedef struct devicetype DEVTYPE;
  89.  
  90. DEVTYPE DevTypes[] = {
  91.     { DT_GENERIC,    NULL,            PrintGeneric },
  92.     { DT_DISKDRIVE,    "disk drive",        PrintDiskdrive },
  93.     { DT_DISKCTLR,    "disk controller",    PrintGeneric },
  94.     { DT_TAPEDRIVE,    "tape drive",        PrintGeneric },
  95.     { DT_TAPECTLR,    "tape controller",    PrintGeneric },
  96.     { DT_FRAMEBUFFER,    "frame buffer",        PrintFrameBuffer },
  97.     { DT_NETIF,        "network interface",    PrintNetIf },
  98.     { DT_BUS,        "system bus",        PrintGeneric },
  99.     { DT_PSEUDO,    "pseudo device",    PrintGeneric },
  100.     { 0 },
  101. };
  102.  
  103. static float             TotalDisk = 0;
  104.  
  105. /*
  106.  * Get a device type.
  107.  */
  108. static DEVTYPE *GetDevType(Device)
  109.     DEVICE                *Device;
  110. {
  111.     register int         i;
  112.  
  113.     if (!Device)
  114.     return((DEVTYPE *) NULL);
  115.  
  116.     for (i = 0; DevTypes[i].dt_prfunc; ++i)
  117.     if (DevTypes[i].dt_dtype == Device->dv_type)
  118.         return(&DevTypes[i]);
  119.  
  120.     return((DEVTYPE *) NULL);
  121. }
  122.  
  123. /*
  124.  * Print all device info
  125.  */
  126. extern void ShowDevices(MyInfo, SpecInfo)
  127.     SHOWINFO               *MyInfo;
  128.     SHOWINFO               *SpecInfo;    /* ARGSUSED */
  129. {
  130.     static DEVICE            *RootDev;
  131.  
  132. #if    defined(sun)
  133.     if (BuildDevicesSunOS(&RootDev) != 0)
  134.     return;
  135. #endif    /* sun */
  136.  
  137. #if    defined(ultrix)
  138.     if (BuildDevicesUltrix(&RootDev) != 0)
  139.     return;
  140. #endif    /* ultrix */
  141.  
  142. #if    defined(NeXT)
  143.     if (BuildDevicesNeXT(&RootDev) != 0)
  144.     return;
  145. #endif    /* NeXT */
  146.  
  147.     if (!RootDev) {
  148.     if (Debug)
  149.         printf("No devices were found.\n");
  150.     return;
  151.     }
  152.  
  153.     printf("\n\n\t%s\n\n", MyInfo->Label);
  154.  
  155.     TotalDisk = 0;
  156.  
  157.     PrintDevice(RootDev, 0);
  158.  
  159.     if (VL_DESC && TotalDisk > 0)
  160.     printf("\nTotal Disk Capacity is %.2f MB.\n", 
  161.            (float) bytes_to_mbytes(TotalDisk));
  162. }
  163.  
  164. /*
  165.  * --RECURSE--
  166.  * Print info about a device.  Recursively calls itself for slaves and
  167.  * next elements
  168.  */
  169. static void PrintDevice(Device, OffSet)
  170.     DEVICE                *Device;
  171.     int             OffSet;
  172. {
  173.     DEVTYPE                *DevType;
  174.  
  175.     /*
  176.      * If device->dv_name is not set, this is the root of the device tree
  177.      */
  178.  
  179.     if (Device->dv_name) {
  180.     if (DevType = GetDevType(Device))
  181.         (*DevType->dt_prfunc)(Device, DevType, OffSet);
  182.     else
  183.         PrintGeneric(Device, DevType, OffSet);
  184.     }
  185.  
  186.     /*
  187.      * Descend
  188.      */
  189.     if (Device->dv_slaves)
  190.     PrintDevice(Device->dv_slaves, (Device->dv_name) ? OffSet+OFFSET : 0);
  191.  
  192.     /*
  193.      * Traverse
  194.      */
  195.     if (Device->dv_nxt)
  196.     PrintDevice(Device->dv_nxt, (Device->dv_name) ? OffSet : 0);
  197. }
  198.  
  199. /*
  200.  * Print Off Set space
  201.  */
  202. static void PrOffSet(cnt)
  203.     int             cnt;
  204. {
  205.     printf("%*s", cnt, "");
  206. }
  207.  
  208. /*
  209.  * Print a device label
  210.  */
  211. static void PrDevLabel(Name, OffSet)
  212.     char                *Name;
  213.     int             OffSet;
  214. {
  215.     PrOffSet(OffSet);
  216.     if (VL_CONFIG)
  217.     printf("%*s%-18s:", OFFSET, "", Name);
  218.     else
  219.     printf("%*s%18s:", OFFSET, "", Name);
  220. }
  221.  
  222. /*
  223.  * Print general device information
  224.  */
  225. static void PrintDeviceInfo(Device, DevType, OffSet)
  226.     DEVICE                *Device;
  227.     DEVTYPE                *DevType;
  228.     int             OffSet;
  229. {     
  230.     DEVTYPE                *mdt;
  231.  
  232.     if (!Device->dv_name)
  233.     return;
  234.  
  235.     if (VL_CONFIG) printf("\n");
  236.     PrOffSet(OffSet);
  237.     printf("Device %s", Device->dv_name);
  238.  
  239.     if (Device->dv_model || (DevType && DevType->dt_desc)) {
  240.     printf(" is a");
  241.     if (Device->dv_model)
  242.         printf(" \"%s\"", Device->dv_model);
  243.  
  244.     if (DevType && DevType->dt_desc)
  245.         printf(" %s", DevType->dt_desc);
  246.     } else if (Device->dv_desc) {
  247.     printf(" is a");
  248.     printf(" %s", Device->dv_desc);
  249.     }
  250.  
  251.     if (Device->dv_name)
  252.     printf(".\n");
  253.  
  254.     if (VL_DESC || VL_CONFIG) {
  255.     if (Device->dv_desc) {
  256.         PrDevLabel("Description", OffSet);
  257.         printf(" %s\n", Device->dv_desc);
  258.     } else if ((mdt = GetDevType(Device)) && mdt && mdt->dt_desc) {
  259.         PrDevLabel("Description", OffSet);
  260.         printf(" %s\n", mdt->dt_desc);
  261.     }
  262.  
  263.     if (Device->dv_master && Device->dv_master->dv_name) {
  264.         PrDevLabel("Description", OffSet);
  265.         if (Device->dv_master->dv_name)
  266.         printf(" Connected to %s", Device->dv_master->dv_name);
  267.         else if (Device->dv_master->dv_model) {
  268.         printf(" Connected to %s", Device->dv_master->dv_model);
  269.         if (mdt = GetDevType(Device->dv_master))
  270.             printf(" %s", mdt->dt_desc);
  271.         }
  272.         printf("\n");
  273.     }
  274.     }
  275. }
  276.  
  277. /*
  278.  * Print info about a generic device
  279.  */
  280. static void PrintGeneric(Device, DevType, OffSet)
  281.     DEVICE                *Device;
  282.     DEVTYPE                *DevType;
  283.     int             OffSet;
  284. {
  285.     register DEVICE            *pd;
  286.  
  287.     PrintDeviceInfo(Device, DevType, OffSet);
  288.  
  289.     if (VL_CONFIG) {
  290.     if (Device->dv_unit >= 0 || Device->dv_addr >= 0 || 
  291.         Device->dv_prio >= 0 || Device->dv_vec >= 0) {
  292.         PrDevLabel("Configuration", OffSet);
  293.         if (Device->dv_unit >= 0)
  294.         printf(" Unit %d", Device->dv_unit);
  295.         if (Device->dv_addr >= 0)
  296.         printf(" Address 0x%x", Device->dv_addr);
  297.         if (Device->dv_prio >= 0)
  298.         printf(" Priority %d", Device->dv_prio);
  299.         if (Device->dv_vec >= 0)
  300.         printf(" Vector %d", Device->dv_vec);
  301.         printf("\n");
  302.     }
  303.     }
  304.  
  305.     if (VL_CONFIG) {
  306.     if (Device->dv_slaves && (Device->dv_name || Device->dv_model || 
  307.                   (DevType && DevType->dt_desc))) {
  308.         PrDevLabel("Attached Device(s)", OffSet);
  309.         for (pd = Device->dv_slaves; pd; pd = pd->dv_nxt)
  310.         printf(" %s", pd->dv_name);
  311.         printf("\n");
  312.     }
  313.     }
  314. }
  315.  
  316. /*
  317.  * Print info about disk partitioning.
  318.  */
  319. static void PrintDiskPart(Disk, OffSet)
  320.     DISKDRIVE                *Disk;
  321.     int             OffSet;
  322. {
  323.     register DISKPART            *pp;
  324.  
  325.     printf("\n");
  326.     PrOffSet(OffSet);
  327.     printf("%50s\n", "Partition Information");
  328.  
  329.     PrOffSet(OffSet);
  330.     printf("%20s %10s %10s %9s\n",
  331.        "", "START", "NUMBER OF", "SIZE");
  332.  
  333.     PrOffSet(OffSet);
  334.     printf("%20s %10s %10s %9s %s\n",
  335.        "PART", "SECTOR", "SECTORS", "(MB)", "USAGE");
  336.  
  337.     for (pp = Disk->dd_part; pp; pp = pp->dp_nxt) {
  338.     PrOffSet(OffSet);
  339.     printf("%20s %10d %10d %9.2f %s\n",
  340.            pp->dp_name,
  341.            pp->dp_stsect,
  342.            pp->dp_nsect,
  343.            bytes_to_mbytes(nsect_to_bytes(pp->dp_nsect, Disk->dd_secsize)),
  344.            (pp->dp_mnt) ? pp->dp_mnt : ""
  345.            );
  346.     }
  347. }
  348.  
  349. /*
  350.  * Print info about a disk device.
  351.  */
  352. static void PrintDiskdrive(Device, DevType, OffSet)
  353.     DEVICE                *Device;
  354.     DEVTYPE                *DevType;
  355.     int             OffSet;
  356. {
  357.     DISKDRIVE                *Disk;
  358.  
  359.     PrintDeviceInfo(Device, DevType, OffSet);
  360.  
  361.     if (!Device->dv_devspec)
  362.     return;
  363.  
  364.     Disk = (DISKDRIVE *) Device->dv_devspec;
  365.  
  366.     TotalDisk += (float) Disk->dd_size;
  367.  
  368.     if (VL_CONFIG) {
  369.     PrDevLabel("Configuration", OffSet);
  370.     if (FLAGS_ON(Disk->dd_flags, DF_HEXUNIT))
  371.         printf(" Unit %3.3x", Disk->dd_unit);
  372.     else
  373.         printf(" Unit %3d", Disk->dd_unit);
  374.  
  375.     printf("  Slave %2d  RPM %d  APC %d  Interleave %d\n", 
  376.            Disk->dd_slave, Disk->dd_rpm, Disk->dd_apc, Disk->dd_intrlv);
  377.  
  378.     PrDevLabel("Configuration", OffSet);
  379.     printf(" %4d Physical Cylinders  %2d Alternate Cylinders\n", 
  380.            Disk->dd_pcyl, Disk->dd_acyl);
  381.  
  382.     PrDevLabel("Geometry", OffSet);
  383.     printf(" %4d Data Cylinders      %2d Heads  %3d Sectors/Track\n",
  384.            Disk->dd_dcyl, Disk->dd_heads, Disk->dd_sect);
  385.  
  386.     if (Disk->dd_psect || Disk->dd_promrev) {
  387.         PrDevLabel("Hardware Info", OffSet);
  388.         printf(" %4d Hard Sectors  PROM Revision %d\n",
  389.            Disk->dd_psect, Disk->dd_promrev);
  390.     }
  391.     }
  392.  
  393.     if (VL_ALL && Disk->dd_part)
  394.     PrintDiskPart(Disk, OffSet);
  395. }
  396.  
  397. /*
  398.  * Print info about a frame buffer.
  399.  */
  400. static void PrintFrameBuffer(Device, DevType, OffSet)
  401.     DEVICE                *Device;
  402.     DEVTYPE                *DevType;
  403.     int             OffSet;
  404. {
  405.     FRAMEBUFFER            *fb;
  406.  
  407.     PrintDeviceInfo(Device, DevType, OffSet);
  408.  
  409.     if (!Device->dv_devspec)
  410.     return;
  411.  
  412.     fb = (FRAMEBUFFER *) Device->dv_devspec;
  413.  
  414.     if (VL_CONFIG) {
  415.     PrDevLabel("Screen Size", OffSet);
  416.     printf(" %d KB  Height %d  Width %d  Depth %d-bit%s\n",
  417.            bytes_to_kbytes(fb->fb_size),
  418.            fb->fb_height, fb->fb_width, fb->fb_depth,
  419.            (fb->fb_depth == 1) ? "" : "s");
  420.  
  421.     if (fb->fb_vmsize || fb->fb_cmsize) {
  422.         PrDevLabel("Configuration", OffSet);
  423.         if (fb->fb_vmsize)
  424.         printf(" Video Memory %d KB ", bytes_to_kbytes(fb->fb_vmsize));
  425.         if (fb->fb_cmsize)
  426.         printf(" Color Map Size is %d", fb->fb_cmsize);
  427.         printf("\n");
  428.     }
  429.     }
  430. }
  431.  
  432. /*
  433.  * Print info about a network interface
  434.  */
  435. static void PrintNetIf(Device, DevType, OffSet)
  436.     DEVICE                *Device;
  437.     DEVTYPE                *DevType;
  438.     int             OffSet;
  439. {
  440.     register NETIF           *ni;
  441.  
  442.     PrintDeviceInfo(Device, DevType, OffSet);
  443.  
  444.     if (!Device->dv_devspec)
  445.     return;
  446.  
  447.     if (VL_CONFIG) {
  448.     for (ni = (NETIF *) Device->dv_devspec; ni; ni = ni->ni_nxt) {
  449.         if (ni->ni_typename) {
  450.         printf("\n");
  451.         PrDevLabel("Address Type", OffSet);
  452.         printf(" %s\n", ni->ni_typename);
  453.         }
  454.  
  455.         if (ni->ni_hostaddr) {
  456.         PrDevLabel("Host Address", OffSet);
  457.         printf(" %-18s [%s]\n", ni->ni_hostaddr,
  458.                (ni->ni_hostname) ? ni->ni_hostname : "<unknown>");
  459.         }
  460.  
  461.         if (ni->ni_netaddr) {
  462.         PrDevLabel("Network Address", OffSet);
  463.         printf(" %-18s [%s]\n", ni->ni_netaddr, 
  464.                (ni->ni_netname) ? ni->ni_netname : "<unknown>");
  465.         }
  466.  
  467.         if (ni->ni_macaddr) {
  468.         PrDevLabel("MAC Address", OffSet);
  469.         printf(" %-18s [%s]\n", ni->ni_macaddr,
  470.                (ni->ni_macname && ni->ni_macname[0]) 
  471.                ? ni->ni_macname : "<unknown>");
  472.         }
  473.     }
  474.     }
  475. }
  476.  
  477. /*
  478.  * --RECURSE--
  479.  * Create a new DEVICE and optionally copy an old DEVICE.
  480.  */
  481. extern DEVICE *NewDevice(Old)
  482.     DEVICE                *Old;
  483. {
  484.     register DEVICE            *SlavePtr, *Slave;
  485.     DEVICE                *New = NULL;
  486.  
  487.     New = (DEVICE *) xcalloc(1, sizeof(DEVICE));
  488.  
  489.     /* Set int's to -1 */
  490.     New->dv_type = New->dv_unit = New->dv_addr = New->dv_prio = 
  491.     New->dv_vec = -1;
  492.  
  493.     if (!Old)
  494.     return(New);
  495.  
  496.     /* Bulk copy what we can */
  497.     bcopy((char *) Old, (char *) New, sizeof(DEVICE));
  498.  
  499.     New->dv_nxt = NULL;
  500.  
  501.     /* Copy contents of pointers */
  502.     if (Old->dv_name)    New->dv_name = strdup(Old->dv_name);
  503.     if (Old->dv_model)    New->dv_model = strdup(Old->dv_model);
  504.     if (Old->dv_desc)    New->dv_desc = strdup(Old->dv_desc);
  505.  
  506.     /* Copy Slave info */
  507.     for (Slave = Old->dv_slaves; Slave; Slave = Slave->dv_nxt) {
  508.     /* Find last slave */
  509.     for (SlavePtr = New->dv_slaves; SlavePtr && SlavePtr->dv_nxt; 
  510.          SlavePtr = SlavePtr->dv_nxt);
  511.     /* Copy Old slave to last new slave device */
  512.     SlavePtr = NewDevice(Slave);
  513.     }
  514.  
  515.     return(New);
  516. }
  517.  
  518. /*
  519.  * Create a new DISKPART and optionally copy an old DISKPART.
  520.  */
  521. extern DISKPART *NewDiskPart(Old)
  522.     DISKPART                *Old;
  523. {
  524.     DISKPART                *New = NULL;
  525.  
  526.     New = (DISKPART *) xcalloc(1, sizeof(DISKPART));
  527.  
  528.     if (!Old)
  529.     return(New);
  530.  
  531.     /* Bulk copy what we can */
  532.     bcopy((char *) Old, (char *) New, sizeof(DISKPART));
  533.  
  534.     New->dp_nxt = NULL;
  535.  
  536.     /* Copy contents of pointers */
  537.     if (Old->dp_name)    New->dp_name = strdup(Old->dp_name);
  538.     if (Old->dp_mnt)    New->dp_mnt = strdup(Old->dp_mnt);
  539.  
  540.     return(New);
  541. }
  542.  
  543. /*
  544.  * --RECURSE--
  545.  * Create a new DISKDRIVE and optionally copy an old DISKDRIVE.
  546.  */
  547. extern DISKDRIVE *NewDiskDrive(Old)
  548.     DISKDRIVE                *Old;
  549. {
  550.     register DISKPART            *dp, *pdp;
  551.     DISKDRIVE                *New = NULL;
  552.  
  553.     New = (DISKDRIVE *) xcalloc(1, sizeof(DISKDRIVE));
  554.  
  555.     if (!Old)
  556.     return(New);
  557.  
  558.     /* Bulk copy what we can */
  559.     bcopy((char *) Old, (char *) New, sizeof(DISKDRIVE));
  560.  
  561.     New->dd_nxt = NULL;
  562.  
  563.     /* Copy contents of pointers */
  564.     if (Old->dd_label)    New->dd_label = strdup(Old->dd_label);
  565.     if (Old->dd_ctlr)     New->dd_ctlr = NewDevice(Old->dd_ctlr);
  566.  
  567.     /* Copy partition info */
  568.     for (dp = Old->dd_part; dp; dp = dp->dp_nxt) {
  569.     /* Find last DISKPART */
  570.     for (pdp = New->dd_part; pdp && pdp->dp_nxt; pdp = pdp->dp_nxt);
  571.     /* Copy old DISKPART to last New DISKPART */
  572.     pdp = NewDiskPart(dp);
  573.     }
  574.  
  575.     return(New);
  576. }
  577.  
  578. /*
  579.  * Create a new FRAMEBUFFER and optionally copy an old FRAMEBUFFER.
  580.  */
  581. extern FRAMEBUFFER *NewFrameBuffer(Old)
  582.     FRAMEBUFFER            *Old;
  583. {
  584.     FRAMEBUFFER            *New = NULL;
  585.  
  586.     New = (FRAMEBUFFER *) xcalloc(1, sizeof(FRAMEBUFFER));
  587.  
  588.     if (!Old)
  589.     return(New);
  590.  
  591.     /* Bulk copy what we can */
  592.     bcopy((char *) Old, (char *) New, sizeof(FRAMEBUFFER));
  593.  
  594.     return(New);
  595. }
  596.  
  597. /*
  598.  * Create a new NETIF and optionally copy an old NETIF.
  599.  */
  600. extern NETIF *NewNetif(Old)
  601.     NETIF                *Old;
  602. {
  603.     NETIF                *New = NULL;
  604.  
  605.     New = (NETIF *) xcalloc(1, sizeof(NETIF));
  606.  
  607.     if (!Old)
  608.     return(New);
  609.  
  610.     /* Copy */
  611.     New->ni_hostaddr = strdup(Old->ni_hostaddr);
  612.     New->ni_hostname = strdup(Old->ni_hostname);
  613.     New->ni_macaddr = strdup(Old->ni_macaddr);
  614.     New->ni_macname = strdup(Old->ni_macname);
  615.     New->ni_netaddr = strdup(Old->ni_netaddr);
  616.     New->ni_netname = strdup(Old->ni_netname);
  617.  
  618.     return(New);
  619. }
  620.  
  621. /*
  622.  * --RECURSE--
  623.  * Find device named "name" in tree "treeptr".
  624.  * This function recursively calls itself looking for 
  625.  * the device "name".
  626.  */
  627. extern DEVICE *FindDeviceByName(Name, TreePtr)
  628.     char                *Name;
  629.     DEVICE                *TreePtr;
  630. {
  631.     DEVICE                *Ptr;
  632.  
  633.     if (!Name || !TreePtr)
  634.     return((DEVICE *) NULL);
  635.  
  636.     if (TreePtr->dv_name && Name && EQ(TreePtr->dv_name, Name))
  637.     return(TreePtr);
  638.  
  639.     if (TreePtr->dv_slaves)
  640.     if (Ptr = FindDeviceByName(Name, TreePtr->dv_slaves))
  641.         return(Ptr);
  642.  
  643.     if (TreePtr->dv_nxt)
  644.     if (Ptr = FindDeviceByName(Name, TreePtr->dv_nxt))
  645.         return(Ptr);
  646.  
  647.     return((DEVICE *) NULL);
  648. }
  649.  
  650. /*
  651.  * Check to see if device's dev1 and dev2 are consistant.
  652.  * If there is a discrepancy between the two due to one
  653.  * device not having it's value set, then set it to the
  654.  * other device's value.  Basically this "fills in the blanks".
  655.  */
  656. static void CheckDevice(Dev1, Dev2)
  657.      DEVICE                *Dev1;
  658.      DEVICE                *Dev2;
  659. {
  660. #define CHECK(a,b) \
  661.     if (a != b) { \
  662.     if (a) \
  663.         b = a; \
  664.     else if (b) \
  665.         a = b; \
  666.     }
  667.  
  668.     CHECK(Dev1->dv_type,     Dev2->dv_type);
  669.     CHECK(Dev1->dv_model,     Dev2->dv_model);
  670.     CHECK(Dev1->dv_desc,     Dev2->dv_desc);
  671.     CHECK(Dev1->dv_unit,     Dev2->dv_unit);
  672.     CHECK(Dev1->dv_addr,     Dev2->dv_addr);
  673.     CHECK(Dev1->dv_prio,     Dev2->dv_prio);
  674.     CHECK(Dev1->dv_vec,     Dev2->dv_vec);
  675.     CHECK(Dev1->dv_devspec,     Dev2->dv_devspec);
  676.     CHECK(Dev1->dv_master,     Dev2->dv_master);
  677.  
  678. #undef CHECK
  679. }
  680.  
  681. /*
  682.  * --RECURSE--
  683.  * Add a device to a device list.
  684.  */
  685. extern int AddDevice(Device, TreePtr)
  686.     DEVICE                *Device;
  687.     DEVICE               **TreePtr;
  688. {
  689.     register DEVICE            *master = NULL, *mp = NULL;
  690.  
  691.     if (!Device || !TreePtr) {
  692.     Error("Invalid parameter passed to AddDevice()");
  693.     return(-1);
  694.     }
  695.  
  696.     /*
  697.      * Make sure device hasn't already been added
  698.      */
  699.     if (FindDeviceByName(Device->dv_name, *TreePtr)) {
  700.     if (Debug) 
  701.         printf("AddDevice: Device '%s' already exists; master = '%s'\n",
  702.            Device->dv_name, (master) ? master->dv_name : "?");
  703.     return(-1);
  704.     }
  705.  
  706.     if (Device->dv_name)
  707.     Device->dv_name = strdup(Device->dv_name);
  708.  
  709.     /*
  710.      * If the device has a master, find the master device.
  711.      * If one doesn't exist in the tree, then add it by recursively
  712.      * calling this function.
  713.      */
  714.     if (Device->dv_master) {
  715.     if (*TreePtr) {
  716.         master = FindDeviceByName(Device->dv_master->dv_name, *TreePtr);
  717.         if (master && EQ(master->dv_name, Device->dv_master->dv_name))
  718.         /* Check and fix any differences in info between master's */
  719.         CheckDevice(master, Device->dv_master);
  720.     } else
  721.         master = NULL;
  722.     if (!master) {
  723.         if (AddDevice(Device->dv_master, TreePtr) != 0) {
  724.         Error("Cannot add master '%s' to device tree.", 
  725.               master->dv_name);
  726.         return(-1);
  727.         }
  728.         master = Device->dv_master;
  729.     }
  730.     } else {
  731.     if (!*TreePtr)
  732.         *TreePtr = NewDevice((DEVICE *)NULL);
  733.     master = *TreePtr;
  734.     }
  735.  
  736.     if (master->dv_name)
  737.     master->dv_name = strdup(master->dv_name);
  738.  
  739.     if (master->dv_slaves) {
  740.     /* Add to existing list of slaves */
  741.     for (mp = master->dv_slaves; mp && mp->dv_nxt; mp = mp->dv_nxt);
  742.     mp->dv_nxt = Device;
  743.     } else
  744.     /* Create first slave */
  745.     master->dv_slaves = Device;
  746.  
  747.     return(0);
  748. }
  749.  
  750. /*
  751.  * Get device data tab entry for "name"
  752.  */
  753. extern DEVDATATAB *GetDevDataTab(Name)
  754.     char                *Name;
  755. {
  756.     extern DEVDATATAB          DevDataTab[];
  757.     register int         i;
  758.  
  759.     for (i = 0; DevDataTab[i].ddt_name; ++i) {
  760.     if (EQN(Name, DevDataTab[i].ddt_name, 
  761.         strlen(DevDataTab[i].ddt_name))) {
  762.         return(&DevDataTab[i]);
  763.     }
  764.     }
  765.  
  766.     return((DEVDATATAB *) NULL);
  767. }
  768.  
  769. /*
  770.  * Create a device entry for a generic device
  771.  */
  772. extern DEVICE *ProbeGeneric(Name, DevData, DevDataTab)
  773.      /*ARGSUSED*/
  774.     char                *Name;
  775.     DEVDATA                *DevData;
  776.     DEVDATATAB                *DevDataTab;
  777. {
  778.     DEVICE               *Device;
  779.  
  780.     /*
  781.      * DT_GENERIC devices MUST be marked alive to proceed
  782.      */
  783.     if (DevDataTab->ddt_type == DT_GENERIC && 
  784.     !(FLAGS_ON(DevData->dd_flags, DD_IS_ALIVE) ||
  785.       FLAGS_ON(DevData->dd_flags, DD_MAYBE_ALIVE)))
  786.     return((DEVICE *) NULL);
  787.  
  788.     Device = NewDevice((DEVICE *) NULL);
  789.     if (Name)
  790.     Device->dv_name = strdup(Name);
  791.     else
  792.     Device->dv_name = strdup(MkDevName(DevData->dd_devname, 
  793.                        DevData->dd_devunit,
  794.                        DevDataTab->ddt_type));
  795.     Device->dv_type = DevDataTab->ddt_type;
  796.     Device->dv_model = DevDataTab->ddt_model;
  797.     Device->dv_desc = DevDataTab->ddt_desc;
  798.     Device->dv_unit = DevData->dd_devunit;
  799.     Device->dv_master = MkMasterFromDevData(DevData);
  800.  
  801.     return(Device);
  802. }
  803.  
  804. /*
  805.  * Search for and call an appropriate probe function for this 
  806.  * device
  807.  */
  808. extern DEVICE *ProbeDevice(DevData, TreePtr)
  809.     DEVDATA                *DevData;
  810.     DEVICE               **TreePtr;
  811. {
  812.     register DEVDATATAB        *pddt;
  813.     register char            *Name;
  814.     DEVICE                *ProbeUnknown();
  815.  
  816.     if (pddt = GetDevDataTab(DevData->dd_devname)) {
  817.     Name = MkDevName(DevData->dd_devname, DevData->dd_devunit,
  818.              pddt->ddt_type);
  819.     if (FindDeviceByName(Name, *TreePtr)) {
  820.         if (Debug) printf("Device %s already exists.\n", Name);
  821.         return((DEVICE *) NULL);
  822.     }
  823.     return((*pddt->ddt_probe)(Name, DevData, pddt));
  824.     }
  825.  
  826.     /*
  827.      * The device is unknown to us.  If it's definetly alive,
  828.      * return a minimal device entry for it.  If it's not alive,
  829.      * ignore it.
  830.      */
  831.     if (DoPrintUnknown && DevData->dd_devname && 
  832.     FLAGS_ON(DevData->dd_flags, DD_IS_ALIVE))
  833.     return(ProbeUnknown(Name, DevData));
  834.  
  835.     if (Debug)
  836.     printf("Device `%s' is not defined.\n", DevData->dd_devname);
  837.  
  838.     return((DEVICE *) NULL);
  839. }
  840.  
  841.  
  842. /*
  843.  * Make a master device from a DevData controller
  844.  */
  845. extern DEVICE *MkMasterFromDevData(DevData)
  846.     DEVDATA                *DevData;
  847. {
  848.     register DEVICE            *Device = NULL;
  849.     register DEVDATATAB        *ddt;
  850.     int             type = 0;
  851.  
  852.     if (DevData->dd_ctlrname) {
  853.     Device = NewDevice(NULL);
  854.     if (ddt = GetDevDataTab(DevData->dd_ctlrname)) {
  855.         type = ddt->ddt_type;
  856.         Device->dv_desc = ddt->ddt_desc;
  857.         Device->dv_model = ddt->ddt_model;
  858.     }
  859.     Device->dv_name = MkDevName(DevData->dd_ctlrname,
  860.                     DevData->dd_ctlrunit, 
  861.                     type);
  862.     }
  863.  
  864.     return(Device);
  865. }
  866.  
  867. /*
  868.  * Make the file name of the raw device
  869.  */
  870. extern char *GetRawFile(Name, Part)
  871.     char                *Name;
  872.     char                *Part;
  873. {
  874.     static char         rfile[BUFSIZ];
  875.  
  876.     if (!Name)
  877.     return((char *) NULL);
  878.  
  879.     (void) sprintf(rfile, "/dev/r%s%s", Name, (Part) ? Part : "");
  880.  
  881.     return(rfile);
  882. }
  883.  
  884. /*
  885.  * Make the file name of the character device
  886.  */
  887. extern char *GetCharFile(Name, Part)
  888.     char                *Name;
  889.     char                *Part;
  890. {
  891.     static char         file[BUFSIZ];
  892.  
  893.     if (!Name)
  894.     return((char *) NULL);
  895.  
  896.     (void) sprintf(file, "/dev/%s%s", Name, (Part) ? Part : "");
  897.  
  898.     return(file);
  899. }
  900.  
  901. /*
  902.  * Make device name
  903.  */
  904. extern char *MkDevName(Name, Unit, Type)
  905.     char                *Name;
  906.     int             Unit;
  907.     int             Type;
  908. {
  909.     static char            Buf[BUFSIZ];
  910.  
  911.     /*
  912.      * Don't attach unit number if this is a pseudo device.
  913.      */
  914.     if (Type == DT_PSEUDO)
  915.     sprintf(Buf, "%s", Name);
  916.     else
  917.     sprintf(Buf, "%s%d", Name, Unit);
  918.  
  919.     return(strdup(Buf));
  920. }
  921.  
  922. /*
  923.  * Create a minimal device type for an unknown device.
  924.  */
  925. extern DEVICE *ProbeUnknown(Name, DevData)
  926.      /*ARGSUSED*/
  927.     char                *Name;
  928.     DEVDATA                *DevData;
  929. {
  930.     DEVICE               *Device;
  931.  
  932.     Device = NewDevice((DEVICE *) NULL);
  933.     Device->dv_name = strdup(MkDevName(DevData->dd_devname, 
  934.                        DevData->dd_devunit,
  935.                        -1));
  936.     Device->dv_type = DT_GENERIC;
  937.     Device->dv_desc = "unknown device type";
  938.     Device->dv_unit = DevData->dd_devunit;
  939.     Device->dv_master = MkMasterFromDevData(DevData);
  940.  
  941.     return(Device);
  942. }
  943.