8139too.c (2)

Linux カーネル解析入門の 259p から 261p のあたり、最近の実装では手続き呼び出しの痕跡さえありません。
ちなみに rtl8139_init_one 手続きの中に以下な記述があります。

	ioaddr = tp->mmio_addr;
	assert (ioaddr != NULL);

	addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6;
	for (i = 0; i < 3; i++)
		((__le16 *) (dev->dev_addr))[i] =
		    cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len));
	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);

EEPROM から mac アドレスを読み出して云々してる処理。この処理で使われている ioaddr は priv な属性の mmio_addr 属性が根拠らしいのですが、これを設定していると思われる rtl8139_init_board 手続きを確認してみます。

rtl8139_init_board 手続き

mmio_addr 属性を云々しているのは以下な記述になっている模様。

	ioaddr = pci_iomap(pdev, bar, 0);
	if (!ioaddr) {
		dev_err(d, "cannot map %s\n", res[bar].type);
		if (!use_io) {
			use_io = true;
			goto retry;
		}
		rc = -ENODEV;
		goto err_out;
	}
	tp->regs_len = io_len;
	tp->mmio_addr = ioaddr;

pci_iomap 手続きは lib/pci_iomap.c で定義されてます。ここで

  • pci_resource_* とか
  • IORESOURCE_* とか
  • ioremap 手続きとか

駆使されてますね。全部引用してしまえ。

void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
{
	resource_size_t start = pci_resource_start(dev, bar);
	resource_size_t len = pci_resource_len(dev, bar);
	unsigned long flags = pci_resource_flags(dev, bar);

	if (!len || !start)
		return NULL;
	if (maxlen && len > maxlen)
		len = maxlen;
	if (flags & IORESOURCE_IO)
		return __pci_ioport_map(dev, start, len);
	if (flags & IORESOURCE_MEM) {
		if (flags & IORESOURCE_CACHEABLE)
			return ioremap(start, len);
		return ioremap_nocache(start, len);
	}
	/* What? */
	return NULL;
}

これ、呼び出す前に pci_request_regions 手続きを呼び出しておく必要があるのだろうな、と思ったらその通りでした。これ、struct net_device 型の mmio_addr 属性に設定するナニはこの手続きを使う、という理解で良いのかな。

pci_iomap は掘っておくべきな気がしてます。あと、rtl8139_init_board あたりも色々確認を、ということで。