lspci Expantion Rom の [vurtual][disable]表示条件

lspci.c
virtual 変数がセットされたとき、[virtualが表示される]

```lspci.c
static void
show_rom(struct device *d, int reg)
{
...
  if (virtual)
    printf(" [virtual]");
```


virtual変数は初期値0
```
  int virtual = 0;
```
　
#### virtual変数が1に設定される条件は、以下を全て満たすこと
1. regが0以上
1. romのPCI_ROM_ADDRESS_MASKビットが有効
1. flgのPCI_ROM_ADDRESS_MASKビットが無効
1. 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の第２引数
PCIヘッダタイプ0の場合は、PCI_ROM_ADDRESS 0x30
```
#define PCI_ROM_ADDRESS 0x30
```
```lspci.c
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ビット以上が０ではないこと)
```lib/header.h
#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);
```

```lspci.c
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コンフィグレーション空間の値を保持している？
```lspci.c
/*** 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;
```

```pci.h
#define PCI_FILL_IO_FLAGS 0x1000
```

PCI_FILL_IO_FLAGSビットが有効だと[enhanced]が表示される
```
  if (ioflg & PCI_IORESOURCE_PCI_EA_BEI)
      printf(" [enhanced]");
```


## [disabled] 表示条件

```lspci.c
  if (!(flg & PCI_ROM_ADDRESS_ENABLE))
    printf(" [disabled]");
  else if (!virtual && !(cmd & PCI_COMMAND_MEMORY))
    printf(" [disabled by cmd]");
```
```lib/header.h
#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関数全体
```lspci.c
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');
}