PCI总线信号详解:模块间信息交换的关键

需积分: 1 3 下载量 95 浏览量 更新于2024-07-12 收藏 596KB PPT 举报
在第六章《微机原理》中,PCI总线信号是讨论的重点内容。PCI (Peripheral Component Interconnect) 总线是一种模块级内部扩展总线,在PC系列微机中被广泛应用。它提供了一种高效的数据传输方式,支持32位和64位数据传输,以及多种控制线,如C/BE(控制/地址),AD(地址/数据),PAR/FRAME(参数/帧),中断线,以及系统信号线如CLK(时钟)、TRDY(传输就绪)等。 PCI总线信号包括了接口控制线、中断线、Cache支持线、JTAG/边界扫描信号线,以及地址和数据线,这些线路上的信号负责设备间的通信和同步。其中,控制线如REQ(请求)、GNT(应答)、ACK64(64位确认)、LOCK(锁定)等在数据传输过程中起着关键作用,确保数据的正确传输和同步。中断线INTA、INTB、INTC、INTD则允许外部设备向CPU发送中断请求,以便进行处理。 PCI总线采用仲裁机制来决定哪个设备有权访问总线,这可能涉及到TRDY(发送就绪)、IRDY(接收就绪)、STOP(停止)和DEVSEL/IDSEL(设备选择)等信号。当设备试图访问总线时,它会发送一个请求信号,然后通过仲裁确定是否被授予使用权。此外,PERR(错误指示)和SERR(严重错误)用于报告总线错误,而SBO、TDI/TDO、TCK/TMS等信号则是数据传输的时钟和数据线,用于实现数据的双向传输。 在微机系统中,总线操作是一个核心概念,包括总线周期和指令周期的关系。总线操作由四个阶段组成:总线请求和仲裁、寻址、数据传输和结束。每个阶段都有特定的信号控制流程,确保系统的稳定性和效率。通过这些复杂的信号交互,PCI总线使得计算机系统内的不同模块能够协同工作,提升整体性能。 PCI总线是微机系统中不可或缺的一部分,它定义了设备间通信的规则和标准,优化了数据传输效率,并通过严格的信号控制实现了多设备之间的同步和资源共享。理解并掌握PCI总线信号及其工作原理对于深入学习微机原理和系统设计至关重要。

static void nvme_calc_irq_sets(struct irq_affinity *affd, unsigned int nrirqs) { struct nvme_dev *dev = affd->priv; unsigned int nr_read_queues, nr_write_queues = dev->nr_write_queues; if (!nrirqs) { nrirqs = 1; nr_read_queues = 0; } else if (nrirqs == 1 || !nr_write_queues) { nr_read_queues = 0; } else if (nr_write_queues >= nrirqs) { nr_read_queues = 1; } else { nr_read_queues = nrirqs - nr_write_queues; } dev->io_queues[HCTX_TYPE_DEFAULT] = nrirqs - nr_read_queues; affd->set_size[HCTX_TYPE_DEFAULT] = nrirqs - nr_read_queues; dev->io_queues[HCTX_TYPE_READ] = nr_read_queues; affd->set_size[HCTX_TYPE_READ] = nr_read_queues; affd->nr_sets = nr_read_queues ? 2 : 1; }static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues) { struct pci_dev *pdev = to_pci_dev(dev->dev); struct irq_affinity affd = { //ָ���ж��׺��Եļ��㷽���Ͳ��� .pre_vectors = 1, .calc_sets = nvme_set_irq_affinity, //nvme_calc_irq_sets, .priv = dev, }; unsigned int irq_queues, poll_queues; poll_queues = min(dev->nr_poll_queues, nr_io_queues - 1); dev->io_queues[HCTX_TYPE_POLL] = poll_queues; dev->io_queues[HCTX_TYPE_DEFAULT] = 1; dev->io_queues[HCTX_TYPE_READ] = 0; irq_queues = 1; if (!(dev->ctrl.quirks & NVME_QUIRK_SINGLE_VECTOR)) irq_queues += (nr_io_queues - poll_queues); return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues, PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd); } 在 Linux 5.17.12 内核版本中,如何修改 pci_alloc_irq_vectors_affinity() 函数的 affinity_hint 参数来绑定 NVMe 驱动的所有 I/O 队列到同一 CPU 核心上。代码展示

2023-06-09 上传

static void nvme_calc_irq_sets(struct irq_affinity *affd, unsigned int nrirqs) { struct nvme_dev *dev = affd->priv; unsigned int nr_read_queues, nr_write_queues = dev->nr_write_queues; if (!nrirqs) { nrirqs = 1; nr_read_queues = 0; } else if (nrirqs == 1 || !nr_write_queues) { nr_read_queues = 0; } else if (nr_write_queues >= nrirqs) { nr_read_queues = 1; } else { nr_read_queues = nrirqs - nr_write_queues; } dev->io_queues[HCTX_TYPE_DEFAULT] = nrirqs - nr_read_queues; affd->set_size[HCTX_TYPE_DEFAULT] = nrirqs - nr_read_queues; dev->io_queues[HCTX_TYPE_READ] = nr_read_queues; affd->set_size[HCTX_TYPE_READ] = nr_read_queues; affd->nr_sets = nr_read_queues ? 2 : 1; }static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues) { struct pci_dev *pdev = to_pci_dev(dev->dev); struct irq_affinity affd = { //ָ���ж��׺��Եļ��㷽���Ͳ��� .pre_vectors = 1, .calc_sets = nvme_set_irq_affinity, //nvme_calc_irq_sets, .priv = dev, }; unsigned int irq_queues, poll_queues; poll_queues = min(dev->nr_poll_queues, nr_io_queues - 1); dev->io_queues[HCTX_TYPE_POLL] = poll_queues; dev->io_queues[HCTX_TYPE_DEFAULT] = 1; dev->io_queues[HCTX_TYPE_READ] = 0; irq_queues = 1; if (!(dev->ctrl.quirks & NVME_QUIRK_SINGLE_VECTOR)) irq_queues += (nr_io_queues - poll_queues); return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues, PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd); } 在 Linux 5.17.12 内核版本中,可以通过修改 pci_alloc_irq_vectors_affinity() 函数的 affinity_hint 参数来绑定 NVMe 驱动的所有 I/O 队列到同一 CPU 核心上。

2023-06-09 上传