lspci.c
virtual 変数がセットされたとき、[virtualが表示される]
static void
show_rom(struct device *d, int reg)
{
...
if (virtual)
printf(" [virtual]");
virtual変数は初期値0
int virtual = 0;
virtual変数が1に設定される条件は、以下を全て満たすこと
- regが0以上
- romのPCI_ROM_ADDRESS_MASKビットが有効
- flgのPCI_ROM_ADDRESS_MASKビットが無効
- ioflgのPCI_IORESOURCE_PCI_EA_BEIが無効
if (reg >= 0 && (rom & PCI_ROM_ADDRESS_MASK) && !(flg & PCI_ROM_ADDRESS_MASK) && !(ioflg & PCI_IORESOURCE_PCI_EA_BEI))
{
flg = rom;
virtual = 1;
}
条件1. regが0以上
regはshow_romの第2引数
PCIヘッダタイプ0の場合は、PCI_ROM_ADDRESS 0x30
#define PCI_ROM_ADDRESS 0x30
static void
show_htype0(struct device *d)
{
show_bases(d, 6, 0);
show_rom(d, PCI_ROM_ADDRESS);
show_caps(d, PCI_CAPABILITY_LIST);
}
条件2. romのPCI_ROM_ADDRESS_MASKビットが有効
romは第1引数d から辿れる rom_base_addr変数
struct pci_dev *p = d->dev;
pciaddr_t rom = p->rom_base_addr;
rom_base_addrはsysfs_get_resroucesで取得する
static void
sysfs_get_resources(struct pci_dev *d)
{
else if (i == 6)
{
d->rom_flags = flags;
flags &= PCI_ADDR_FLAG_MASK;
d->rom_base_addr = start | flags;
d->rom_size = size;
have_rom_base = 1;
}
PCI_ROM_ADDRESS_MASKビットは下位11ビットをクリア
(romのPCI_ROM_ADDRESS_MASKビットが有効とは、12ビット以上が0ではないこと)
#define PCI_ROM_ADDRESS_MASK (~(pciaddr_t)0x7ff)
条件3. flgのPCI_ROM_ADDRESS_MASKビットが無効(12ビット以上が0)
今回reg>0なので、flgはget_conf_longで取得する
u32 flg = reg >= 0 ? get_conf_long(d, reg) : ioflg_to_pciflg(ioflg);
u32
get_conf_long(struct device *d, unsigned int pos)
{
check_conf_range(d, pos, 4);
return d->config[pos] |
(d->config[pos+1] << 8) |
(d->config[pos+2] << 16) |
(d->config[pos+3] << 24);
}
config値は、PCIコンフィグレーション空間の値を保持している?
/*** PCI devices and access to their config space ***/
struct device {
struct device *next;
struct pci_dev *dev;
/* Bus topology calculated by grow_tree() */
struct device *bus_next;
struct bus *parent_bus;
struct bridge *bridge;
/* Cache */
int no_config_access;
unsigned int config_cached, config_bufsize;
byte *config; /* Cached configuration space data */
byte *present; /* Maps which configuration bytes are present */
};
条件4. ioflgのPCI_IORESOURCE_PCI_EA_BEIが無効
#define PCI_IORESOURCE_PCI_EA_BEI (1<<5)
ioflgは、p->known_fieldsのPCI_FILL_IO_FLAGSビットが有効であれば、p->rom_flags値
pciaddr_t ioflg = (p->known_fields & PCI_FILL_IO_FLAGS) ? p->rom_flags : 0;
#define PCI_FILL_IO_FLAGS 0x1000
PCI_FILL_IO_FLAGSビットが有効だと[enhanced]が表示される
if (ioflg & PCI_IORESOURCE_PCI_EA_BEI)
printf(" [enhanced]");
[disabled] 表示条件
if (!(flg & PCI_ROM_ADDRESS_ENABLE))
printf(" [disabled]");
else if (!virtual && !(cmd & PCI_COMMAND_MEMORY))
printf(" [disabled by cmd]");
#define PCI_ROM_ADDRESS_ENABLE 0x01
virtual=1 がセットされるとき、flg = rom
virtual=0 のとき、PCI Expantion ROM addressレジスタ値
u32 flg = reg >= 0 ? get_conf_long(d, reg) : ioflg_to_pciflg(ioflg);
show_rom関数全体
static void
show_rom(struct device *d, int reg)
{
struct pci_dev *p = d->dev;
pciaddr_t rom = p->rom_base_addr;
pciaddr_t len = (p->known_fields & PCI_FILL_SIZES) ? p->rom_size : 0;
pciaddr_t ioflg = (p->known_fields & PCI_FILL_IO_FLAGS) ? p->rom_flags : 0;
u32 flg = reg >= 0 ? get_conf_long(d, reg) : ioflg_to_pciflg(ioflg);
word cmd = reg >= 0 ? get_conf_word(d, PCI_COMMAND) : PCI_COMMAND_MEMORY;
int virtual = 0;
if (!rom && !flg && !len)
return;
if (reg >= 0 && (rom & PCI_ROM_ADDRESS_MASK) && !(flg & PCI_ROM_ADDRESS_MASK) && !(ioflg & PCI_IORESOURCE_PCI_EA_BEI))
{
flg = rom;
virtual = 1;
}
printf("\tExpansion ROM at ");
if (rom & PCI_ROM_ADDRESS_MASK)
printf(PCIADDR_T_FMT, rom & PCI_ROM_ADDRESS_MASK);
else if (flg & PCI_ROM_ADDRESS_MASK)
printf("<ignored>");
else
printf("<unassigned>");
if (virtual)
printf(" [virtual]");
if (!(flg & PCI_ROM_ADDRESS_ENABLE))
printf(" [disabled]");
else if (!virtual && !(cmd & PCI_COMMAND_MEMORY))
printf(" [disabled by cmd]");
if (ioflg & PCI_IORESOURCE_PCI_EA_BEI)
printf(" [enhanced]");
show_size(len);
putchar('\n');
}