<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>中文 &#187; linuxdrivers</title>
	<atom:link href="http://software.intel.com/zh-cn/blogs/author/linuxdrivers/feed/" rel="self" type="application/rss+xml" />
	<link>http://software.intel.com/zh-cn/blogs</link>
	<description></description>
	<lastBuildDate>Sat, 26 May 2012 06:34:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>浅谈 PCI 设备驱动</title>
		<link>http://software.intel.com/zh-cn/blogs/2010/09/09/pci/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2010/09/09/pci/#comments</comments>
		<pubDate>Thu, 09 Sep 2010 10:06:23 +0000</pubDate>
		<dc:creator>linuxdrivers</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[移动技术]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2010/09/09/pci/</guid>
		<description><![CDATA[要弄清楚PCI设备驱动，首先要明白，所谓的PCI设备驱动实际包括PCI设备驱动和设备本身驱动两部分；这里着重于PCI设备驱动，会在最后列出一段包含设备本身驱动的示例代码，仅供参考。 一、概述及简介 PCI有三种地址空间：PCI I/O空间、PCI内存地址空间和PCI配置空间。其中，PCI I/O空间和PCI内存地址空间由设备驱动程序使用，而PCI配置空间由Linux内核中的PCI初始化代码使用，这些代码用于配置PCI设备，比如中断号以及I/O或内存基地址。对于写Linux设备驱动来说，要大致了解Linux内核已经帮我们做了哪些工作，而我们要完成的是哪些工作，后者就是我们写驱动时要完成的工作。所以这里的PCI设备驱动就是要大致描述对于PCI设备驱动，Linux内核都帮我们做了什么，接着就是我们应该完成什么。 (1)Linux内核做了什么 简单的说，Linux内核主要就做了对PCI设备的枚举和配置；这些工作都是在内核初始时完成的。 枚举：对于PCI总线，可以通过一个叫做PCI桥的设备连接到一条PCI总线。CPU通过宿主--PCI桥与一条PCI总线相连，处在这种位置上的PCI总线称为主总线。这样，通过PCI-PCI桥，就构筑起了一个层次的、树状的PCI系统结构(主总线是根)。 所谓枚举，就是从宿主--PCI桥开始进行探测和扫描，逐个“枚举”连接在第一条PCI总线上的所有设备并记录在案。如果其中的某个设备是PCI-PCI桥，则又进一步再探测和扫描连在这个桥上的次级PCI总线。就这样递归下去，直到穷尽系统中的所有PCI设备。其结果，是在内存中建立起一棵代表着这些PCI总线和设备的PCI树。 配置：PCI设备中一般都带有一些RAM和ROM 空间，通常的控制/状态寄存器和数据寄存器也往往以RAM区间的形式出现，这些地址都要先映射到系统总线上，在进一步映射到内核的虚拟地址空间。而所谓的配置就是通过对PCI配置空间的寄存器进行操作从而完成地址的映射。 (2)内核怎么做的 这里首先要说明的是，对于PCI的设备初始化(即上面提到的枚举和配置工作)，BIOS和Linux内核都可以做。一般而言，只要是采用PCI总线的PC机，其BIOS就必须提供对PCI总线操作的支持，因而称为PCI BIOS。而且最早Linux内核也是通过这种BIOS调用的方式来获取系统中的PCI设备信息的，只不过现在改由自己动手了。 二、开始我们的枚举与配置之路 注：为了更清晰，简单的描述PCI设备的初始化过程(因为2.4.18中还没有引入设备驱动模型，这样可以让我们专心研究PCI设备驱动本身)。这里是对Linux-2.4.18的内核进行的分析。主要原因大家从参考资料中也应该能明白，这里很多就是参考了[1]中的资料来分析的。如果想学PCI设备驱动，那么应该好好看看[1]的第八章中的PCI总线一节。然后再能找到一个驱动的例子代码看看，就可以说算是对PCI设备驱动入门了，当然，前提是都看懂了 呵呵。 废话少说，下面进入正题。前面提到了PCI有三种地址空间，其中的PCI配置空间是给Linux内核中的PCI初始化代码用的，也就是我们这里的枚举与配置时用到的。那么这个PCI配置空间里放的是什么东西呢，显然应该是寄存器，称为配置寄存器组。 PCI标准规定每个设备的配置寄存器组最多可以有256字节的连续空间，其中开头的64字节的用途和格式是标准的，称为配置寄存器的头部。而64字节头部中的16个字节中又包含着有关头部的类型、设备的种类、设备的一些性质、由谁制造等等信息。根据这16个字节中提供的信息，来确定应该怎样进一步解释和处理剩余头部中的48个字节。这里有个问题要先说清楚，就是这些寄存器的地址问题，不然往后就进行不下去了。 MSI(Message Signal Interrupt) BAR(Base Address Register) 参考资料： [1] Linux源代码情景分析(下册) [2]Linux设备驱动开发详解 [3]Linux设备驱动(第三版) [4]内核Documentation下的pci.txt [5]精通Linux设备驱动开发]]></description>
			<content:encoded><![CDATA[<p>要弄清楚PCI设备驱动，首先要明白，所谓的PCI设备驱动实际包括PCI设备驱动和设备本身驱动两部分；这里着重于PCI设备驱动，会在最后列出一段包含设备本身驱动的示例代码，仅供参考。</p>
<p>一、概述及简介</p>
<p>PCI有三种地址空间：PCI I/O空间、PCI内存地址空间和PCI配置空间。其中，PCI I/O空间和PCI内存地址空间由设备驱动程序使用，而PCI配置空间由Linux内核中的PCI初始化代码使用，这些代码用于配置PCI设备，比如中断号以及I/O或内存基地址。对于写Linux设备驱动来说，要大致了解Linux内核已经帮我们做了哪些工作，而我们要完成的是哪些工作，后者就是我们写驱动时要完成的工作。所以这里的PCI设备驱动就是要大致描述对于PCI设备驱动，Linux内核都帮我们做了什么，接着就是我们应该完成什么。</p>
<p>(1)Linux内核做了什么</p>
<p>简单的说，Linux内核主要就做了对PCI设备的枚举和配置；这些工作都是在内核初始时完成的。</p>
<p>枚举：对于PCI总线，可以通过一个叫做PCI桥的设备连接到一条PCI总线。CPU通过宿主--PCI桥与一条PCI总线相连，处在这种位置上的PCI总线称为主总线。这样，通过PCI-PCI桥，就构筑起了一个层次的、树状的PCI系统结构(主总线是根)。 所谓枚举，就是从宿主--PCI桥开始进行探测和扫描，逐个“枚举”连接在第一条PCI总线上的所有设备并记录在案。如果其中的某个设备是PCI-PCI桥，则又进一步再探测和扫描连在这个桥上的次级PCI总线。就这样递归下去，直到穷尽系统中的所有PCI设备。其结果，是在内存中建立起一棵代表着这些PCI总线和设备的PCI树。</p>
<p>配置：PCI设备中一般都带有一些RAM和ROM 空间，通常的控制/状态寄存器和数据寄存器也往往以RAM区间的形式出现，这些地址都要先映射到系统总线上，在进一步映射到内核的虚拟地址空间。而所谓的配置就是通过对PCI配置空间的寄存器进行操作从而完成地址的映射。</p>
<p>(2)内核怎么做的</p>
<p>这里首先要说明的是，对于PCI的设备初始化(即上面提到的枚举和配置工作)，BIOS和Linux内核都可以做。一般而言，只要是采用PCI总线的PC机，其BIOS就必须提供对PCI总线操作的支持，因而称为PCI BIOS。而且最早Linux内核也是通过这种BIOS调用的方式来获取系统中的PCI设备信息的，只不过现在改由自己动手了。<br />
<img src="http://p.blog.csdn.net/images/p_blog_csdn_net/fengyv/2.jpg" alt="" /><br />
二、开始我们的枚举与配置之路</p>
<p>注：为了更清晰，简单的描述PCI设备的初始化过程(因为2.4.18中还没有引入设备驱动模型，这样可以让我们专心研究PCI设备驱动本身)。这里是对Linux-2.4.18的内核进行的分析。主要原因大家从参考资料中也应该能明白，这里很多就是参考了[1]中的资料来分析的。如果想学PCI设备驱动，那么应该好好看看[1]的第八章中的PCI总线一节。然后再能找到一个驱动的例子代码看看，就可以说算是对PCI设备驱动入门了，当然，前提是都看懂了 呵呵。</p>
<p>废话少说，下面进入正题。前面提到了PCI有三种地址空间，其中的PCI配置空间是给Linux内核中的PCI初始化代码用的，也就是我们这里的枚举与配置时用到的。那么这个PCI配置空间里放的是什么东西呢，显然应该是寄存器，称为配置寄存器组。</p>
<p>PCI标准规定每个设备的配置寄存器组最多可以有256字节的连续空间，其中开头的64字节的用途和格式是标准的，称为配置寄存器的头部。而64字节头部中的16个字节中又包含着有关头部的类型、设备的种类、设备的一些性质、由谁制造等等信息。根据这16个字节中提供的信息，来确定应该怎样进一步解释和处理剩余头部中的48个字节。这里有个问题要先说清楚，就是这些寄存器的地址问题，不然往后就进行不下去了。<br />
<img src="http://hi.csdn.net/attachment/201005/10/0_1273499366G4Ni.gif" alt="" /></p>
<p>MSI(Message Signal Interrupt)</p>
<p>BAR(Base Address Register)</p>
<p>参考资料：</p>
<p>[1] Linux源代码情景分析(下册)</p>
<p>[2]Linux设备驱动开发详解</p>
<p>[3]Linux设备驱动(第三版)</p>
<p>[4]内核Documentation下的pci.txt</p>
<p>[5]精通Linux设备驱动开发</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2010/09/09/pci/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

