2009年7月18日星期六

digium pci模拟板卡 硬件访问分析

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);
    
}

没有评论:

发表评论