一、前言
在之前的内容中,我们已经对PCI有了一些基本的认识,我们了解了PCI的一般架构,标准传输周期等相关的内容,接下来我们会进一步了解PCI具体的传输模型和传输机制。
二、PCI传输模型
PCI一共有三种数据传输模型,分别是:Programmed I/O(PIO),Peer-to-Peer和DMA。
2.1 Programmed I/O(PIO)
PIO在PC早期非常常用,因为设计者不愿意增加设备的成本或复杂度以实现复杂的事务管理逻辑。当时,处理器的速度比任何其他设备都要快,因此在这种模型中,CPU负责处理所有工作。例如,如果PCI设备通过中断通知CPU需要将数据写入内存,CPU会从PCI设备读取数据到内部寄存器中,然后将寄存器中的数据复制到内存中。相反,如果需要将数据从内存移动到PCI设备,软件会指示CPU从内存读取数据到内部寄存器中,然后将寄存器中的数据写入PCI设备。
尽管这种方式有效,但由于两个原因效率低下。首先,每次数据传输时,CPU都会生成两个总线周期(一次用于读,一次用于写)。其次,CPU忙于处理数据传输的管理工作,而无法执行其他更有意义的任务。在早期,这种方式是最快的数据传输方法,因为单任务处理器没有太多其他任务要处理。然而,在现代系统中,这种效率低下的方式通常不可接受,因此这种方法已经不再常用于数据传输,取而代之的是更为高效的直接内存访问(DMA)。
尽管如此,PIO仍然是软件与设备交互的必要事务模型,尤其是在一些低层次的设备初始化和配置操作中。
2.2 DMA
直接内存访问(DMA)是一种更高效的数据传输方式。在这种模型中,一个称为DMA引擎的设备负责代表处理器处理内存到外围设备的传输,从而减轻了处理器的负担。一旦CPU为DMA引擎设置了起始地址和字节数,DMA引擎便独立处理总线协议和地址序列。这种方法不需要对PCI外围设备做出任何改变,因此外围设备能够保持低成本的设计。后来,随着技术的进步,一些外围设备能够本地集成DMA功能,因而不再需要外部DMA引擎。这些设备可以自主处理总线传输,称为总线控制器(Bus Master)设备。
DMA方法比PIO更高效,因为在数据传输过程中,CPU不需要参与,并且一次总线周期就足以传输一个数据块。这样不仅释放了CPU的处理能力,还减少了总线传输的开销,提升了系统性能。
2.3 Peer-to-Peer
如果一个设备能够充当总线控制器(Bus Master),那么就有了另一种有趣的选项:一个PCI总线控制器可以启动向另一个PCI设备的传输,整个事务都保持在PCI总线内部进行,不涉及任何其他系统资源。由于这类事务发生在系统中被视为对等设备之间,因此称为点对点(peer-to-peer)事务。
这种传输方式有明显的效率优势,因为系统的其他部分可以继续执行其他任务而不受影响。然而,在实际应用中这种方式很少使用,原因是发起设备和目标设备通常不会使用相同的数据格式,除非它们是由同一厂商生产的。因此,数据通常必须先传输到内存,经过CPU重新格式化后,再传输给目标设备。这种处理方式破坏了点对点传输的初衷,降低了效率,因此点对点传输在实际中较为罕见。
2.4 小结
编程输入输出(PIO):在这种模式下,CPU通过显式的指令来控制数据的传输。CPU负责从设备读取数据或将数据写入设备。这种方法简单,但由于CPU直接参与数据传输,效率较低且会占用大量CPU资源。
点对点(Peer-to-peer):点对点模式允许两个PCI设备之间直接交换数据,而无需通过主存或CPU。这个模型在多设备通信的场景下非常高效,因为它减少了数据传输路径上的瓶颈,尤其是在多个高带宽设备(如显卡、网络接口卡)之间进行数据交换时。
直接内存访问(DMA):DMA是一种高效的模型,设备可以直接与系统内存交换数据,而无需CPU参与。这种方式允许设备在后台传输数据,同时CPU可以处理其他任务,因此在高性能系统中广泛使用。
这三种模型为不同的应用场景提供了灵活的选择,确保了PCI总线在数据传输中的高效性和适应性。
三、PCI延时事务协议
3.1 PCI重试协议
PCI主设备发起一个访问目标设备的事务。且目标设备没有准备好时,目标设备发出事务重试信息。
在这个例子中,北桥发起了一次内存读取事务,目的是从以太网设备中读取数据。以太网设备作为目标设备认领了总线周期,但此时它并没有立即准备好返回数据给北桥(作为总线控制器)。此时,以太网设备有两种选择来延迟数据传输。
第一种选择是:在数据阶段插入等待状态(wait-states)。如果仅需要插入少量的等待状态,数据传输仍然能够高效完成。然而,如果目标设备需要更多时间(超过事务开始后的16个时钟周期),那么第二种选择是:通过一个称为STOP#的信号通知进行重试。重试会告诉总线控制器结束当前的总线周期而不传输数据,这样可以避免总线在等待状态中被长时间占用,从而提高总线的使用效率。
当目标设备发出重试信号后,总线控制器必须至少等待两个时钟周期,并再次进行总线仲裁以重新发起相同的总线周期。在这个过程中,仲裁器可以将总线分配给其他请求的总线控制器,以更有效地利用PCI总线。等到被重试的总线控制器重新获得总线使用权并重新启动总线周期时,目标设备可能已经准备好,此时它会认领周期并完成数据传输。如果目标设备仍未准备好,它将再次重试总线控制器的总线周期,整个过程会重复,直到总线控制器成功完成数据传输为止。
这种机制通过重试和等待状态的结合,确保了当设备未准备好时总线不会被长时间占用,从而优化了总线的利用率。
3.2 PCI连接断开协议
PCI断开协议规定,当PCI总线控制器发起访问目标设备的事务时,如果目标设备能够传输至少一个双字的数据,但无法完成整个数据传输,它会在无法继续传输的时刻断开事务。这一情景在图1-8中进行了说明。
例如,北桥发起了一次突发内存读取事务,目的是从以太网设备中读取数据。以太网目标设备认领了总线周期并传输了部分数据,但随后由于数据不足而无法继续传输。此时,以太网设备有两种选择来延迟数据传输。
第一种选择是:在当前数据阶段插入等待状态(wait-states),等待额外的数据到达。如果目标设备仅需要插入少量的等待状态,数据仍然可以有效地传输。然而,如果目标设备需要更长的时间(PCI规范允许在数据阶段最多插入8个时钟周期的等待状态),则目标设备必须发出断开信号。它通过在总线周期中间断言STOP#信号,通知总线控制器提前结束该总线周期。断开操作意味着一些数据已经成功传输,而重试则完全没有传输任何数据。断开操作能够防止总线被长时间的等待状态占用,从而释放总线资源。
被断开的总线控制器必须至少等待两个时钟周期,然后再次进行总线仲裁,以继续从断开的地址处继续总线周期。在此期间,仲裁器可以将总线分配给其他请求的总线控制器,以提高PCI总线的利用效率。当断开的总线控制器再次获得总线并继续总线周期时,目标设备此时可能已经准备好继续传输数据,直到传输完成。如果目标设备仍未准备好,它会再次重试或断开总线控制器的总线周期,整个过程会重复,直到总线控制器成功传输所有数据为止。
这种断开协议在需要长时间等待数据时,能够有效地提高总线利用率,避免系统资源被无效的等待状态占用。
四、PCI中断处理
PCI中断处理采用四条旁带中断信号(INTA#、INTB#、INTC#或INTD#)中的一条,向系统发送中断请求。当某一引脚被断言时,在单CPU系统中,中断控制器会通过断言INTR(中断请求)引脚向CPU发出中断信号。随后,CPU会响应中断请求并处理相应的任务。
随着多CPU设计的发展,单线中断输入的方式变得不足,因此引入了APIC(高级可编程中断控制器)模型。在APIC模型中,控制器通过发送中断消息给多个CPU,而不是仅仅向某一个CPU断言INTR引脚。这种方式提升了多CPU系统的中断处理能力。
无论是哪种中断传递模型,被中断的CPU都需要确定中断的来源并处理中断。在传统的中断模型中,完成这个过程需要多个总线周期,效率较低。APIC模型在处理效率上有所改进,但仍有进一步提升的空间。这种改进的中断处理方式尤其在多处理器系统中更为有效,减少了中断响应时间,并提高了系统的整体性能。
五、PCI错误处理
PCI设备在事务期间可以选择检测并报告地址和数据阶段的奇偶校验错误。PCI通过PAR信号在大多数信号上生成偶校验。这意味着,如果在地址或数据阶段传输的信号位数为奇数,主设备将设置PAR信号,使奇偶校验结果为偶数。目标设备接收地址或数据后,会检查是否存在错误。
奇偶校验错误仅在一定情况下可检测到,即当奇数个信号受到干扰,导致接收到的“1”位数为奇数时。若设备检测到数据阶段的奇偶校验错误,它将断言PERR#(奇偶校验错误)信号。对于一些场景(如内存读取),这种错误可能是可恢复的,因为只需重复一次事务,可能就能解决问题。
然而,PCI本身并不包含任何自动或基于硬件的恢复机制,因此错误恢复必须由软件来处理。这意味着,当发生奇偶校验错误时,系统依赖于软件的干预来判断如何重复事务或采取其他措施以纠正错误。
然而,如果在地址阶段检测到奇偶校验错误,情况会有所不同。在这种情况下,地址已经被损坏,可能导致错误的目标设备识别了该地址。由于无法确定损坏的地址变成了什么,也无法得知总线上其他设备对该地址的响应,因此无法进行简单的恢复。因此,发生这种类型的错误时,会断言SERR#(系统错误)引脚,通常会触发系统错误处理程序。
在早期的计算机中,这种错误通常会作为一种预防措施导致系统停止运行,出现著名的“蓝屏死机”。在早期机器中,PERR#和SERR#信号都连接到南桥中的错误逻辑处理单元。为了简化设计并降低成本,这通常会导致向CPU发送NMI(不可屏蔽中断信号),从而系统往往会停止运行,以避免进一步的损害或数据丢失。
这种设计在处理严重错误时提供了一定的保护,但也带来了系统突然中断的副作用,使得用户不得不面对系统崩溃。随着技术的发展,现代系统对这些错误处理机制进行了优化,减少了系统完全停止的情况。