PCI resource management

PCI resource management
这部分主要完成azx chip 特定的construtor/destructor,以及PCI entries.

首先这里涉及到几个重要的函数:
struct azx{}
static int azx_free(struct azx *chip)
statci int azx_create(…) //azx芯片特定的constructor

azx_create(struct snd_card *card,
							  struct pci_dev *pci,
		     				  int dev, 
		     				  unsigned int driver_caps,
		     				  const struct hda_controller_ops *hda_ops,
		      				  struct azx **rchip)

下面讲解函数azx_create()里的主要内容

err = pci_enable_device(pci)
这个函数是初始化PCI entry
**hda = kzalloc(sizeof(hda), GFP_KERNEL);
这一句对应《write alsa》里的chip = kzalloc(sizeof(chip),GFP_KERNEL)那是不是就说明这里的hda 就对应 文档里面的chip
后面怎么又来一句:chip = &hda->chip???
position 相关
err = snd_device_new()
然后发现 write alsa driver文档中的snd_mychio_create()函数里面关于PCI相关的几个函数都在 hda_intel.c的azx_first_init()函数中,是不是说明这个函数就是用来设置pci resource相关内容的,主要函数有以下几个:

err = pci_request_regions(pci, “ICH HD audio”);
这是PCI resource的一个allocation,这里的ICH HD audio就是 My Chip,
chip->addr = pci_resource_start(pci, 0);
这里的addr就是文档里面提到的IO Port address
pci_set_dma_mask(pci, DMA_BIT_MASK(32));
check PCI availability

关于resource allocation的一些主要内容

关于I/O port address & irqs的分配是通过内核标准函数来完成的,现假设这个PCI device有一个8 byte的IO Port , 以及一个interrupt,在struct azx{}里面会有如下几个项:struct snd_card *card, unsigned long addr(这个就是IO port addr), int irq;
对于一个IO Port(addr)来说,我们需要有一个resource pointer来指向标准的resource management, 关于port address 以及resource pointer会自动通过kzalloc()来初始化,不需要我们重置;
对于一个irq来说,需要有一个独立的irq number, 在实际的分配之前,先要初始化该值为-1,0值表示有效。

I/O port的分配一般如下所示

	err = pci_request_regions(pci, "ICH HD audio");
	if (err < 0)
		return err;
	chip->region_requested = 1;
		chip->addr = pci_resource_start(pci, 0);
	chip->remap_addr = pci_ioremap_bar(pci, 0);
	if (chip->remap_addr == NULL) {
		dev_err(card->dev, "ioremap error\n");
		return -ENXIO;
	}

中断资源的分配在azx_acquire_irq()中
if (request_irq(pci->irq, snd_mychip_interrupt,IRQF_SHARED, KBUILD_MODNAME, chip))

	if (request_irq(chip->pci->irq, azx_interrupt,
			chip->msi ? 0 : IRQF_SHARED,
			KBUILD_MODNAME, chip)) {
		dev_err(chip->card->dev,
			"unable to grab IRQ %d, disabling device\n",
			chip->pci->irq);
		if (do_disconnect)
			snd_card_disconnect(chip->card);
		return -1;
	}
	chip->irq = chip->pci->irq;

在pci bus上,interrupts 可以被shared,所以 IRQF_SHARED 被用来当作request_irq()的中断标志

memory-mapped region的管理和IO port部分的管理差不多

struct mychip {
        ....
        unsigned long iobase_phys;
        void __iomem *iobase_virt;
};
and the allocation would be like below:
if ((err = pci_request_regions(pci, "My Chip")) < 0) {
        kfree(chip);
        return err;
}
chip->iobase_phys = pci_resource_start(pci, 0);
chip->iobase_virt = ioremap_nocache(chip->iobase_phys,
                                    pci_resource_len(pci, 0));
and the corresponding destructor would be:
static int snd_mychip_free(struct mychip *chip)
{
        ....
        if (chip->iobase_virt)
                iounmap(chip->iobase_virt);
        ....
        pci_release_regions(chip->pci);
        ....
}

在azx chip中的表示如下

	unsigned long addr;
	void __iomem *remap_addr;


chip->addr = pci_resource_start(pci, 0);
	chip->remap_addr = pci_ioremap_bar(pci, 0);

PCI Entries
就是一些pci_device_id 和一些device table。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值