一、环境
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
版权声明:本文为博主(宽简厚重,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
版权声明:本文为博主(宽简厚重,Yuesichiu)原创文章,未经博主允许不得转载。
http://blog.csdn.net/yuesichiu/article/details/77429981