10

I plug an external HDD into my laptop. I try to find out the information by

$ udevadm info -a -n /dev/sdb

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host10/target10:0:0/10:0:0:0/block/sdb':
    KERNEL=="sdb"
    SUBSYSTEM=="block"
    DRIVER==""
    ATTR{range}=="16"
    ATTR{ext_range}=="256"
    ATTR{removable}=="0"
    ATTR{ro}=="0"
    ATTR{size}=="312581808"
    ATTR{alignment_offset}=="0"
    ATTR{discard_alignment}=="0"
    ATTR{capability}=="50"
    ATTR{stat}=="     322    11207    13259     2196        2        0       16        0        0     1524     2196"
    ATTR{inflight}=="       0        0"
    ATTR{events}==""
    ATTR{events_async}==""
    ATTR{events_poll_msecs}=="-1"

  looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host10/target10:0:0/10:0:0:0':
    KERNELS=="10:0:0:0"
    SUBSYSTEMS=="scsi"
    DRIVERS=="sd"
    ATTRS{device_blocked}=="0"
    ATTRS{type}=="0"
    ATTRS{scsi_level}=="0"
    ATTRS{vendor}=="USB 2.0 "
    ATTRS{model}=="Storage Device  "
    ATTRS{rev}=="0100"
    ATTRS{state}=="running"
    ATTRS{timeout}=="30"
    ATTRS{iocounterbits}=="32"
    ATTRS{iorequest_cnt}=="0x165"
    ATTRS{iodone_cnt}=="0x165"
    ATTRS{ioerr_cnt}=="0x2"
    ATTRS{evt_media_change}=="0"
    ATTRS{dh_state}=="detached"
    ATTRS{queue_depth}=="1"
    ATTRS{queue_type}=="none"
    ATTRS{max_sectors}=="240"

  looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host10/target10:0:0':
    KERNELS=="target10:0:0"
    SUBSYSTEMS=="scsi"
    DRIVERS==""

  looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host10':
    KERNELS=="host10"
    SUBSYSTEMS=="scsi"
    DRIVERS==""

  looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0':
    KERNELS=="2-1:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb-storage"
    ATTRS{bInterfaceNumber}=="00"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bNumEndpoints}=="02"
    ATTRS{bInterfaceClass}=="08"
    ATTRS{bInterfaceSubClass}=="06"
    ATTRS{bInterfaceProtocol}=="50"
    ATTRS{supports_autosuspend}=="1"

  looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb2/2-1':
    KERNELS=="2-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="c0"
    ATTRS{bMaxPower}=="  0mA"
    ATTRS{urbnum}=="1076"
    ATTRS{idVendor}=="0402"
    ATTRS{idProduct}=="5621"
    ATTRS{bcdDevice}=="0103"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="480"
    ATTRS{busnum}=="2"
    ATTRS{devnum}=="8"
    ATTRS{devpath}=="1"
    ATTRS{product}=="USB 2.0 Storage Device"
    ATTRS{serial}=="00042222200000064007"

  looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb2':
    KERNELS=="usb2"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bMaxPower}=="  0mA"
    ATTRS{urbnum}=="382"
    ATTRS{idVendor}=="1d6b"
    ATTRS{idProduct}=="0002"
    ATTRS{bcdDevice}=="0302"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="480"
    ATTRS{busnum}=="2"
    ATTRS{devnum}=="1"
    ATTRS{devpath}=="0"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="6"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="Linux 3.2.0-27-generic-pae ehci_hcd"
    ATTRS{product}=="EHCI Host Controller"
    ATTRS{serial}=="0000:00:1d.7"
    ATTRS{authorized_default}=="1"

  looking at parent device '/devices/pci0000:00/0000:00:1d.7':
    KERNELS=="0000:00:1d.7"
    SUBSYSTEMS=="pci"
    DRIVERS=="ehci_hcd"
    ATTRS{vendor}=="0x8086"
    ATTRS{device}=="0x293a"
    ATTRS{subsystem_vendor}=="0x17aa"
    ATTRS{subsystem_device}=="0x20f1"
    ATTRS{class}=="0x0c0320"
    ATTRS{irq}=="19"
    ATTRS{local_cpus}=="ff"
    ATTRS{local_cpulist}=="0-7"
    ATTRS{dma_mask_bits}=="32"
    ATTRS{consistent_dma_mask_bits}=="32"
    ATTRS{broken_parity_status}=="0"
    ATTRS{msi_bus}==""
    ATTRS{companion}==""
    ATTRS{uframe_periodic_max}=="100"

  looking at parent device '/devices/pci0000:00':
    KERNELS=="pci0000:00"
    SUBSYSTEMS==""
    DRIVERS==""

I wonder what "the chain of parent devices" is, implied by the output? I don't quite understand what following each looking at (parent) device means. For example,

Is the first one my external HDD? What are the rest?

Why are all except the last two have "usb" within '...'?

Is the one next to the last PCI slots?

What is the last one that is so empty, although having pci in its name?

Does "walk up" mean from the external HDD to CPU?

Thanks!

Tim
  • 101,790

1 Answers1

11

The walk is over the different software components (drivers) that handle the device; this corresponds by and large to the hardware devices and buses that are involved in connecting to the device. This is mostly unrelated to the physical arrangement of the devices: most of them are inside the same chip anyway.

Taking this example from the top:

  • First we have a block device (a disk-like device).
    This is the actual device, so its keys have no final S (KERNEL, ATTR, etc.). A final S (KERNELS, ATTRS, etc.) is added to ancestors' keys in the udevadm output, to match what you can write in udev rules.
  • The first parent is a SCSI disk, handled by the sd (SCSI disk) driver. This is a disk connected with the SCSI protocol, not necessarily over a physical SCSI connection; most modern storage links (ATA, SCSI, USB, iSCSI) use the SCSI protocol over different physical communication protocols.
  • SCSI addressing is layered: the SCSI device is attached to a target which is attached to a host.
  • The SCSI host is a USB storage controller, handled by the usb-storage driver.
  • The USB storage controller is attached to a USB controller. USB devices are attached in a tree fashion (like SCSI, but SCSI has a fixed number of branching points, whereas USB can chain hubs that increase the depth of the tree). I don't know enough about USB to explain the details of the USB steps.
  • Eventually we arrive at the USB host controller: ATTRS{product}=="EHCI Host Controller". EHCI means a USB 2.0 controller.
  • The USB controller talks to the CPU over a PCI bus. 0000:00:1d.7 is the bus address at which the USB controller is attached.
    PCI extension cards are attached at this level. The chip containing the USB controller isn't connected with anything so bulky, its connections are deep inside the silicon.
  • The last entry is the PCI bus itself. This is the last entry because the endpoint of that bus is the CPU.
  • Thanks! (1) Which one do "a block device (a disk-like device)" and "a SCSI disk" mean respectively: the hard disk, hard disk drive (HDD), or the external HDD (with enclosure)? Note that the HDD is IDE, which I think is different from SCSI? (2) where are the hard disk, hard disk drive, external HDD, and the interface between the USB cable connector and my laptop USB receptor respectively in the chain? – Tim Aug 18 '12 at 20:16
  • 2
    @Tim The enclosure translates between IDE and USB storage physically, electrically and at the lower level of the protocol stack. Both IDE and USB storage use SCSI as the data exchange protocol (or very close variants). Your first question is a bit tricky; the system sees different things at different levels (you could say it sees the hard disk at the block device level, the hdd at the SCSI level, and the enclosure at the USB level). The USB cable is invisible from software. – Gilles 'SO- stop being evil' Aug 18 '12 at 20:21
  • 2
    @Tim These levels are all abstractions created by the OS designers. Most of these abstractions correspond to some view of a piece of hardware (which may not be all separate components, and there can be more than one component inside a physically single-piece piece of hardware), the correspondence between the abstractions and the hardware is close but not always perfect. – Gilles 'SO- stop being evil' Aug 18 '12 at 20:23
  • Thanks! Do you know some sources for learning about the protocol stack of communication between computer or its CPU and peripheral devices? I didn't know there are different levels there. – Tim Aug 18 '12 at 20:38
  • 1
    @Tim Hmmm, I suppose these are things you only really understand when you've written the driver code on both sides (which I've never done). You can start from Wikipedia, and there are books on the topic (I have no idea what to recommend), and you can read the standards (some are freely available, some require paying, sometimes a substantial fee only available to a medium-to-large organization). – Gilles 'SO- stop being evil' Aug 18 '12 at 20:45
  • I browsed Wikipedia's articles about Buses(computing), SCSI, IDE, SATA, USB, PCI, PCIe, etc. From there, my understanding is that SCSI, IDE, SATA, USB, PCI and PCIe are all buses that are different from each other. I don't think I saw they were mentioned as different levels of protocols which can co-exist instead of being exclusive from each other. – Tim Aug 18 '12 at 20:49
  • 1
    @Tim It's like you can have IP over Ethernet, or over PPP, or over Bluetooth, etc. And you can have things like Ajax over HTTP over TCP over IP. You can have SCSI commands over SCSI, over IDE, over USB, etc. And the PCI bus relays all of these. – Gilles 'SO- stop being evil' Aug 18 '12 at 20:55
  • Thanks! (1) So levels of protocols from high to low: "SCSI commands", SCSI, IDE, USB, PCI? (2) Why are "SCSI commands" separated from SCSI? – Tim Aug 18 '12 at 21:56
  • 1
    @Tim 1) Replace IDE by USB storage, the enclosure translates between the two. 2) SCSI commands vs SCSI – Gilles 'SO- stop being evil' Aug 18 '12 at 22:06
  • Thanks! In OSI model for network, there are a host and a client, each of which has the same layers/levels of protocols. On each side of client or host, messages must goes from top to the lowest, and the communication between host and client is through the lowest level of protocol. Now back at the stack of protocols for a computer and an external HDD, I wonder where the borderline between host and client is drawn in the chain, which part of the chain is for going from top to low on each side, and which part of the chain is for going between host and client on the lowest level? – Tim Aug 19 '12 at 16:46
  • 1
    A different question: "This is the actual device, so its keys have no final S (KERNEL, ATTR, etc.). A final S (KERNELS, ATTRS, etc.) is added to ancestors' keys in the udevadm output, to match what you can write in udev rules." I wonder if keys with final S indicates software driver, not hardware, while keys without final S indicates hardware? – Tim Aug 20 '12 at 14:47
  • 1
    @Tim No, nothing to do with soft/hard. ATTRS and all are what you write in udev rules, and that's a plural, because ATTR (etc.) matches just the one device whereas ATTRS matches any device in the ancestor chain. – Gilles 'SO- stop being evil' Aug 20 '12 at 15:15
  • Thanks! Are USB storage controller, USB controller and USB host controller different things, in the last five bullets: The SCSI host is a USB storage controller, handled by the usb-storage driver, The USB storage controller is attached to a USB controller, Eventually we arrive at the USB host controller: ATTRS{product}=="EHCI Host Controller". EHCI means a USB 2.0 controller, and The USB controller talks to the CPU over a PCI bus. 0000:00:1d.7 is the bus address at which the USB controller is attached? – Tim Aug 20 '12 at 18:18