#!/bin/bash

###############################################################################
#
# lsvfio: lsuio equivalent for vfiouser devices
#

while read _vfio_dev; do

    # show the PCI device
    _pci_dev="${_vfio_dev#*@}"
    _pci_desc=$(lspci -s ${_pci_dev})
    [ -z "${_pci_desc}" ] && continue
    echo ${_vfio_dev}
    echo ${_pci_desc#* }

    # collect the IRQs assigned to the device
    _dev_dir="/sys/bus/pci/devices/${_pci_dev}"
    if [ -d ${_dev_dir}/msi_irqs ]; then
        _irqs=${_dev_dir}/msi_irqs/*
    else
        _irqs=$(cat ${_dev_dir}/irq 2>/dev/null)
    fi

    # show the IRQ count(s)
    for _irq in ${_irqs}; do
        _irq=${_irq##*/}
        _irql=$(grep -o "^ *${_irq}:[ 0-9]*" /proc/interrupts)
        _count=0
        for _i in ${_irql#*:}; do _count=$((${_count}+${_i})); done
        echo "	IRQ ${_irq}: ${_count}"
    done

    # show the memory regions
    while read _bar; do
        echo "	${_bar/Memory at/Bus address:}"
        _bar=${_bar#* at }
        _bar=${_bar%% *}
        # and the user-space mappings
        while read -a _map; do
            echo "	${_map[@]/maps:/maps: }"
        done < <(grep -H " ${_bar} .*vfio-device" /proc/*/maps 2>/dev/null)
    done < <(lspci -vs ${_pci_dev} | grep "^	Memory at")

    echo

done < <(for _dev in /dev/vfio/*@*:*:*\.*; do
             [ -h ${_dev} ] || continue
             echo "${_dev##*/}"
         done | sort -k 2 -t @)

