📄 程序示例-pci初始化5.htm
字号:
1硬件连接使能.<BR>*/<BR></STRONG></P></BLOCKQUOTE>
<BLOCKQUOTE>
<BLOCKQUOTE>
<BLOCKQUOTE>
<P><STRONG>//PTM1LA 0xEF400034, PTM1_LOCAL_ADRS
0x00000000</STRONG></P>
<P>sysPciOutLong(PTM1LA, PTM1_LOCAL_ADRS);</P>
<P><STRONG>//PTM1MS 0xEF400030, </STRONG></P>
<P>sysPciOutLong(PTM1MS,
PTM1_SIZE_ATTRIB);<BR><BR>...................</P></BLOCKQUOTE></BLOCKQUOTE>
<P><STRONG>/*<BR>* 写 405GP PCI 设置寄存器.<BR>* 使能 405GP,使其成为PCI总线的一个master
(PMM).<BR>* 使能 405GP 作为一个PCI memory target (PTM).<BR>*/</STRONG></P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<P>temp_short = pciConfigIn(PPC405GP_PCI_BUSDEVFUNC, PCI_CFG_COMMAND,
2);<BR>temp_short = temp_short | PCI_CMD_MASTER_ENABLE |
PCI_CMD_MEM_ENABLE;<BR>pciConfigOut(PPC405GP_PCI_BUSDEVFUNC,
PCI_CFG_COMMAND, temp_short,
2);<BR><BR>..........................<BR></P></BLOCKQUOTE></BLOCKQUOTE>
<P><STRONG>/*<BR>* 作为PCI的主机host扫描PCI总线,查找PCI设备. 并为每个设备分配唯一的PCI或I/O地址*
空间<BR>*/</STRONG></P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<P>pciScan(0);<BR>return;<BR>}</P>
<P> </P></BLOCKQUOTE></BLOCKQUOTE></BLOCKQUOTE>
<P><STRONG>//pciScan() - 扫描PCI总线,根据PCI ID和 vender ID查找设置现有的PCI设备</STRONG></P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<BLOCKQUOTE>
<P>void pciScan<BR>(<BR>int
busNum <BR>)<BR>{<BR>int
Device;<BR>int BusDevFunc;</P></BLOCKQUOTE></BLOCKQUOTE>
<P><BR><BR><STRONG>/*<BR>* 从device 1开始,查找每个Slot,如有PCI设备,分配内存和I/O, 405GP是
device 0.<BR>*/</STRONG></P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<P><BR>for (Device = 1; Device <= WALNUT_NUM_PCI_SLOTS;
Device++)<BR>{<BR>BusDevFunc = (busNum << 16) | (Device <<
11);</P>
<P><STRONG>//如果Device存在<BR></STRONG>if (pciConfigIn(BusDevFunc,
PCI_CFG_VENDOR_ID,2) != 0xFFFF) <BR>{<BR>#ifdef PCIDEBUG<BR>printf("* * *
* * * * * * * * * * * * * *\n");<BR>printf("Device %d is
present\n",Device);<BR>#endif<BR>switch( pciConfigIn(BusDevFunc,
PCI_CFG_SUBCLASS, 2) )<BR>{<BR><BR>case
0x0604: <STRONG>/*
PCI-PCI Bridge
*/</STRONG><BR>break;<BR><BR>default:<BR>pciDumpDevice(BusDevFunc);
<STRONG>//打印 Vendor ID, Device
ID</STRONG></P></BLOCKQUOTE></BLOCKQUOTE></BLOCKQUOTE>
<BLOCKQUOTE>
<P><STRONG>//调用pciConfigDevice(BusDevFunc, 6)对PCI设备进行设置<BR></STRONG></P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<P>pciConfigDevice(BusDevFunc, 6);<BR>}<BR>}<BR>else<BR>{<BR>#ifdef
PCIDEBUG<BR>printf("Device %d not
present\n",Device);<BR>#endif<BR>}<BR>}<BR>}</P></BLOCKQUOTE></BLOCKQUOTE></BLOCKQUOTE>
<P><STRONG>//pciConfigDevice - 为PCI设备配置内存和I/O方式</STRONG></P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<BLOCKQUOTE>
<P>void pciConfigDevice(int BusDevFunc,int NumBaseAddr)<BR>{<BR>int
AddrSlot;<BR>int i;<BR>unsigned long AddrDesc;<BR>unsigned long
AddrProg;<BR>unsigned long Min_Gnt_Val;<BR></P>
<P><STRONG>// NumBaseAddr = 6<BR></STRONG>for (AddrSlot = 0; AddrSlot <
NumBaseAddr; AddrSlot++)<BR>{</P>
<P><STRONG>// PCI_CFG_BASE_ADDRESS_0 = 0x10 将0xFFFFFFFF写入
PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot)<BR></STRONG>pciConfigOut(BusDevFunc,
PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot),<BR>0xFFFFFFFF, 4);</P>
<P><STRONG>// 从PCI_CFG_BASE_ADDRESS_0 +
(4*AddrSlot)读出数据<BR></STRONG>AddrDesc =
pciConfigIn(BusDevFunc,<BR>PCI_CFG_BASE_ADDRESS_0 +
(4*AddrSlot),<BR>4);<BR></P>
<P><STRONG>// 如果数据是0,没有PCI设备,继续循环搜索<BR></STRONG>if (AddrDesc == 0) /*
unimplemented, stop looking */<BR>continue;<BR><BR>#ifdef
PCIDEBUG<BR>printf("Read Base Addr Reg %d =
0x%08x\n",AddrSlot,AddrDesc);<BR>#endif<BR><STRONG>/*
如果AddrDesc的位0是0,表示是Mem方式 */</STRONG><BR>if ((AddrDesc & 1) == 0)
<BR>{<BR>AddrDesc &= 0xFFFFFFF0;<BR><BR>for (i = 0; (AddrDesc & 1)
!= 1; i++) <STRONG>//查询Mem的大小</STRONG><BR>AddrDesc =
AddrDesc >> 1;<BR><BR>AddrDesc = 1 << i;<BR><BR>if ((unsigned
long)AddrDesc < 4096)<BR>AddrDesc = 4096;<BR>#ifdef
PCIDEBUG<BR>printf(" PCI Memory space = 0x%x bytes
\n",AddrDesc);<BR>#endif<BR>for (AddrProg = PCI_MEMORY_START;<BR>AddrProg
< LowestMemAddr;<BR>AddrProg +=
AddrDesc);<BR><BR>pciConfigOut(BusDevFunc, PCI_CFG_BASE_ADDRESS_0 +
(4*AddrSlot),<BR>AddrProg, 4);<BR>LowestMemAddr = AddrProg +
AddrDesc;<BR>}<BR>else
<STRONG>/* I/O 方式*/</STRONG><BR>{<BR>AddrDesc &=
0xFFFFFFFC;<BR><BR>for (i = 0; (AddrDesc & 1) != 1;
i++) <STRONG>//查询I/O空间的大小</STRONG><BR>AddrDesc =
AddrDesc >> 1;<BR><BR>AddrDesc = 1 << i;<BR>#ifdef
PCIDEBUG<BR>printf(" PCI I/O space = 0x%x bytes
\n",AddrDesc);<BR>#endif<BR>for (AddrProg =
PCI_IO_REGION_1_START;<BR>AddrProg < LowestIOAddr;<BR>AddrProg +=
AddrDesc);<BR><BR>pciConfigOut(BusDevFunc, PCI_CFG_BASE_ADDRESS_0 +
(4*AddrSlot),<BR>AddrProg, 4);<BR>LowestIOAddr = AddrProg +
AddrDesc;<BR>}<BR><BR>}<BR><BR><BR>/*<BR>* Read Min_Gnt(0x3eh) register
value and write it to<BR>* the Latency Timer(0xdh)
register<BR>*/<BR>Min_Gnt_Val = 0x80;<BR>pciConfigOut(BusDevFunc,
PCI_CFG_LATENCY_TIMER, Min_Gnt_Val,
1);<BR><BR>}</P></BLOCKQUOTE></BLOCKQUOTE></BLOCKQUOTE>
<P><FONT
color=#0000ff><STRONG><BIG><BIG>2.PCI网卡驱动调用过程</BIG></BIG></STRONG></FONT></P>
<BLOCKQUOTE>
<P><BIG><STRONG>sysNet.c用于初始化系统的网络</STRONG></BIG></P>
<P><BIG><STRONG>文件sysNet.c中void sysNetHwInit(void)定义了,这里以AMD
PCI网卡97x为例:</STRONG></BIG></P>
<BLOCKQUOTE>
<P>#ifdef INCLUDE_PCI_NETWORK<BR> unsigned char
sysEnetAddr [6]; <STRONG>/* 网卡的 MAC 地址 */</STRONG><BR>
char sys97xLoadString[100]; <STRONG>/* 需要为初始化加载的字符串
*/</STRONG><BR>#endif</P>
<P>#ifdef INCLUDE_PCI_NETWORK<BR> STATUS
sysIn97xEndBldLoadStr() <STRONG>//
生成网络初始化的字符串</STRONG><BR></P></BLOCKQUOTE>
<P><STRONG>函数sysIn97xEndBldLoadStr()调用pciFindDevice()</STRONG></P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<P>STATUS pciFindDevice <STRONG>//用Vendor ID和Device
ID查找PCI网卡</STRONG><BR>(<BR>int VendorID,<BR>int DeviceID,<BR>int
index,<BR>int *busDevFunc<BR>)<BR>{<BR>int Device;<BR>int
tmpBusDevFunc;<BR>int tmpIndex;<BR>int busNum;<BR><BR>tmpIndex = 0;<BR>for
(busNum = MaxBusNum; busNum >= 0; busNum--)
<STRONG>//查讯Slot</STRONG><BR>{<BR>for (Device = 0; Device <=
WALNUT_NUM_PCI_SLOTS; Device++)<BR>{<BR>tmpBusDevFunc = (busNum <<
16) | (Device << 11);</P></BLOCKQUOTE>
<P><STRONG>// 如果指定寄存器中Vendor ID和Device ID正确,赋值给*busDevFunc,返回</STRONG></P>
<BLOCKQUOTE>
<P>if (pciConfigIn(tmpBusDevFunc, PCI_CFG_VENDOR_ID, 2) ==
VendorID<BR>&& pciConfigIn(tmpBusDevFunc, PCI_CFG_DEVICE_ID, 2) ==
DeviceID)<BR>{<BR>if (tmpIndex == index)<BR>{<BR>*busDevFunc =
tmpBusDevFunc;<BR>return (OK);<BR>}<BR>else /* have a match, but not
correct index */<BR>{<BR>tmpIndex++;<BR>}<BR>} } }<BR>return (ERROR);
}<BR></P></BLOCKQUOTE></BLOCKQUOTE></BLOCKQUOTE>
<P><STRONG>
sysln97xEndBldLoadStr(..)查找PCI以太网卡,得到PCI网卡的基地址,根据PCI插槽Slot选择正确的中断向量,读网卡的MAC地址,然后调用ln97xEndLoad</STRONG></P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<BLOCKQUOTE>
<P>STATUS sysln97xEndBldLoadStr ( void )<BR>{<BR>int i;<BR>int
intvec;<BR>int intlvl;<BR>ULONG pciMemAddr;<BR>unsigned int
busDevFunc;</P></BLOCKQUOTE></BLOCKQUOTE>
<P><BR><STRONG>/*<BR>* 在PCI总线上查找设置第一个AMD设备.<BR>* 如果发现存在,函数pciFindDevice
为busDevFunc赋值<BR>*/</STRONG></P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<P>if (pciFindDevice(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_79C97X, 0,
&busDevFunc))<BR>return(ERROR);<BR><BR><STRONG>/*<BR>* 97x的基地址 1
包含PCI存储空间的基地址.<BR>*/<BR></STRONG>pciMemAddr = pciConfigIn(busDevFunc,
PCI_CFG_BASE_ADDRESS_1, 4);<BR>pciMemAddr &=
0xFFFFFFF0;<BR><BR>/*<BR>* 设置PCI定时器反应时间为50 Set latency timer to
50.<BR>*/<BR>pciConfigOut(busDevFunc, PCI_LATENCY_TIMER, 50,
1);<BR><BR><STRONG>/*<BR>*
每个PCI插槽连接到中断控制器的管脚不一样,中断取决于网卡插在哪一个PCI插槽上.<BR>*/<BR></STRONG>switch
((busDevFunc & 0x0000F800) >> 11) /* Strip off just the device
*/<BR>{<BR>case 1 : intvec = INT_VEC_PCI_SLOT3; <STRONG>/* 插槽 3
*/</STRONG><BR>intlvl = INT_LVL_PCI_SLOT3;<BR>break;<BR>case 2 : intvec =
INT_VEC_PCI_SLOT2; <STRONG>/* 插槽 2 */</STRONG><BR>intlvl =
INT_LVL_PCI_SLOT2;<BR>break;<BR>case 3 : intvec = INT_VEC_PCI_SLOT1;
<STRONG>/* 插槽 1 */</STRONG><BR>intlvl =
INT_LVL_PCI_SLOT1;<BR>break;<BR>case 4 : intvec = INT_VEC_PCI_SLOT0;
<STRONG>/* 插槽 0 */</STRONG><BR>intlvl =
INT_LVL_PCI_SLOT0;<BR>break;<BR>default : return(ERROR); /* Not possible,
error */<BR><BR>}<BR><BR>/*<BR>* 使能PCI Mem cycles 和 总线 Master
操作<BR>*/<BR>pciConfigOut(busDevFunc,
PCI_CFG_COMMAND,<BR>PCI_CMD_MEM_ENABLE | PCI_CMD_MASTER_ENABLE,
2);<BR><BR><STRONG>/*<BR>* 得到网卡的MAC地址<BR>*/</STRONG><BR>for (i=0; i<6;
i++)<BR>sysEnetAddr[i] =
sysInByte(pciMemAddr+APROM01+i);<BR><BR><STRONG>/*<BR>*
生成初始化字符串,如一下形式:<BR>*<BR></STRONG>*
<devMemAddr>:<devIoAddr>:<pciMemBase>:<vecNum>:<intLvl>:<memAdrs>:<BR>*
<memSize>:<memWidth>:<csr3b>:<offset>:<flags><BR>*<BR><STRONG>*
这个字符串将在函数muxEndLoad()中加载<BR></STRONG>*/<BR><BR>sprintf(sys97xLoadString,
"0x%x:0x%x:0:%d:%d:0x%x:0:0x%x:0:0:0",<BR>(unsigned int)pciMemAddr, NONE,
intvec, intlvl,<BR>NONE,NONE);<BR><BR>return(OK);<BR><BR>}<BR></P>
<P> </P></BLOCKQUOTE></BLOCKQUOTE></BLOCKQUOTE></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -