开发者社区> hopegrace> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

35、PCI设备驱动简介

简介: PCI(Peripheral Component Interconnect)总线标准是一种将系统外部设备连接起来的总线标准,速度可以达到133MB/s,它是PC中最重要的总线,其他总路线如ISA总线,USB总线等,都挂载在PCI总线上(通过桥接电路)。
+关注继续查看

PCI(Peripheral Component Interconnect)总线标准是一种将系统外部设备连接起来的总线标准,速度可以达到133MB/s,它是PC中最重要的总线,其他总路线如ISA总线,USB总线等,都挂载在PCI总线上(通过桥接电路)。由Intel推出的一种局部总线,为32位数据地址总线,可以扩展为64位,支持突发读写,及多组外围设备。

PCI系统中,Host/PCI称为北桥,连接主处理器总线到基础PCI局部总线;PCI-ISA桥称为南桥,连接基础PCI总线到ISA总线。其中南桥通常还含有中断控制器,IDE控制器,USB控制器和DMA控制器等设备。

wps_clip_image-27502

图示 P412

PCI有三个相互独立的物理地址空间:设备存储器地址空间,I/O地址空间和配置空间。由于PCI支持设备即插即用,所以PCI设备不占用固定的内存地址空间或I/O地址空间,而是可以由操作系统决定其映射的基址。

PCI总线规范定义的配置Hha总长度为256个字节,配置信息按一定的顺序和大小依次存放。根据读取PCI配置空间,可以得到PCI设备的所有资源。[1]中讲述了多种读取PCI配置空间的方法,包括通过最基本的I/O端口操作进行读取,通过DDK提供的函数HalGetBusData,HalSetBusDataNT式驱动中进行读取,在WDM驱动中的读取方法,等。

一般程序所看到的内存指针都是虚拟内存,如果想操作物理内存,必须使用DDK提供的内核函数WRITE_REGISTER_XX,READ_REGISTER_XX系列函数。

MmAllocateContiguousMemory分配连续的物理地址,MmGetPhysicalAddress得到连续的物理内存地址。

代码

#pragma PAGEDCODE
NTSTATUS InitMyPCI(IN PDEVICE_EXTENSION pdx,IN PCM_PARTIAL_RESOURCE_LIST list)
{
PDEVICE_OBJECT fdo
= pdx->fdo;

ULONG vector;
KIRQL irql;
KINTERRUPT_MODE mode;
KAFFINITY affinity;
BOOLEAN irqshare;
BOOLEAN gotinterrupt
= FALSE;

PHYSICAL_ADDRESS portbase;
BOOLEAN gotport
= FALSE;

PCM_PARTIAL_RESOURCE_DESCRIPTOR resource
= &list->PartialDescriptors[0];
ULONG nres
= list->Count;
BOOLEAN IsMem0
= TRUE;
for (ULONG i = 0; i < nres; ++i, ++resource)
{
// for each resource
switch (resource->Type)
{
// switch on resource type
case CmResourceTypePort:
portbase
= resource->u.Port.Start;
pdx
->nports = resource->u.Port.Length;
pdx
->mappedport = (resource->Flags & CM_RESOURCE_PORT_IO) == 0;
gotport
= TRUE;
break;

case CmResourceTypeMemory:
if (IsMem0)
{
pdx
->MemBar0 = (PUCHAR)MmMapIoSpace(resource->u.Memory.Start,
resource
->u.Memory.Length,
MmNonCached);
pdx
->nMem0 = resource->u.Memory.Length;
IsMem0
= FALSE;
}
else
{
pdx
->MemBar1 = (PUCHAR)MmMapIoSpace(resource->u.Memory.Start,
resource
->u.Memory.Length,
MmNonCached);
pdx
->nMem1 = resource->u.Memory.Length;
}

break;

case CmResourceTypeInterrupt:
irql
= (KIRQL) resource->u.Interrupt.Level;
vector
= resource->u.Interrupt.Vector;
affinity
= resource->u.Interrupt.Affinity;
mode
= (resource->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
? Latched : LevelSensitive;
irqshare
= resource->ShareDisposition == CmResourceShareShared;
gotinterrupt
= TRUE;

break;

default:
KdPrint((
"Unexpected I/O resource type %d\n", resource->Type));
break;
}
// switch on resource type
} // for each resource

if (!(TRUE&& gotport&& gotinterrupt ))
{
KdPrint((
" Didn't get expected I/O resources\n"));
return STATUS_DEVICE_CONFIGURATION_ERROR;
}

if (pdx->mappedport)
{
// map port address for RISC platform
pdx->portbase = (PUCHAR) MmMapIoSpace(portbase, pdx->nports, MmNonCached);
if (!pdx->mappedport)
{
KdPrint((
"Unable to map port range %I64X, length %X\n", portbase, pdx->nports));
return STATUS_INSUFFICIENT_RESOURCES;
}
}
// map port address for RISC platform
else
pdx
->portbase = (PUCHAR) portbase.QuadPart;

NTSTATUS status
= IoConnectInterrupt(&pdx->InterruptObject, (PKSERVICE_ROUTINE) OnInterrupt,
(PVOID) pdx, NULL, vector, irql, irql, LevelSensitive, TRUE, affinity, FALSE);
if (!NT_SUCCESS(status))
{
KdPrint((
"IoConnectInterrupt failed - %X\n", status));
if (pdx->portbase && pdx->mappedport)
MmUnmapIoSpace(pdx
->portbase, pdx->nports);
pdx
->portbase = NULL;
return status;
}

#define IMAGE_LENGTH (640*480)
//申请一段连续物理地址来读取图像
PHYSICAL_ADDRESS maxAddress;
maxAddress.u.LowPart
= 0xFFFFFFFF;
maxAddress.u.HighPart
= 0;

pdx
->MemForImage = MmAllocateContiguousMemory(IMAGE_LENGTH,maxAddress);

PHYSICAL_ADDRESS pycialAddressForImage
= MmGetPhysicalAddress(pdx->MemForImage);

WRITE_REGISTER_BUFFER_UCHAR((PUCHAR)pdx
->MemBar0+0x10000,
(PUCHAR)
&pycialAddressForImage.u.LowPart,4);

return STATUS_SUCCESS;
}

 

示例代码 P428

参考

[1] Windows 驱动开发技术详解,张帆

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
1.5 PCI-X总线简介
<div class="bct fc05 fc11 nbw-blog ztag"> <p style="TEXT-INDENT: 21pt;"><span lang="EN-US" xmllang="EN-US">PCI-X</span><span style="FONT-FAMILY: 宋体;">总线仍采用并行总线技术。</span><span lang="EN-US" xmllang="
1026 0
第1章 PCI总线的基本知识
<div class="bct fc05 fc11 nbw-blog ztag"> <p style="TEXT-INDENT: 21pt;"><span lang="EN-US" xmllang="EN-US">PCI</span><span style="FONT-FAMILY: 宋体;">总线作为处理器系统的局部总线,主要目的是为了连接外部设备,而不是作为处理器的系统总线连接</spa
973 0
第I篇PCI体系结构概述
<div class="bct fc05 fc11 nbw-blog ztag"><span lang="EN-US" xmllang="EN-US"> <p style="TEXT-INDENT: 21pt;"><span lang="EN-US" xmllang="EN-US">PCI</span><span style="FONT-FAMILY: 宋体;">总线作为处理器系统的局部总线
1218 0
LDD3学习笔记(15):PCI驱动
 #include  包含 PCI 寄存器的符号名和几个供应商和设备 ID 值的头文件. struct pci_dev; 表示内核中一个 PCI 设备的结构.
633 0
38、其它设备驱动
关于RS-232,485等系列的驱动编写,类似于USB等,见[1]。 摄像头驱动程序 WDM摄像头驱动程序分两部分,一部分是类驱动(Class Driver)程序,由MS提供,提供了标准接口,一部分是小驱动(Mini Driver)程序,用户编写。
504 0
37、SDIO设备驱动
SD(Secure Digital Memory Card)IO卡是在SD内存卡接口基础之上发展起来的接口。SDIO协议类似于USB总线协议。 和USB总路线类似,SDIO总路线也有两端,一端是HOST端,另外一端是DEVICE端,所有指令都是由HOST端发出指令开始,在DEVICE端只要能解析HOST的命令,就可以和HOST进行通信。
677 0
PCI设备驱动开发
 PCI设备驱动开发 1. PCI 简介     PCI 总线标准是一种将系统外部设备连接起来的总线标准,是 PC 中最重要的总线,实际上是系统的各个部分如何交互的接口。
784 0
+关注
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载