元器件交易网-中发网全新升级平台
关注我们:
首页 > 技术资料 > 正文

pci卡制作技巧概述

  其实从开始我对pci卡是一窍不通的,硬件还好说,软件驱动程序更是一头雾水,由于我的pci卡是要在windows98操作系统下应用的,所以必须编写pci卡的驱动程序,支持windows98下pnp硬件的驱动程序一般可以编程vxd。如果想为了以后的2k平台兼容就最好编wdm,因为windows2k不支持vxd,而且以后的发展wdm肯定要代替vxd了。不过由于我找到的资料基本上都是介绍vxd的,感觉vxd的技术好像更成熟一点,编的人更多一点,所以偷了一下懒(惭愧),就没有去研究wdm,就选择了vxd。

  我的pci卡其实很简单,仅仅在本地端接了一个遥测信号的处理系统。

  先说说硬件吧,其实按照正常的pci卡开发过程,仔细阅读pci规范是很重要的,但是由于时间比较短,我也没有很大的耐性看那些破规范,也就稍稍了解了一下。现在市场上有许多的专用的pci规范接口芯片,这些芯片提供的pci接口完全符合规范,具体符合的规范版本可以参看具体的芯片所以即使开发者不是很了解规范的具体细则,也可成功的设计pci卡。也就是可以达到傻瓜及设计。在连线上只要将对应的引脚连在总线上就可以了,在连线时要注意pci规范中提到了信号用的反射波信号,所以驱动的信号只用了要求电压的一半,另一半靠反射来提升。所以对信号线的长度有要求:64位卡的32位信号具备的最大连线长度是1500mil,64位扩展信号的附加信号的连线长度最大为2000mil,pci clk的长度为2500mil+/-100mil,如果不够长度可以多绕几圈。

  还有一个要注意的是pci信号中prsnt1和prsnt2,开始我对这两个信号一直不是很清楚,清华bbs上的精华区说得也是含糊,后来师兄devilface告诉我的prsnt1和prsnt2两者必须有一个接gnd,否则系统肯定找不到卡,主板就是靠这两个信号来判断这个插槽上是否有卡,而其接法同pci卡使用的功率有关具体的含义如下(0 表示悬空,1表示接地):

  prsnt1 prsnt2 含义

  0 0 no card

  0 1 15w

  1 0 25w

  1 1 7.5w

  另外pci卡上最好在从槽上引的电源上多加几个电容,所有电源都必须退藕一般规范推荐pci卡做4层板,但是我只做了2层,其实无所谓,只要2层布得开,没必要布4层,不过我布线的时候还是费了一点功夫,用specctra布了5,6次,为研究室节省开支嘛!(要是导师看见了该多感动呀!)

  找到了pci卡的配置空间后,读出space0的基地址,然后进行物理地址到线性地址的转换,我又偷了懒,vtools提供的example中有实现此功能的vxd源代码,直接用vc++编译成vxd就可以共win app使用了。所以实际上我的app程序使用了两个vxd,一个用来专门找卡,一个用来地址转换。

 

  至于app如何调用vxd,可以参看vc的参考书,一般都有介绍。

  下面将一下如何安装vxd到系统中,我编的vxd都是动态加载的(pnp一般都用动态加载vxd)要编写一个inf文件以便系统将vxd安装进去。我用的是windriver生成的inf文件模板,然后再按照需要进行修改,自然加上我的大名了。编完了inf文件后,就可以安装了。一般情况如果你插上pci卡windows启动后就会发现新硬件,你只要按照以前安装硬件的步骤进行就可以了只是在选择安装文件时选择自己编写的inf文件就可以了。我觉得一般的安装过程就是将vxd文件拷入系统的文件夹,即windows目录下,以便当app加载vxd时,系统可以找到vxd程序,进行动态加载。

  下面是我的inf文件

  :

  [Version]

  Signature=ICAGO$ ;必须这么写

  Class=PLX ;可以自己改

  Provider=%SHENLI% ;制作者

  [Manufacturer]

  %Manufacture%=SECTION0

  [SECTION0]

  %my_card%=my.install,PCIVEN_10b5&DEV_9050 ;my.install表示了安装过程所要做的事,

  [my.install]

  CopyFiles=CopyFiles_PLX10b5 ;主要做拷贝文件和注册表添加

 

  AddReg=AddReg_PLX10b5

  [CopyFiles_PLX10b5]

  Vxd8_25.vxd

  [AddReg_PLX10b5]

  HKR,,DevLoader,0,Vxd8_25.vxd

  [Strings]

  Manufacture="BUAA202" ;这些信息会在安装时显示

  my_card="PLX9052"

  下面提供了vxd中查询pci卡的代码,这个代码是参考清华bbs驱动版精华区huyuguang大虾的大作,他提供了更详细的代码

  有兴趣可以参考。

  BOOL findpci(DWORD DeviceVendor,PCIINF *pciinf)//我的卡的DeviceVendor=0x905210b5

  {

  DWORD io_cf8;

  DWORD io_cfc;

  int i;

  DWORD buf[16];

  io_cf8=0x80000000;

  for(;;)

  {

  DWORD_OUT(0xcf8,io_cf8);//向0xcf8输出双字 io_cf8

  io_cfc=DWORD_IN(0xcfc); //从0xcfc读入双字

 

  if(io_cfc==DeviceVendor)//find pci9052

  {

  for(i=0;i<16;i++)

  {

  DWORD_OUT(0xcf8,io_cf8+4*i);

  buf[i]=DWORD_IN(0xcfc);

  }

  pciinf->VendorID=(WORD)(buf[0]&0xffff);

  pciinf->DeviceID=(WORD)((buf[0]&0xffff0000)/0x10000);

  pciinf->Command=(WORD)(buf[1]&0xffff);

  pciinf->Status=(WORD)((buf[1]&0xffff0000)/0x10000);

  pciinf->RevisionID=(UCHAR)(buf[2]&0xff);

  pciinf->CacheLineSize=(UCHAR)(buf[3]&0xff);

  pciinf->LatencyTimer=(UCHAR)((buf[3]&0xff00)/0x100);

  pciinf->HeaderType=(UCHAR)((buf[3]&0xff0000)/0x10000);

  pciinf->BIST=(UCHAR)((buf[3]&0xff000000)/0x1000000);

  pciinf->BaseAddresses[0]=buf[4];

  pciinf->BaseAddresses[1]=buf[5];

  pciinf->BaseAddresses[2]=buf[6];

  pciinf->BaseAddresses[3]=buf[7];

  pciinf->BaseAddresses[4]=buf[8];

  pciinf->BaseAddresses[5]=buf[9];

  pciinf->SubsystemVendorID=(USHORT)(buf[11]&0xffff);

  pciinf->SubsystemID=(USHORT)((buf[12]&0xffff0000)/0x10000);

 

  pciinf->InterruptLine=(UCHAR)(buf[15]&0xff);

  pciinf->InterruptPin=(UCHAR)((buf[15]&0xff00)/0x100);

  pciinf->MinimumGrant=(UCHAR)((buf[15]&0xff0000)/0x10000);

  pciinf->MaximumLatency=(UCHAR)((buf[15]&0xff000000)/0x1000000);

  break;

  }

  else

  io_cf8+=0x800;

  if(io_cf8>=0x80ffff00)

  return 1;

  }

  return 0;

  }

  还有很多不清楚的地方,写出来只是想让感兴趣的pci门外汉了解一下,但愿能有所帮助。肯定有很多错误,希望各位大虾指正,但求不会误人子弟。

  • 微笑
  • 流汗
  • 难过
  • 羡慕
  • 愤怒
  • 流泪