📄 plx9054.c
字号:
/* Plx9054.c: Plx9054 PCI桥片驱动源文件*/
/* author: Wang.qi Jilin Univ. 2004512025*/
/*
PLX9054驱动程序从功能上可划分为以下模块:
初始化模块、PCI配置寄存器读写模块、本地寄存器读写模块、
本地空间读写模块、读写模块、控制与配置模块、DMA模块、
中断处理模块及测试维护模块。
各模块调用关系图
配置和
控制模块
PLX9054 PCI 配 PLX9054 本
置寄存器 地寄存器
读写模块 读写模块
PLX9054本地空间读写模块 DMA模块
*/
/*
modification history
------------------
2006-09-17
*/
#ifdef __cplusplus
extern "C" {
#endif
/* includes (header file) 头包含文件 */
#include "vxWorks.h"
#include "vme.h"
#include "memLib.h"
#include "sysLib.h"
#include "string.h"
#include "intLib.h"
#include "config.h"
#include "logLib.h"
#include "taskLib.h"
#include "vxLib.h"
#include "errnoLib.h"
#include "dosFsLib.h"
#include "stdio.h"
#include "cacheLib.h"
#include "private/vmLibP.h"
#include "arch/i86/pentiumLib.h"
#include "drv/pci/pciConfigLib.h"
#include "drv/pci/pciIntLib.h"
#include "plx9054.h"
/* define 宏定义 */
/* global */
PLX9054_DRVCTRL * pPlxDrvCtrl = NULL; /* 指向设备驱动结构体,驱动里通过这个指针操作设备*/
static PLX9054_DRVCTRL plxDrvCtrl;
static PLX9054_DEVICE plxDevCtrl[PLX9054_MAX_DEV];
/* local */
LOCAL PLX9054_BOARD_RESOURCES plx9054Brds [] =
{
{0, PLX_9054_VENDORID, PLX_9054_DEVICEID, 0},
};
LOCAL PLX9054_PCI_RESOURCES plx9054PciResrcs [] = /*默认分配给PLX 的PCI资源*/
{
{PLX9054_MEM_ADR0, PLX9054_IO_ADR0, PLX9054_INT_LVL0, PLX9054_INT_VEC0,
PCI_CFG_TYPE, 0, 0, 0},
{PLX9054_MEM_ADR1, PLX9054_IO_ADR1, PLX9054_INT_LVL1, PLX9054_INT_VEC1,
PCI_CFG_TYPE, 0, 0, 0},
{PLX9054_MEM_ADR2, PLX9054_IO_ADR2, PLX9054_INT_LVL2, PLX9054_INT_VEC2,
PCI_CFG_TYPE, 0, 0, 0},
{PLX9054_MEM_ADR3, PLX9054_IO_ADR3, PLX9054_INT_LVL3, PLX9054_INT_VEC3,
PCI_CFG_TYPE, 0, 0, 0}
};
static char line[256];
/* import */
IMPORT STATUS sysMmuMapAdd (void *, UINT, UINT, UINT);
IMPORT void sysWait(void);
#ifdef BOOT_COM_PRINT
IMPORT void com1BootPrint(char * buf);
#endif
IMPORT STATUS pciIntConnect();
IMPORT STATUS rebootHookAdd (FUNCPTR rebootHook);
/* function declarations*/
#if 0
STATUS PLX9054_GetSpaceInfo(int index, PLX9054_SPACE_INDEX spaceIndex, PLX9054_SPACE_DESC * pPlxSpace);
STATUS PLX9054_GetAllSpaceInfo(int index);
STATUS PLX9054_Local_Reg_Read( int index, int offset, UINT32 * pData);
STATUS PLX9054_Local_Reg_Write( int index, int offset, UINT32 data);
STATUS PLX9054_Pci_Reg_Read( int index, int offset, UINT32 * pData, DATA_WIDTH_MODE dataWidth);
STATUS PLX9054_Pci_Reg_Write( int index, int offset, UINT32 data, DATA_WIDTH_MODE dataWidth);
void PLX9054_IntEnable (int index);
void PLX9054_IntDisable (int index);
STATUS PLX9054_ReadByte (int index, PLX9054_SPACE_INDEX spaceIndex, UINT32 dwOffset, char * pData);
STATUS PLX9054_WriteByte (int index, PLX9054_SPACE_INDEX spaceIndex, UINT32 dwOffset, char data);
STATUS PLX9054_ReadWord (int index, PLX9054_SPACE_INDEX spaceIndex, UINT32 dwOffset, short * pData);
STATUS PLX9054_WriteWord (int index, PLX9054_SPACE_INDEX spaceIndex, UINT32 dwOffset, short data);
STATUS PLX9054_ReadDword (int index, PLX9054_SPACE_INDEX spaceIndex, UINT32 dwOffset, UINT32 * pData);
STATUS PLX9054_WriteDword (int index, PLX9054_SPACE_INDEX spaceIndex, UINT32 dwOffset, UINT32 data);
#endif
void PLX9054_EepromSendCommand(int index, UINT32 EepromCommand, UCHAR DataLengthInBits);
void PLX9054_EepromClock(int index);
void PLX9054_Int(int index);
STATUS sysPlx9054IntEnable(int level);
STATUS sysPlx9054IntDisable(int level);
/* function */
/*
sysPlx9054PciInit
在sysHwInit中调用,此时系统内核、MMU 等还未初始化
查找PLX9054扩展卡,读取PLX9054的PCI配置空间,以获取
BIOS分配给PLX9054扩展卡的资源
*/
STATUS sysPlx9054PciInit (void)
{
UINT32 membaseCsr;
UINT32 iobaseCsr;
UINT32 sp0MemBase; /* PCI9054 本地空间0 的PCI Memory 基地址*/
UINT32 sp1MemBase; /* PCI9054 本地空间1 的PCI Memory 基地址*/
UINT32 sp0Range; /* PCI9054 本地空间0 的大小*/
UINT32 sp1Range; /* PCI9054 本地空间1 的大小*/
char irq;
int pciBus;
int pciDevice;
int pciFunc;
int ix;
int unit;
int found = FALSE;
int plx9054Units = 0;
char buf[255];
PLX9054_DRVCTRL * pDrvCtrl = NULL;
PLX9054_DEVICE * pDevCtrl = NULL;
/* 为驱动结构体申请内存空间*/
#if 0
pDrvCtrl = (PLX9054_DRVCTRL *)malloc(sizeof(PLX9054_DRVCTRL));
if(NULL == pDrvCtrl)
{
printf("Malloc return NULL File:%s, Line:%d.\n", __FILE__, __LINE__);
return ERROR;
}
#endif
pDrvCtrl = &plxDrvCtrl;
PLX9054_SetDrvCtrl(pDrvCtrl); /* 设置全局设备驱动结构体指针*/
memset((void *)pDrvCtrl, 0, sizeof(PLX9054_DRVCTRL));
/* find all plx9054 cards */
for (unit = 0; unit < PLX9054_MAX_DEV; unit++)
{
for (ix=0; ix < NELEMENTS (plx9054Brds); ix++)
{
if (pciFindDevice (plx9054Brds [ix].vendorId, plx9054Brds [ix].deviceId,
unit, &pciBus, &pciDevice, &pciFunc) == OK)
{
/* board detected */
found = TRUE;
#if 0
/* 为设备结构体申请内存空间*/
pDevCtrl = (PLX9054_DEVICE *)malloc(sizeof(PLX9054_DEVICE));
if(NULL == pDevCtrl)
{
printf("Malloc return NULL File:%s, Line:%d.\n", __FILE__, __LINE__);
/* 释放已分配的内存空间*/
return ERROR;
}
memset((void *)pDevCtrl, 0, sizeof(PLX9054_DEVICE));
#endif
pDevCtrl = &(plxDevCtrl[unit]);
/* load up the PCI device table */
pDevCtrl->PlxPciRsrc = plx9054PciResrcs[unit];
pDevCtrl->PlxPciRsrc.pciBus = pciBus;
pDevCtrl->PlxPciRsrc.pciDevice = pciDevice;
pDevCtrl->PlxPciRsrc.pciFunc = pciFunc;
pDrvCtrl->pDevice[unit] = pDevCtrl;
plx9054Units++; /* number of units found */
break;
}
}
}
pDrvCtrl->plxCardNum = plx9054Units;
if ((found != TRUE) || (pciDevice > PCI_MAX_DEV))
{
#ifdef PLX_DEBUG_PRINT
#ifdef BOOT_COM_PRINT
com1BootPrint("No PLX Device Find\n\r");
#endif
#endif
return ((int)NULL);
}
sprintf(buf, "Driver Find %d PLX9054 Devices.\n\r", plx9054Units);
#ifdef BOOT_COM_PRINT
com1BootPrint(buf);
#endif
/* Now initialize all the units we found
由于BIOS已经分配好资源,这里只需要读取BIOS
分配给PLX9054的资源信息即可,无需配置*/
for (unit = 0; unit < plx9054Units; unit++)
{
/* Fill in the resource entry */
pDevCtrl = pDrvCtrl->pDevice[unit];
if (PCI_CFG_FORCE == pDevCtrl->PlxPciRsrc.configType)
{
/* write the iobase, membase, and irq */
pciConfigOutLong (pDevCtrl->PlxPciRsrc.pciBus,
pDevCtrl->PlxPciRsrc.pciDevice,
pDevCtrl->PlxPciRsrc.pciFunc,
PCI_CFG_BASE_ADDRESS_1,
pDevCtrl->PlxPciRsrc.iobaseCsr |
PCI_BASE_IO);
pciConfigOutLong (pDevCtrl->PlxPciRsrc.pciBus,
pDevCtrl->PlxPciRsrc.pciDevice,
pDevCtrl->PlxPciRsrc.pciFunc,
PCI_CFG_BASE_ADDRESS_0,
pDevCtrl->PlxPciRsrc.membaseCsr);
pciConfigOutByte (pDevCtrl->PlxPciRsrc.pciBus,
pDevCtrl->PlxPciRsrc.pciDevice,
pDevCtrl->PlxPciRsrc.pciFunc,
PCI_CFG_DEV_INT_LINE,
pDevCtrl->PlxPciRsrc.irq);
}
/*
* get memory base address and IO base address
* Note: we read it in again, even if we just wrote it out because
* the device can change what we wrote
*/
pciConfigInLong (pDevCtrl->PlxPciRsrc.pciBus,
pDevCtrl->PlxPciRsrc.pciDevice,
pDevCtrl->PlxPciRsrc.pciFunc,
PCI_CFG_BASE_ADDRESS_1, &iobaseCsr);
pciConfigInLong (pDevCtrl->PlxPciRsrc.pciBus,
pDevCtrl->PlxPciRsrc.pciDevice,
pDevCtrl->PlxPciRsrc.pciFunc,
PCI_CFG_BASE_ADDRESS_0, &membaseCsr);
pciConfigInByte (pDevCtrl->PlxPciRsrc.pciBus,
pDevCtrl->PlxPciRsrc.pciDevice,
pDevCtrl->PlxPciRsrc.pciFunc,
PCI_CFG_DEV_INT_LINE, &irq);
/*
* mask off registers. IO base needs to be masked off because bit0
* will always be set to 1
*/
membaseCsr &= PCI_MEMBASE_MASK;
iobaseCsr &= PCI_IOBASE_MASK;
#ifdef INCLUDE_MMU_BASIC
if (sysMmuMapAdd ((void *)(membaseCsr & PCI_DEV_MMU_MSK),
PCI_DEV_ADRS_SIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE |
VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE |
VM_STATE_CACHEABLE_NOT
) == ERROR)
{
/* for now, exit, but later break and stop where we're at
when we're detecting multiple units */
return (ERROR);
}
#else
#warning INCLUDE_MMU_BASIC not defined
#endif /* INCLUDE_MMU_BASIC */
/* 获取PCI9054 本地空间的PCI 基地址*/
pciConfigInLong (pDevCtrl->PlxPciRsrc.pciBus,
pDevCtrl->PlxPciRsrc.pciDevice,
pDevCtrl->PlxPciRsrc.pciFunc,
PCI_CFG_BASE_ADDRESS_2, &sp0MemBase);
pciConfigInLong (pDevCtrl->PlxPciRsrc.pciBus,
pDevCtrl->PlxPciRsrc.pciDevice,
pDevCtrl->PlxPciRsrc.pciFunc,
PCI_CFG_BASE_ADDRESS_3, &sp1MemBase);
/* 利用PCI I/O 读取PCI9054本地配置寄存器,获取本地空间的大小*/
sp0Range = sysInLong(iobaseCsr + P9054_LAS0RR);
sp1Range = sysInLong(iobaseCsr + P9054_LAS1RR);
sp0Range = (~(sp0Range & PCI_MEMBASE_MASK)) + 1;
sp1Range = (~(sp1Range & PCI_MEMBASE_MASK)) + 1;
/* 将PCI9054 本地空间0、1申请的PCI Memory空间加入MMU 表中sysPhysMemDesc*/
#ifdef INCLUDE_MMU_BASIC
if((sp0MemBase & BIT0) != BIT0) /* 是PCI Memory 空间,将其加入到MMU表中*/
{
sp0MemBase &= PCI_MEMBASE_MASK;
sp0Range = ROUND_UP(sp0Range, VM_PAGE_SIZE);
if (sysMmuMapAdd ((void *)(sp0MemBase & PCI_DEV_MMU_MSK),
sp0Range,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE |
VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE |
VM_STATE_CACHEABLE
) == ERROR)
{
/* for now, exit, but later break and stop where we're at
when we're detecting multiple units */
return (ERROR);
}
}
if((sp1MemBase & BIT0) != BIT0) /* 是PCI Memory 空间,将其加入到MMU表中*/
{
sp1MemBase &= PCI_MEMBASE_MASK;
sp1Range = ROUND_UP(sp1Range, VM_PAGE_SIZE);
if (sysMmuMapAdd ((void *)(sp1MemBase & PCI_DEV_MMU_MSK),
sp1Range,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE |
VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE |
VM_STATE_CACHEABLE
) == ERROR)
{
/* for now, exit, but later break and stop where we're at
when we're detecting multiple units */
return (ERROR);
}
}
#else
#warning INCLUDE_MMU_BASIC not defined
#endif /* INCLUDE_MMU_BASIC */
/* over write the resource table with values read */
pDevCtrl->PlxPciRsrc.membaseCsr = membaseCsr;
pDevCtrl->PlxPciRsrc.iobaseCsr = iobaseCsr;
pDevCtrl->PlxPciRsrc.irq = irq;
pDevCtrl->PlxPciRsrc.irqvec = irq + EXT_INTERRUPT_BASE;
/* enable mapped memory and IO addresses */
pciConfigOutWord (pDevCtrl->PlxPciRsrc.pciBus,
pDevCtrl->PlxPciRsrc.pciDevice,
pDevCtrl->PlxPciRsrc.pciFunc,
PCI_CFG_COMMAND, PCI_CMD_IO_ENABLE |
PCI_CMD_MEM_ENABLE | PCI_CMD_MASTER_ENABLE);
/* disable sleep mode */
pciConfigOutWord (pDevCtrl->PlxPciRsrc.pciBus,
pDevCtrl->PlxPciRsrc.pciDevice,
pDevCtrl->PlxPciRsrc.pciFunc,
PCI_CFG_MODE,
SLEEP_MODE_DIS);
/* 获取PLX9054所有本地空间信息*/
PLX9054_GetAllSpaceInfo(unit);
}
return (int)NULL;
}
/******************************************************************
sysPlx9054PciStart
在系统内核初始化完毕后,启动扩展卡
需要注意sysPlx9054PciInit 与sysPlx9054PciStart 函数的区别,
两者执行时所处的运行环境不同,
一个在系统内核初始化前被调用---- sysPlx9054PciInit
一个在系统内核初始化后被调用---- sysPlx9054PciStart
*/
void sysPlx9054PciStart(void)
{
PLX9054_DRVCTRL * pDrvCtrl;
int index;
pDrvCtrl = PLX9054_GetDrvCtrl( );
for(index = 0; index < pDrvCtrl->plxCardNum; index++)
{
#if 0
/* 此处用于复位CPLD 逻辑,使其状态机处于S0(idle)状态.
规避一开始状态错误问题,也可以在VHDL中修改*/
PLX9054_SoftReset(index);
#endif
PLX9054_DMA_Init(index);
/* 挂接中断*/
#if 1
pciIntConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->pDevice[index]->PlxPciRsrc.irqvec), \
(VOIDFUNCPTR)PLX9054_Int, index);
#else
intConnect(pDrvCtrl->pDevice[index]->PlxPciRsrc.irq, (FUNCPTR)PLX9054_Int, index);
#endif
/* 使能中断*/
PLX9054_IntEnable(index);
/* 使能系统中断*/
sysPlx9054IntEnable((int)(pDrvCtrl->pDevice[index]->PlxPciRsrc.irq));
/* 挂接热启动函数*/
rebootHookAdd((FUNCPTR)PLX9054_SoftReset);
}
}
/*************************************************************************
系统中断使能
*/
STATUS sysPlx9054IntEnable(int level)
{
return (sysIntEnablePIC(level));
}
/*************************************************************************
系统中断使能
*/
STATUS sysPlx9054IntDisable(int level)
{
return (sysIntDisablePIC(level));
}
/*
PLX9054_GetSpaceInfo
获取PLX9054本地空间信息Space0、Space1、Programe ROM Space
input
int index: 设备索引
int spaceIndex: 本地空间索引
pPlxSpace: 指向本地空间信息结构体
*/
STATUS PLX9054_GetSpaceInfo(int index, PLX9054_SPACE_INDEX spaceIndex, PLX9054_SPACE_DESC * pPlxSpace)
{
PLX9054_DRVCTRL * pDrvCtrl;
UINT32 range, localBase, pciBase;
pDrvCtrl = PLX9054_GetDrvCtrl( );
/* 输入参数判断*/
if( (index < 0) || (index > (pDrvCtrl->plxCardNum - 1)))
{
printf("Index out of range file:%s, line:%d.\n", __FILE__, __LINE__);
return ERROR;
}
if( (spaceIndex < P9054_ADDR_REG) || (spaceIndex >= P9054_ADDR_EPROM))
{
printf("spaceIndex out of range file:%s, line:%d.\n", __FILE__, __LINE__);
return ERROR;
}
if(NULL == pPlxSpace)
{
printf("Pointer is NULL file:%s, line:%d.\n", __FILE__, __LINE__);
return ERROR;
}
switch(spaceIndex)
{
case P9054_ADDR_REG:
sprintf(pPlxSpace->spaceName, "Pci Mem For Local Reg");
pPlxSpace->dwPciBar = pDrvCtrl->pDevice[index]->PlxPciRsrc.membaseCsr;
pPlxSpace->dwRange = 256;
pPlxSpace->fIsEnable = TRUE;
pPlxSpace->fIsMemory = TRUE;
return OK;
break;
case P9054_ADDR_REG_IO:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -