DAHDI驱动源代码分析之五硬件初始化

来源:互联网 发布:用数据讲故事 pdf 编辑:程序博客网 时间:2024/05/16 05:37
一、环境
      DAHDI驱动版本:dahdi-linux-complete-2.6.2+2.6.2
      DAHDI卡:Digium Wildcard TE420 dual-span T1/E1/J1 card

二、概述
     dahdi驱动的硬件初始化分为两个阶段:Stage1(t4_hardware_init_1函数)和Stage2(t4_hardware_init_2函数

版权声明:本文为博主(宽简厚重,Yuesichiu)原创文章,未经博主允许不得转载。
http://blog.csdn.net/yuesichiu/article/details/77429981

1、Stage1阶段(t4_hardware_init_1)
       主要是显示Firmware版本,PCIE初始化,复位DMA控制寄存器,复位DAHDI端口指示灯寄存器,设置DMA的物理地址。
根据传递进来的dahdi卡结构体和设备私有数据
(1)、读取DAHDI卡上的WC_VERSION,显示Firmware版本(WC_VERSION)。

(2)、如果是PCIE接口的话,就需要复位它。
        t4_extended_reset(wc);
       上述函数是先保存中断寄存器的值,然后设置一大堆PCIE寄存器,最后恢复中断寄存器。
static void t4_extended_reset(struct t4 *wc)
{
    unsigned int oldreg = t4_pci_in(wc, 0x4);

    udelay(1000);

    t4_pci_out(wc, 0x4, 0x42000000);
    t4_pci_out(wc, 0xa, 0x42000000);
    t4_pci_out(wc, 0xa, 0x00080000);
    t4_pci_out(wc, 0xa, 0x00080000);
    t4_pci_out(wc, 0xa, 0x00080000);
    t4_pci_out(wc, 0xa, 0x00180000);
    t4_pci_out(wc, 0xa, 0x00080000);
    t4_pci_out(wc, 0xa, 0x00180000);
    t4_pci_out(wc, 0xa, 0x00080000);
    t4_pci_out(wc, 0xa, 0x00180000);
    t4_pci_out(wc, 0xa, 0x00080000);
    t4_pci_out(wc, 0xa, 0x00180000);
    t4_pci_out(wc, 0xa, 0x00080000);
    t4_pci_out(wc, 0xa, 0x00180000);
    t4_pci_out(wc, 0xa, 0x00080000);
    t4_pci_out(wc, 0xa, 0x00180000);
    t4_pci_out(wc, 0x4, oldreg);

    udelay(1000);
}

(3)、复位DMA控制寄存器
    /* Make sure DMA engine is not running and interrupts are acknowledged */
    wc->dmactrl = 0x0;
    t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);

 (4)、复位DAHDI端口指示灯寄存器
    /* Reset Framer and friends */
    t4_pci_out(wc, WC_LEDS, 0x00000000);


  (5)、设置DMA物理地址
     /* Set DMA addresses */
    t4_pci_out(wc, WC_RDADDR, wc->readdma);
    t4_pci_out(wc, WC_WRADDR, wc->writedma);

   (6)、设置计数器和中断标志
     0x0ffc0000 | 0x000007fc
t4_pci_out(wc, WC_COUNT, ((DAHDI_MAX_CHUNKSIZE * 2 * 32 - 1) << 18) | ((DAHDI_MAX_CHUNKSIZE * 2 * 32 - 1) << 2));

  (7)、复位挂起中断寄存器WC_INTR
     t4_pci_out(wc, WC_INTR, 0x00000000);

  (8)、读取T1/E1状态
     如果没有设置default_linemode的话,默认是auto,即从WC_LEDS的[11:8]位读取出来以做判断t1e1模式。
     /* Read T1/E1 status */
    if (!strcasecmp("auto", default_linemode)) {
        if (-1 == t1e1override) {
            wc->t1e1 = (((t4_pci_in(wc, WC_LEDS)) & 0x0f00) >> 8);
            wc->t1e1 &= 0xf;
            if (is_octal(wc)) {
                wc->t1e1 |= ((t4_pci_in(wc, WC_LEDS2)) &
                            0x0f00) >> 4;
            }
        } else {
            dev_warn(&wc->dev->dev, "'t1e1override' is deprecated. "
                 "Please use 'default_linemode'.\n");
            wc->t1e1 = t1e1override & 0xf;
        }
    } else if (!strcasecmp("t1", default_linemode)) {
        wc->t1e1 = 0;
    } else if (!strcasecmp("e1", default_linemode)) {
        wc->t1e1 = 0xff;
    } else if (!strcasecmp("j1", default_linemode)) {
        wc->t1e1 = 0;
        j1mode = 1;
    } else {
        dev_err(&wc->dev->dev, "'%s' is an unknown linemode.\n",
            default_linemode);
        wc->t1e1 = 0;
    }

   (9)、读取卡的顺序
       WC_LEDS的[31:28]位
     wc->order = ((t4_pci_in(wc, WC_LEDS)) & 0xf0000000) >> 28;
     order_index[wc->order]++;

版权声明:本文为博主(宽简厚重,Yuesichiu)原创文章,未经博主允许不得转载。
http://blog.csdn.net/yuesichiu/article/details/77429981

2、Stage2阶段(t4_hardware_init_2函数)
       主要是根据WC_VERSION判断是否需要设置FLAG_OCTOPT,激活T4,点亮运行状态灯,读取FALC版本号和显示板子寄存器相关信息。
   (1)、读取WC_VERSION,如果读取出来的值大于0xc01a0165,就给T1/E1口的端口标志增加FLAG_OCTOPT。
         if (t4_pci_in(wc, WC_VERSION) >= 0xc01a0165) {
              wc->tspans[0]->spanflags |= FLAG_OCTOPT;
         }

   (2)、设置WC_LEDS寄存器,去除rest。
t4_pci_out(wc, WC_LEDS, 0x000000ff);

    (3)、激活T4,点亮LED灯
static inline void t4_activate(struct t4 *wc)
{
    wc->ledreg |= WC_ACTIVATE;                //#define WC_ACTIVATE    (1 << 12)
    t4_pci_out(wc, WC_LEDS, wc->ledreg);
}

      (4)、读取FALC Framer版本,需要暂时关闭compat模式,检查下VSTR寄存器(Version Status Register),当完成FALC版本读取后,再恢复回去。
       

版权声明:本文为博主(宽简厚重,Yuesichiu)原创文章,未经博主允许不得转载。
http://blog.csdn.net/yuesichiu/article/details/77429981



原创粉丝点击