Back to index

lshw  02.16
Defines | Functions | Variables
ide.cc File Reference
#include "version.h"
#include "cpuinfo.h"
#include "osutils.h"
#include "cdrom.h"
#include "disk.h"
#include "heuristics.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <endian.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <ctype.h>
#include <vector>
#include <linux/hdreg.h>

Go to the source code of this file.

Defines

#define PROC_IDE   "/proc/ide"
#define PCI_SLOT(devfn)   (((devfn) >> 3) & 0x1f)
#define PCI_FUNC(devfn)   ((devfn) & 0x07)
#define IORDY_SUP   0x0800 /* 1=support; 0=may be supported */
#define IORDY_OFF   0x0400 /* 1=may be disabled */
#define LBA_SUP   0x0200 /* 1=Logical Block Address support */
#define DMA_SUP   0x0100 /* 1=Direct Memory Access support */
#define DMA_IL_SUP   0x8000 /* 1=interleaved DMA support (ATAPI) */
#define CMD_Q_SUP   0x4000 /* 1=command queuing support (ATAPI) */
#define OVLP_SUP   0x2000 /* 1=overlap operation support (ATAPI) */
#define GEN_CONFIG   0 /* general configuration */
#define CD_ROM   5
#define NOT_ATA   0x8000
#define NOT_ATAPI   0x4000 /* (check only if bit 15 == 1) */
#define EQPT_TYPE   0x1f00
#define command_set_1   command_sets
#define command_set_2   word83
#define hw_config   word93

Functions

 __ID ("@(#) $Id: ide.cc 2433 2012-01-10 22:01:30Z lyonel $")
static unsigned long long get_longlong (const string &path)
static string get_pciid (const string &bus, const string &device)
static bool probe_ide (const string &name, hwNode &device)
static bool is_master (const string &device)
bool scan_ide (hwNode &n)

Variables

static const char * description []

Define Documentation

#define CD_ROM   5

Definition at line 49 of file ide.cc.

#define CMD_Q_SUP   0x4000 /* 1=command queuing support (ATAPI) */

Definition at line 45 of file ide.cc.

#define command_set_1   command_sets

Definition at line 92 of file ide.cc.

#define command_set_2   word83

Definition at line 93 of file ide.cc.

#define DMA_IL_SUP   0x8000 /* 1=interleaved DMA support (ATAPI) */

Definition at line 44 of file ide.cc.

#define DMA_SUP   0x0100 /* 1=Direct Memory Access support */

Definition at line 43 of file ide.cc.

#define EQPT_TYPE   0x1f00

Definition at line 52 of file ide.cc.

#define GEN_CONFIG   0 /* general configuration */

Definition at line 48 of file ide.cc.

#define hw_config   word93

Definition at line 94 of file ide.cc.

#define IORDY_OFF   0x0400 /* 1=may be disabled */

Definition at line 41 of file ide.cc.

#define IORDY_SUP   0x0800 /* 1=support; 0=may be supported */

Definition at line 40 of file ide.cc.

#define LBA_SUP   0x0200 /* 1=Logical Block Address support */

Definition at line 42 of file ide.cc.

#define NOT_ATA   0x8000

Definition at line 50 of file ide.cc.

#define NOT_ATAPI   0x4000 /* (check only if bit 15 == 1) */

Definition at line 51 of file ide.cc.

#define OVLP_SUP   0x2000 /* 1=overlap operation support (ATAPI) */

Definition at line 46 of file ide.cc.

#define PCI_FUNC (   devfn)    ((devfn) & 0x07)

Definition at line 38 of file ide.cc.

#define PCI_SLOT (   devfn)    (((devfn) >> 3) & 0x1f)

Definition at line 37 of file ide.cc.

#define PROC_IDE   "/proc/ide"

Definition at line 35 of file ide.cc.


Function Documentation

__ID ( "@(#) $Id: ide.cc 2433 2012-01-10 22:01:30Z lyonel $"  )
static unsigned long long get_longlong ( const string &  path) [static]

Definition at line 97 of file ide.cc.

{
  FILE *in = fopen(path.c_str(), "r");
  unsigned long long l = 0;

  if (in)
  {
    if(fscanf(in, "%lld", &l) < 1)
      l = 0;
    fclose(in);
  }

  return l;
}

Here is the caller graph for this function:

static string get_pciid ( const string &  bus,
const string &  device 
) [static]

Definition at line 113 of file ide.cc.

{
  char buffer[20];
  int pcibus, pcidevfunc;

  sscanf(bus.c_str(), "%x", &pcibus);
  sscanf(device.c_str(), "%x", &pcidevfunc);
  snprintf(buffer, sizeof(buffer), "%02x:%02x.%x", pcibus,
    PCI_SLOT(pcidevfunc), PCI_FUNC(pcidevfunc));

  return string(buffer);
}

Here is the caller graph for this function:

static bool is_master ( const string &  device) [static]

Definition at line 319 of file ide.cc.

{
  if (device == "")
    return false;

  switch ((device[device.length() - 1] - 'a') % 2)
  {
    case 0:
      return true;
    case 1:
      return false;
    default:
      return false;
  }
}

Here is the caller graph for this function:

static bool probe_ide ( const string &  name,
hwNode device 
) [static]

Definition at line 128 of file ide.cc.

{
  struct hd_driveid id;
  const u_int8_t *id_regs = (const u_int8_t *) &id;
  int fd = open(device.getLogicalName().c_str(), O_RDONLY | O_NONBLOCK);

  if (fd < 0)
    return false;

  memset(&id, 0, sizeof(id));
  if (ioctl(fd, HDIO_GET_IDENTITY, &id) != 0)
  {
    close(fd);
    return false;
  }

  u_int8_t args[4 + 512] = { WIN_IDENTIFY, 0, 0, 1, };

  if(id.config & 0x8000)                          // we have a packet device
  {
    args[0] = WIN_PIDENTIFY;                      // so use the right command to avoid kernel messages (Aborted Command)
    device.addCapability("packet", "ATAPI packet device");
  }

  if (ioctl(fd, HDIO_DRIVE_CMD, &args) != 0)
  {
    close(fd);
    return false;
  }

  close(fd);

  u_int16_t pidentity[256];
  for (int i = 0; i < 256; i++)
    pidentity[i] = args[4 + 2 * i] + (args[4 + 2 * i + 1] << 8);

  if (id.model[0])
    device.setProduct(hw::strip(string((char *) id.model, sizeof(id.model))));
  if (id.fw_rev[0])
    device.
      setVersion(hw::strip(string((char *) id.fw_rev, sizeof(id.fw_rev))));
  if (id.serial_no[0])
    device.
      setSerial(hw::
      strip(string((char *) id.serial_no, sizeof(id.serial_no))));

  if (!(pidentity[GEN_CONFIG] & NOT_ATA))
  {
    device.addCapability("ata", "ATA");
    device.setDescription("ATA Disk");
  }
  else if (!(pidentity[GEN_CONFIG] & NOT_ATAPI))
  {
    u_int8_t eqpt = (pidentity[GEN_CONFIG] & EQPT_TYPE) >> 8;
    device.addCapability("atapi", "ATAPI");

    if (eqpt == CD_ROM)
      device.addCapability("cdrom", "can read CD-ROMs");

    if (eqpt < 0x20)
      device.setDescription("IDE " + string(description[eqpt]));
  }
  if (id.config & (1 << 7))
    device.addCapability("removable", "support is removable");
  if (id.config & (1 << 15))
    device.addCapability("nonmagnetic", "support is non-magnetic (optical)");
  if (id.capability & 1)
    device.addCapability("dma", "Direct Memory Access");
  if (id.capability & 2)
    device.addCapability("lba", "Large Block Addressing");
  if (id.capability & 8)
    device.addCapability("iordy", "I/O ready reporting");
  if (id.command_set_1 & 1)
    device.addCapability("smart",
      "S.M.A.R.T. (Self-Monitoring And Reporting Technology)");
  if (id.command_set_1 & 2)
    device.addCapability("security", "ATA security extensions");
  if (id.command_set_1 & 4)
    device.addCapability("removable", "support is removable");
  if (id.command_set_1 & 8)
    device.addCapability("pm", "Power Management");
  if (id.command_set_2 & 8)
    device.addCapability("apm", "Advanced Power Management");

  if ((id.capability & 8) || (id.field_valid & 2))
  {
    if (id.field_valid & 4)
    {
      if (id.dma_ultra & 0x100)
        device.setConfig("mode", "udma0");
      if (id.dma_ultra & 0x200)
        device.setConfig("mode", "udma1");
      if (id.dma_ultra & 0x400)
        device.setConfig("mode", "udma2");
      if (id.hw_config & 0x2000)
      {
        if (id.dma_ultra & 0x800)
          device.setConfig("mode", "udma3");
        if (id.dma_ultra & 0x1000)
          device.setConfig("mode", "udma4");
        if (id.dma_ultra & 0x2000)
          device.setConfig("mode", "udma5");
        if (id.dma_ultra & 0x4000)
          device.setConfig("mode", "udma6");
        if (id.dma_ultra & 0x8000)
          device.setConfig("mode", "udma7");
      }
    }
  }

  if (id_regs[83] & 8)
    device.addCapability("apm", "Advanced Power Management");

//if (device.isCapable("iordy") && (id.capability & 4))
//device.setConfig("iordy", "yes");

  if (device.isCapable("smart"))
  {
    if (id.command_set_2 & (1 << 14))
      device.setConfig("smart", "on");
    else
      device.setConfig("smart", "off");
  }

  if (device.isCapable("apm"))
  {
    if (!(id_regs[86] & 8))
      device.setConfig("apm", "off");
    else
      device.setConfig("apm", "on");
  }

  if (device.isCapable("lba"))
    device.setCapacity((unsigned long long) id.lba_capacity * 512);
  if (device.isCapable("removable"))
    device.setCapacity(0);                        // we'll first have to make sure we have a disk

  if (device.isCapable("cdrom"))
    scan_cdrom(device);
  else
    scan_disk(device);

#if 0
  if (!(iddata[GEN_CONFIG] & NOT_ATA))
    device.addCapability("ata");
  else if (iddata[GEN_CONFIG] == CFA_SUPPORT_VAL)
  {
    device.addCapability("ata");
    device.addCapability("compactflash");
  }
  else if (!(iddata[GEN_CONFIG] & NOT_ATAPI))
  {
    device.addCapability("atapi");
    device.setDescription(description[(iddata[GEN_CONFIG] & EQPT_TYPE) >> 8]);
  }

  if (iddata[START_MODEL])
    device.setProduct(print_ascii((char *) &iddata[START_MODEL],
      LENGTH_MODEL));
  if (iddata[START_SERIAL])
    device.
      setSerial(print_ascii((char *) &iddata[START_SERIAL], LENGTH_SERIAL));
  if (iddata[START_FW_REV])
    device.
      setVersion(print_ascii((char *) &iddata[START_FW_REV], LENGTH_FW_REV));
  if (iddata[CAPAB_0] & LBA_SUP)
    device.addCapability("lba");
  if (iddata[CAPAB_0] & IORDY_SUP)
    device.addCapability("iordy");
  if (iddata[CAPAB_0] & IORDY_OFF)
  {
    device.addCapability("iordy");
    device.addCapability("iordyoff");
  }
  if (iddata[CAPAB_0] & DMA_SUP)
    device.addCapability("dma");
  if (iddata[CAPAB_0] & DMA_IL_SUP)
  {
    device.addCapability("interleaved_dma");
    device.addCapability("dma");
  }
  if (iddata[CAPAB_0] & CMD_Q_SUP)
    device.addCapability("command_queuing");
  if (iddata[CAPAB_0] & OVLP_SUP)
    device.addCapability("overlap_operation");
#endif
  return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool scan_ide ( hwNode n)

Definition at line 335 of file ide.cc.

{
  struct dirent **namelist;
  int nentries;

  pushd(PROC_IDE);
  nentries = scandir(".", &namelist, selectdir, alphasort);
  popd();

  if (nentries < 0)
    return false;

  for (int i = 0; i < nentries; i++)
  {
    vector < string > config;
    hwNode ide("ide",
      hw::bus);

    ide.setLogicalName(namelist[i]->d_name);
    ide.setHandle("IDE:" + string(namelist[i]->d_name));

    if (exists(string(PROC_IDE"/") + namelist[i]->d_name + "/channel"))
    {
      vector < string > identify;
      string channel = "";
      char *id = namelist[i]->d_name;

      while ((*id != 0) && (!isdigit(*id)))
        id++;
      if (*id != 0)
      {
        ide.setBusInfo("ide@" + string(id));
        ide.setPhysId(string(id));
      }

      loadfile(string(PROC_IDE"/") + namelist[i]->d_name + "/config", config);
      if (config.size() > 0)
        splitlines(config[0], identify, ' ');
      config.clear();
      loadfile(string(PROC_IDE"/") + namelist[i]->d_name + "/channel", config);
      if (config.size() > 0)
        channel = config[0];
      config.clear();

//if (identify.size() >= 1)
      {
        struct dirent **devicelist;
        int ndevices;

        pushd(string(PROC_IDE) + "/" + namelist[i]->d_name);
        ndevices = scandir(".", &devicelist, selectdir, alphasort);
        popd();

        for (int j = 0; j < ndevices; j++)
        {
          string basepath =
            string(PROC_IDE) + "/" + namelist[i]->d_name + "/" +
            devicelist[j]->d_name;
          hwNode idedevice("device",
            hw::storage);

          idedevice =
            hwNode(get_string(basepath + "/media", "disk"), hw::disk);

          idedevice.setCapacity(512 * get_longlong(basepath + "/capacity"));
          idedevice.setLogicalName(string("/dev/") + devicelist[j]->d_name);
          idedevice.setProduct(get_string(basepath + "/model"));
          idedevice.claim();
          idedevice.setHandle(ide.getHandle() + ":" +
            string(devicelist[j]->d_name));
          if (is_master(devicelist[j]->d_name))
            idedevice.setPhysId(0);
          else
            idedevice.setPhysId(1);
          idedevice.setBusInfo(ide.getBusInfo() + "." +
            idedevice.getPhysId());

          probe_ide(devicelist[j]->d_name, idedevice);

          ide.addChild(idedevice);
          free(devicelist[j]);
        }
        free(devicelist);

        ide.setDescription(hw::strip("IDE Channel " + hw::strip(channel)));

        if ( identify.size() == 11 && identify[0] == "pci")
        {
          string businfo = guessBusInfo(get_pciid(identify[2], identify[4]));
          hwNode *parent = n.findChildByBusInfo(businfo);

          if (parent)
          {
            parent->claim();
            ide.setClock(parent->getClock());
            parent->addChild(ide);
          }
        }
        else                                      // we have to guess the parent device
        {
          hwNode * parent = guessParent(ide, n);
          if(parent)
          {
            parent->claim();
            ide.setClock(parent->getClock());
            parent->addChild(ide);
          }
          else
            for (unsigned int k = 0; k < ide.countChildren(); k++)
          {
            hwNode *candidate =
              n.findChildByLogicalName(ide.getChild(k)->getLogicalName());

            if (candidate)
            {
              parent = candidate;
              candidate->merge(*ide.getChild(k));
              break;
            }
          }
          if(!parent) n.addChild(ide);
        }
      }

    }

    free(namelist[i]);
  }
  free(namelist);

  return false;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

const char* description[] [static]

Definition at line 54 of file ide.cc.