一、故事前传
前面的文章针对PCIe的一部分内容已经做了解析。
较为详细解释请见之前的文章:
1. PCIe技术概述;
2.0~2.8 PCIe事务层详细解析;
3.0~3.2 PCIe数据链路层详细解析;
4.0~4.1 PCIe物理层解析;
5. PCIe电源管理;
6. PCIe系统复位方式;
二、热插拔(Hot-Plug)
当你准备在不断电的情况下插拔一块PCIe SSD时,你要小心了。如果在PCIe设备不支持热插拔的条件下,很可能会对主板或PCIe插槽造成损毁。
为了放置意外的发生,PCIe Spec设计了一种"No Surprise"热插拔机制,即,当用户要插拔PCIe设备时,必须先通知系统软件做好准备,然后通过指示灯告知用户热插拔的状态。
PCIe环境下的热插拔需要软件与硬件的通力合作。先来看一张示意图,红色框内属于软件方面的需求,绿色框内是硬件方面的需求。

软件方面主要包括:
User Interface: 这部分由系统OS提供。主要允许用户可以请求插拔PCIe设备。
Hot-Plug Service: 这部分也是由系统OS提供。主要负责处理用户插拔PCIe设备的请求。
Standardized Hot Plug System Driver: 这部分驱动可以由系统OS或者主板提供。
Device Driver: 这部分主要有适配卡提供。
硬件方面主要包括:
Hot-Plug Controller: 主要负责接收和处理来自Hot Plug System Driver的指令。
Card Slot Power Switching Logic: 主要被Hot Plug Controller控制,用于turn-on/off电源。
Card Reset Logic: 按照Hot-plug System Driver的指示,Hot Plug Controller向需要插拔PCIe设备的插槽(Slot)传送PERST#信号。
Power Indicator: 主要负责指示设备连接器上面的电源状态。
Attention Indicator: 这个是警示灯,提醒用户热插拔失败状态,所以一般情况下处于关闭状态。
Card Present Detect Pins: PCIe设计了两个用于检测PCIe设备是否存在的信号PRSNT1#和PRSNT2#。 PRSNT#1接地,当PCIe设备存在时,PRSNT#2拉高。
在介绍PCIe设备插拔的过程前,我们先了解一下PCIe插槽的On/Off状态:
PCIe Slot ON:
PCIe Slot OFF:
断电;
RefClk参考时钟关闭;
PCIe链路是关闭状态或;
PERST#信号处于有效状态。
如果要调整Slot上的状态,步骤如下:
PCIe Slot ON转为OFF:
PCIe Slot OFF转为ON:
先上电;
其次,打开RefClk参考时钟;
然后,解除slot上PERST#信号。
在PCIe slot上面插拔PCIe设备的步骤是什么呢?
移除PCIe设备:
初始状态是:Attention Indicator(Yellow)-Off,Power Indicator(Green)-On
步骤是:
用户通过压下Attention按钮或者在软件界面告知系统移除PCIe设备的消息。当按下Attention按钮之后,Hot-Plug Controller检查到这个讯息之后,会发送中断给Root Complex。之后,Hot-Plug Service会调用Hot-Plug System Driver去读取slot的状态信息并且侦测到Attention按钮的状态;
Hot-Plug Service调用Hot-Plug System Driver让Power指示灯开始闪烁5s并通过状态寄存器来验证热插拔的请求;
Hot-Plug Service命令Device Driver停用PCIe设备;
软件通过Link Control Register关闭PCIe链路;
软件命令Hot-Plug Controller关闭slot;
断电后,Power指示灯处于OFF状态;
系统为PCIe设备寻找对应的驱动,并将驱动放入内存;
系统取消对Slot的配置资源。
插入PCIe设备:
初始状态是:Attention Indicator(Yellow)-Off,Power Indicator(Green)-Off
步骤是:
用户安装PCIe设备,并且压下Attention按钮或者在软件界面告知系统安装PCIe设备的信息。主要通过发送中断的形式告知系统热插拔信息;
热插拔软件通过状态寄存器来验证热插拔的请求;
软件命令Power指示灯开始闪烁;
软件命令Hot-Plug Controller将Slot打开,让Slot处于ON状态;
上电后,Power指示灯处于ON状态;
系统为PCIe设备寻找对应的驱动,并将驱动放入内存;
系统调用驱动完成对PCIe设备的初始化。