digium pci模拟板卡 硬件访问分析
static struct pci_device_id wctdm_pci_tbl[] = {{ 0xe159, 0x0001, 0xa159, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm },
{ 0xe159, 0x0001, 0xe159, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm },
{ 0xe159, 0x0001, 0xb100, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
{ 0xe159, 0x0001, 0xb1d9, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmi },
{ 0xe159, 0x0001, 0xb118, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmi },
{ 0xe159, 0x0001, 0xb119, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmi },
{ 0xe159, 0x0001, 0xa9fd, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh },
{ 0xe159, 0x0001, 0xa8fd, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh },
{ 0xe159, 0x0001, 0xa800, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh },
{ 0xe159, 0x0001, 0xa801, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh },
{ 0xe159, 0x0001, 0xa908, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh },
{ 0xe159, 0x0001, 0xa901, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh },
#ifdef TDM_REVH_MATCHALL
{ 0xe159, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh },
#endif
{ 0 }
};
上面的table分别设定了digium公司的wctdm系列的pci的板卡以第一个为例 vendor ID是0xe159, deviceID是0x0001, subvendorID是0xa159, subdeviceID是PCI_ANY_ID,callsID和class_mask都是0,最后的是driver_data 用来区别不同设备的信息,保存了设备名例如:
static struct wctdm_desc wctdm = { "Wildcard S400P Prototype", 0 };
操作系统就是根据这些ID来自动调用dahdi的driver的。
pci设备好像会自动映射寄存器到IO端口。
下面的是pci控制相关 访问方法:
首先或者IO端口的映射:
wc->ioaddr = pci_resource_start(pdev, 0);
request_region(wc->ioaddr, 0xff, "wctdm")
然后通过outb inb端口访问函数进行访问。
例如:
outb(0x01, wc->ioaddr + WC_CNTL);
inb(wc->ioaddr + WC_CNTL);
pci 板卡寄存器地址(偏移)
#define WC_CNTL 0x00//写入0x0e reset pci chip and registers
//写入0x01 reset signal
#define WC_OPER //控制TDM 写入0x01 reset tdm 开始dma
//写入0x00 stop dma
#define WC_AUXC 0x02
#define WC_AUXD 0x03 ////spi 信号寄存器
#define WC_MASK0 0x04
#define WC_MASK1 0x05 ////中断相关
#define WC_INTSTAT 0x06////中断相关
#define WC_AUXR 0x07 ////spi的接收缓冲器
#define WC_DMAWS 0x08
#define WC_DMAWI 0x0c
#define WC_DMAWE 0x10
#define WC_DMARS 0x18
#define WC_DMARI 0x1c
#define WC_DMARE 0x20
#define WC_AUXFUNC 0x2b
#define WC_SERCTL 0x2d //Configure serial port for MSB->LSB operation
#define WC_FSCDELAY 0x2f //Delay FSC by 0 so it's properly aligned
通过spi的访问板卡芯片: 首先进行片选 然后通过spi总线进行读写。
示例代码:
static unsigned char __wctdm_getreg(struct wctdm *wc, int card, unsigned char reg)
{
__wctdm_setcard(wc, card);////通过给wc_cs寄存器赋值 选择板卡。
if (wc->modtype[card] == MOD_TYPE_FXO) { ////fxo的寄存器读
__write_8bits(wc, 0x60);
__write_8bits(wc, reg & 0x7f);
} else {
__write_8bits(wc, reg | 0x80); ////fxs的寄存器读
}
return __read_8bits(wc); ////读取数据
}
/////片选的实现 通过对wc_cs寄存去赋值 实现片选
#define WC_REGBASE 0xc0 ////这个是spi寄存器的起始地址
#define WC_SYNC 0x0
#define WC_TEST 0x1
#define WC_CS 0x2////片选寄存器 选择哪个fxo口或者fxs口
#define WC_VER 0x3
以上4个寄存器的访问方法:
示例代码:
static unsigned char __wctdm_getcreg(struct wctdm *wc, unsigned char reg)
{
return inb(wc->ioaddr + WC_REGBASE + ((reg & 0xf) << 2));
}
spi bus访问的的实现
wc_auxd 寄存器是控制spi。
spi的输入输出片选时钟信号分别对应 wc_auxd寄存器的一个bit 对应关系如下:
#define BIT_CS (1 << 2)
#define BIT_SCLK (1 << 3)
#define BIT_SDI (1 << 4)
#define BIT_SDO (1 << 5)
ios 是spi的4条信号线的对应位置的数据将ios的相应位置的数据赋值为0 或者1 然后将ios写入wc_auxd寄存去实现对spi的4条信号线的控制。
示例代码:
static inline void __write_8bits(struct wctdm *wc, unsigned char bits)
{
/* Drop chip select */
int x;
wc->ios |= BIT_SCLK;
outb(wc->ios, wc->ioaddr + WC_AUXD);
wc->ios &= ~BIT_CS;
outb(wc->ios, wc->ioaddr + WC_AUXD);
for (x=0;x<8;x++) {
/* Send out each bit, MSB first, drop SCLK as we do so */
if (bits & 0x80)
wc->ios |= BIT_SDI;
else
wc->ios &= ~BIT_SDI;
wc->ios &= ~BIT_SCLK;
outb(wc->ios, wc->ioaddr + WC_AUXD);
/* Now raise SCLK high again and repeat */
wc->ios |= BIT_SCLK;
outb(wc->ios, wc->ioaddr + WC_AUXD);
bits <<= 1;
}
/* Finally raise CS back high again */
wc->ios |= BIT_CS;
outb(wc->ios, wc->ioaddr + WC_AUXD);
}
没有评论:
发表评论