<?xml version="1.0"?>
<!-- A Relax NG schema for the libvirt node device XML format -->
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
    datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
  <include href="basictypes.rng"/>
  <start>
    <ref name="device"/>
  </start>

  <define name="device">
    <element name="device">
      <!-- The name of the network, used to refer to it through the API
         and in virsh -->
      <element name="name"><text/></element>
      <optional>
        <element name="path"><text/></element>
      </optional>
      <optional>
        <element name="devnode">
          <attribute name="type">
            <value>dev</value>
          </attribute>
          <text/>
        </element>
      </optional>
      <zeroOrMore>
        <element name="devnode">
          <attribute name="type">
            <value>link</value>
          </attribute>
          <text/>
        </element>
      </zeroOrMore>
      <optional>
        <ref name="parent"/>
      </optional>

      <optional>
        <element name="driver">
          <element name="name"><text/></element>
        </element>
      </optional>

      <zeroOrMore>
        <ref name="capability"/>
      </zeroOrMore>
    </element>
  </define>

  <define name="parent">
    <element name="parent">
      <choice>
        <group>
          <attribute name="wwnn">
            <ref name="wwn"/>
          </attribute>
          <attribute name="wwpn">
            <ref name="wwn"/>
          </attribute>
          <empty/>
        </group>
        <group>
          <attribute name="fabric_wwn">
            <ref name="wwn"/>
          </attribute>
          <empty/>
        </group>
        <text/>
      </choice>
    </element>
  </define>

  <define name="capability">
    <element name="capability">
      <choice>
        <ref name="capsystem"/>
        <ref name="cappcidev"/>
        <ref name="capusbdev"/>
        <ref name="capusbinterface"/>
        <ref name="capnet"/>
        <ref name="capscsigeneric"/>
        <ref name="capscsihost"/>
        <ref name="capscsitarget"/>
        <ref name="capscsi"/>
        <ref name="capstorage"/>
        <ref name="capdrm"/>
        <ref name="capmdev"/>
        <ref name="capccwdev"/>
        <ref name="capcssdev"/>
        <ref name="capvdpa"/>
        <ref name="capapcard"/>
        <ref name="capapqueue"/>
        <ref name="capapmatrix"/>
      </choice>
    </element>
  </define>

  <define name="capsystem">
    <attribute name="type">
      <value>system</value>
    </attribute>

    <optional>
      <element name="product"><text/></element>
    </optional>

    <element name="hardware">
      <optional>
        <element name="vendor"><text/></element>
      </optional>
      <optional>
        <element name="version"><text/></element>
      </optional>
      <optional>
        <element name="serial"><text/></element>
      </optional>

      <element name="uuid">
        <ref name="UUID"/>
      </element>
    </element>


    <element name="firmware">
      <optional>
        <element name="vendor"><text/></element>
      </optional>
      <optional>
        <element name="version"><text/></element>
      </optional>
      <optional>
        <element name="release_date"><text/></element>
      </optional>
    </element>
  </define>

  <define name="cappcidev">
    <attribute name="type">
      <value>pci</value>
    </attribute>

    <optional>
      <element name="class">
        <data type="string">
          <param name="pattern">0x[0-9a-fA-F]{6}</param>
        </data>
      </element>
    </optional>
    <element name="domain">
      <ref name="unsignedLong"/>
    </element>
    <element name="bus">
      <ref name="unsignedLong"/>
    </element>
    <element name="slot">
      <ref name="unsignedLong"/>
    </element>
    <element name="function">
      <ref name="unsignedLong"/>
    </element>

    <element name="product">
      <attribute name="id">
        <ref name="hexuint"/>
      </attribute>

      <choice>
        <text/>
        <empty/>
      </choice>
    </element>

    <element name="vendor">
      <attribute name="id">
        <ref name="hexuint"/>
      </attribute>

      <choice>
        <text/>
        <empty/>
      </choice>
    </element>

    <optional>
      <element name="capability">
        <attribute name="type">
          <value>phys_function</value>
        </attribute>
        <optional>
          <ref name="address"/>
        </optional>
      </element>
    </optional>

    <optional>
      <element name="capability">
        <attribute name="type">
          <value>virt_functions</value>
        </attribute>
        <optional>
          <attribute name="maxCount">
            <ref name="unsignedInt"/>
          </attribute>
        </optional>
        <zeroOrMore>
          <ref name="address"/>
        </zeroOrMore>
      </element>
    </optional>

    <optional>
      <element name="capability">
        <attribute name="type">
          <choice>
            <value>pci-bridge</value>
            <value>cardbus-bridge</value>
          </choice>
        </attribute>
      </element>
    </optional>

    <optional>
      <ref name="mdev_types"/>
    </optional>

    <optional>
      <ref name="vpd"/>
    </optional>

    <optional>
      <element name="iommuGroup">
        <attribute name="number">
          <ref name="unsignedInt"/>
        </attribute>
        <oneOrMore>
          <ref name="address"/>
        </oneOrMore>
      </element>
    </optional>

    <optional>
      <element name="numa">
        <optional>
          <attribute name="node">
            <data type="int"/>
          </attribute>
        </optional>
      </element>
    </optional>

    <optional>
      <element name="pci-express">
        <zeroOrMore>
          <element name="link">
            <attribute name="validity">
              <choice>
                <value>cap</value>
                <value>sta</value>
              </choice>
            </attribute>
            <optional>
              <attribute name="port">
                <ref name="unsignedInt"/>
              </attribute>
            </optional>
            <optional>
              <attribute name="speed">
                <data type="string">
                  <param name="pattern">[0-9]+(.[0-9]+)?</param>
                </data>
              </attribute>
            </optional>
            <attribute name="width">
              <ref name="unsignedInt"/>
            </attribute>
          </element>
        </zeroOrMore>
      </element>
    </optional>
  </define>

  <define name="capusbdev">
    <attribute name="type">
      <value>usb_device</value>
    </attribute>

    <element name="bus">
      <ref name="unsignedLong"/>
    </element>
    <element name="device">
      <ref name="unsignedLong"/>
    </element>

    <element name="product">
      <attribute name="id">
        <ref name="hexuint"/>
      </attribute>

      <choice>
        <text/>
        <empty/>
      </choice>
    </element>

    <element name="vendor">
      <attribute name="id">
        <ref name="hexuint"/>
      </attribute>

      <choice>
        <text/>
        <empty/>
      </choice>
    </element>
  </define>

  <define name="capusbinterface">
    <attribute name="type">
      <value>usb</value>
    </attribute>

    <element name="number">
      <ref name="unsignedLong"/>
    </element>
    <element name="class">
      <ref name="unsignedLong"/>
    </element>
    <element name="subclass">
      <ref name="unsignedLong"/>
    </element>
    <element name="protocol">
      <ref name="unsignedLong"/>
    </element>

    <optional>
      <element name="description">
        <text/>
      </element>
    </optional>
  </define>

  <define name="capnet">
    <attribute name="type">
      <value>net</value>
    </attribute>

    <element name="interface">
      <text/>
    </element>
    <optional>
      <element name="address">
        <ref name="mac"/>
      </element>
    </optional>
    <ref name="link-speed-state"/>

    <zeroOrMore>
      <element name="feature">
        <attribute name="name">
          <ref name="netfeaturename"/>
        </attribute>
      </element>
    </zeroOrMore>

    <zeroOrMore>
      <ref name="subcapnet"/>
    </zeroOrMore>
  </define>

  <define name="netfeaturename">
    <data type="string">
      <param name="pattern">[a-zA-Z\-_]+</param>
    </data>
  </define>

  <define name="subcapnet">
    <element name="capability">
      <choice>
        <ref name="subcapnet80203"/>
        <ref name="subcapnet80211"/>
      </choice>
    </element>
  </define>

  <define name="subcapnet80203">
    <attribute name="type">
      <value>80203</value>
    </attribute>
  </define>

  <define name="subcapnet80211">
    <attribute name="type">
      <value>80211</value>
    </attribute>
  </define>

  <define name="capsfchost">
    <attribute name="type">
      <value>fc_host</value>
    </attribute>

    <element name="wwnn">
      <ref name="wwn"/>
    </element>

    <element name="wwpn">
      <ref name="wwn"/>
    </element>

    <optional>
      <element name="fabric_wwn">
        <ref name="wwn"/>
      </element>
    </optional>
  </define>

  <define name="capsvports">
    <attribute name="type">
      <value>vport_ops</value>
    </attribute>
    <element name="max_vports">
      <ref name="unsignedInt"/>
    </element>
    <element name="vports">
      <ref name="unsignedInt"/>
    </element>
  </define>

  <define name="capscsigeneric">
    <attribute name="type">
      <value>scsi_generic</value>
    </attribute>

    <element name='char'>
      <text/>
    </element>
  </define>

  <define name="capscsihost">
    <attribute name="type">
      <value>scsi_host</value>
    </attribute>

    <element name="host">
      <ref name="unsignedLong"/>
    </element>

    <optional>
      <element name="unique_id">
        <ref name="unsignedInt"/>
      </element>
    </optional>

    <optional>
      <zeroOrMore>
        <element name="capability">
          <choice>
            <ref name="capsfchost"/>
            <ref name="capsvports"/>
          </choice>
        </element>
      </zeroOrMore>
    </optional>
  </define>

  <define name="capsfcrport">
    <attribute name="type">
      <value>fc_remote_port</value>
    </attribute>

    <element name="rport">
      <text/>
    </element>

    <element name="wwpn">
      <ref name="wwn"/>
    </element>
  </define>

  <define name="capscsitarget">
    <attribute name="type">
      <value>scsi_target</value>
    </attribute>

    <element name="target">
      <text/>
    </element>

    <optional>
      <element name="capability">
        <ref name="capsfcrport"/>
      </element>
    </optional>
  </define>

  <define name="capscsi">
    <attribute name="type">
      <value>scsi</value>
    </attribute>

    <element name="host">
      <ref name="unsignedLong"/>
    </element>
    <element name="bus">
      <ref name="unsignedLong"/>
    </element>
    <element name="target">
      <ref name="unsignedLong"/>
    </element>
    <element name="lun">
      <ref name="unsignedLong"/>
    </element>

    <optional>
      <element name="type">
        <text/>
      </element>
    </optional>
  </define>

  <define name="capstorage">
    <attribute name="type">
      <value>storage</value>
    </attribute>

    <element name="block">
      <ref name="path"/>
    </element>

    <optional>
      <element name="bus">
        <text/>
      </element>
    </optional>
    <optional>
      <element name="drive_type">
        <text/>
      </element>
    </optional>
    <optional>
      <element name="model">
        <text/>
      </element>
    </optional>
    <optional>
      <element name="vendor">
        <text/>
      </element>
    </optional>
    <optional>
      <element name="serial">
        <text/>
      </element>
    </optional>

    <choice>
      <ref name="capstorageremoveable"/>
      <ref name="capstoragefixed"/>
    </choice>

    <optional>
      <element name="capability">
        <attribute name="type">
          <value>hotpluggable</value>
        </attribute>
      </element>
    </optional>
  </define>

  <define name="capstorageremoveable">
    <element name="capability">
      <attribute name="type">
        <value>removable</value>
      </attribute>
      <element name="media_available">
        <choice>
          <value>1</value>
          <value>0</value>
        </choice>
      </element>

      <element name="media_size">
        <ref name="unsignedLong"/>
      </element>
      <optional>
        <element name="media_label">
          <text/>
        </element>
      </optional>
      <ref name="blockData"/>
    </element>
  </define>

  <define name="capstoragefixed">
    <element name="size">
      <ref name="unsignedLong"/>
    </element>
    <ref name="blockData"/>
  </define>

  <define name="blockData">
    <optional>
      <element name="logical_block_size">
        <ref name="unsignedLong"/>
      </element>
      <element name="num_blocks">
        <ref name="unsignedLong"/>
      </element>
    </optional>
  </define>

  <define name="capdrm">
    <attribute name="type">
      <value>drm</value>
    </attribute>
    <element name="type">
      <choice>
        <value>primary</value>
        <value>control</value>
        <value>render</value>
      </choice>
    </element>
  </define>

  <define name="capmdev">
    <interleave>
      <attribute name="type">
        <value>mdev</value>
      </attribute>
      <element name="type">
        <attribute name="id">
          <data type="string"/>
        </attribute>
      </element>
      <optional>
        <element name="iommuGroup">
          <attribute name="number">
            <ref name="unsignedInt"/>
          </attribute>
        </element>
      </optional>
      <optional>
        <element name="uuid">
          <ref name="UUID"/>
        </element>
      </optional>
      <optional>
        <element name="parent_addr">
          <data type="string"/>
        </element>
      </optional>
      <zeroOrMore>
        <element name="attr">
          <attribute name="name"/>
          <attribute name="value"/>
        </element>
      </zeroOrMore>
    </interleave>
  </define>

  <define name="capccwaddress">
    <element name="cssid">
      <ref name="ccwCssidRange"/>
    </element>
    <element name="ssid">
      <ref name="ccwSsidRange"/>
    </element>
    <element name="devno">
      <ref name="ccwDevnoRange"/>
    </element>
  </define>

  <define name="capccwdev">
    <attribute name="type">
      <value>ccw</value>
    </attribute>
    <ref name="capccwaddress"/>
  </define>

  <define name="capcssdev">
    <attribute name="type">
      <value>css</value>
    </attribute>
    <ref name="capccwaddress"/>
    <optional>
      <element name="channel_dev_addr">
        <ref name="capccwaddress"/>
      </element>
    </optional>
    <optional>
      <ref name="mdev_types"/>
    </optional>
  </define>

  <define name="capvdpa">
    <attribute name="type">
      <value>vdpa</value>
    </attribute>
    <element name="chardev">
      <ref name="path"/>
    </element>
  </define>

  <define name="capapcard">
    <attribute name="type">
      <value>ap_card</value>
    </attribute>
    <element name="ap-adapter">
      <ref name="uint8"/>
    </element>
  </define>

  <define name="capapqueue">
    <attribute name="type">
      <value>ap_queue</value>
    </attribute>
    <element name="ap-adapter">
      <ref name="uint8"/>
    </element>
    <element name="ap-domain">
      <ref name="apDomainRange"/>
    </element>
  </define>

  <define name='capapmatrix'>
    <attribute name='type'>
      <value>ap_matrix</value>
    </attribute>
    <optional>
      <ref name="mdev_types"/>
    </optional>
  </define>

  <define name="address">
    <element name="address">
      <attribute name="domain"><ref name="hexuint"/></attribute>
      <attribute name="bus"><ref name="hexuint"/></attribute>
      <attribute name="slot"><ref name="hexuint"/></attribute>
      <attribute name="function"><ref name="hexuint"/></attribute>
    </element>
  </define>

  <define name="mac">
    <data type="string">
      <param name="pattern">([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}</param>
    </data>
  </define>

  <define name="path">
    <data type="string">
      <param name="pattern">/[a-zA-Z0-9_\+\-/%]+</param>
    </data>
  </define>

  <define name="mdev_types">
    <element name="capability">
      <attribute name="type">
        <value>mdev_types</value>
      </attribute>
      <oneOrMore>
        <element name="type">
          <attribute name="id">
            <data type="string"/>
          </attribute>
          <optional>
            <element name="name"><text/></element>
          </optional>
          <element name="deviceAPI">
            <choice>
              <value>vfio-pci</value>
              <value>vfio-ccw</value>
              <value>vfio-ap</value>
            </choice>
          </element>
          <element name="availableInstances">
            <ref name="unsignedInt"/>
          </element>
        </element>
      </oneOrMore>
    </element>
  </define>

  <define name="vpd">
    <element name="capability">
      <attribute name="type">
        <value>vpd</value>
      </attribute>
      <element name="name">
        <ref name="vpdFieldValueFormat"/>
      </element>
      <optional>
        <element name="fields">
          <attribute name="access">
            <value>readonly</value>
          </attribute>
          <optional>
            <element name="change_level">
              <ref name="vpdFieldValueFormat"/>
            </element>
          </optional>
          <optional>
            <element name="manufacture_id">
              <ref name="vpdFieldValueFormat"/>
            </element>
          </optional>
          <optional>
            <element name="part_number">
              <ref name="vpdFieldValueFormat"/>
            </element>
          </optional>
          <optional>
            <element name="serial_number">
              <ref name="vpdFieldValueFormat"/>
            </element>
          </optional>
          <zeroOrMore>
            <element name="vendor_field">
              <attribute name="index">
                <ref name="vendorVPDFieldIndex"/>
              </attribute>
              <ref name="vpdFieldValueFormat"/>
            </element>
          </zeroOrMore>
        </element>
      </optional>
      <optional>
        <element name="fields">
          <attribute name="access">
            <value>readwrite</value>
          </attribute>
          <optional>
            <element name="asset_tag">
              <ref name="vpdFieldValueFormat"/>
            </element>
          </optional>
          <zeroOrMore>
            <element name="vendor_field">
              <attribute name="index">
                <ref name="vendorVPDFieldIndex"/>
              </attribute>
              <ref name="vpdFieldValueFormat"/>
            </element>
          </zeroOrMore>
          <zeroOrMore>
            <element name="system_field">
              <attribute name="index">
                <ref name="systemVPDFieldIndex"/>
              </attribute>
              <ref name="vpdFieldValueFormat"/>
            </element>
          </zeroOrMore>
        </element>
      </optional>
    </element>
  </define>

  <define name="apDomainRange">
    <choice>
      <data type="string">
        <param name="pattern">0x[0-9a-fA-F]{1,4}</param>
      </data>
      <data type="int">
        <param name="minInclusive">0</param>
        <param name="maxInclusive">255</param>
      </data>
    </choice>
  </define>

  <define name="vpdFieldValueFormat">
    <data type="string">
      <param name="pattern">[0-9a-zA-F -_,.:;=]{0,255}</param>
    </data>
  </define>

  <define name="vendorVPDFieldIndex">
    <data type="string">
      <param name="pattern">[0-9A-Z]{1}</param>
    </data>
  </define>

  <define name="systemVPDFieldIndex">
    <data type="string">
      <param name="pattern">[0-9B-Z]{1}</param>
    </data>
  </define>

</grammar>
