added the new B410P HFC-4S based card. This card has Echocancelation in hardware. Modified mISDN_dsp to check for hw_echocan facilities. added possibility to control the gain from lower layers. Thanks to Matthew Fredrickson for most of the patches.
This commit is contained in:
parent
18df072e60
commit
8ab0c38df3
|
@ -4,7 +4,7 @@ EXTRA_CFLAGS += -ggdb
|
|||
#
|
||||
|
||||
ifdef MINCLUDES
|
||||
CFLAGS += -I$(MINCLUDES)
|
||||
CFLAGS += -I$(MINCLUDES) -g
|
||||
endif
|
||||
ifdef CONFIG_MISDN_MEMDEBUG
|
||||
EXTRA_CFLAGS += -DMISDN_MEMDEBUG
|
||||
|
|
|
@ -4,7 +4,7 @@ EXTRA_CFLAGS += -ggdb
|
|||
#
|
||||
|
||||
ifdef MINCLUDES
|
||||
CFLAGS += -I$(MINCLUDES)
|
||||
CFLAGS += -I$(MINCLUDES) -g
|
||||
endif
|
||||
ifdef CONFIG_MISDN_MEMDEBUG
|
||||
EXTRA_CFLAGS += -DMISDN_MEMDEBUG
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
* out the other.
|
||||
*/
|
||||
|
||||
|
||||
//#define AGGRESSIVE_SUPPRESSOR
|
||||
|
||||
//#include "dsp_mec2.h"
|
||||
//#include "dsp_kb1ec.h"
|
||||
#include "dsp_mg2ec.h"
|
||||
|
@ -175,6 +178,7 @@ struct dsp_features {
|
|||
int hfc_id; /* unique id to identify the chip (or -1) */
|
||||
int hfc_dtmf; /* set if HFCmulti card supports dtmf */
|
||||
int hfc_loops; /* set if card supports tone loops */
|
||||
int hfc_echocanhw; /* set if card supports echocancelation*/
|
||||
int pcm_id; /* unique id to identify the pcm bus (or -1) */
|
||||
int pcm_slots; /* number of slots on the pcm bus */
|
||||
int pcm_banks; /* number of IO banks of pcm bus */
|
||||
|
@ -235,7 +239,9 @@ typedef struct _dsp {
|
|||
int bf_sync;
|
||||
|
||||
/* echo cancellation stuff */
|
||||
int queue_cancel[3];
|
||||
int cancel_enable;
|
||||
int cancel_hardware; /*we are using hw echo canc*/
|
||||
struct echo_can_state * ec; /**< == NULL: echo cancellation disabled;
|
||||
!= NULL: echo cancellation enabled */
|
||||
|
||||
|
|
|
@ -22,6 +22,27 @@
|
|||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* send HW message to hfc card
|
||||
*/
|
||||
static void
|
||||
dsp_cancel_hw_message(dsp_t *dsp, u32 message, u32 param)
|
||||
{
|
||||
struct sk_buff *nskb;
|
||||
|
||||
nskb = create_link_skb(PH_CONTROL | REQUEST, message, sizeof(param), ¶m, 0);
|
||||
if (!nskb) {
|
||||
printk(KERN_ERR "%s: No mem for skb.\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
/* unlocking is not required, because we don't expect a response */
|
||||
if (mISDN_queue_down(&dsp->inst, 0, nskb))
|
||||
dev_kfree_skb(nskb);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void bchdev_echocancel_chunk(dsp_t* dev, uint8_t *rxchunk, uint8_t *txchunk, uint16_t size);
|
||||
int bchdev_echocancel_activate(dsp_t* dev, int deftaps, int train);
|
||||
void bchdev_echocancel_deactivate(dsp_t* dev);
|
||||
|
@ -84,21 +105,40 @@ dsp_cancel_init(dsp_t *dsp, int deftaps, int training, int delay)
|
|||
{
|
||||
|
||||
if (!dsp) return -1;
|
||||
|
||||
if (dsp->feature_state != FEAT_STATE_RECEIVED) {
|
||||
dsp->queue_cancel[0]=deftaps;
|
||||
dsp->queue_cancel[1]=training;
|
||||
dsp->queue_cancel[2]=delay;
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk("DSP_CANCEL_INIT called\n");
|
||||
|
||||
if (delay < 0)
|
||||
{
|
||||
printk("Disabling EC\n");
|
||||
printk(KERN_NOTICE "Disabling EC\n");
|
||||
dsp->cancel_enable = 0;
|
||||
|
||||
dsp->txbuflen=0;
|
||||
|
||||
bchdev_echocancel_deactivate(dsp);
|
||||
|
||||
if (dsp->features.hfc_echocanhw) {
|
||||
printk(KERN_NOTICE "Disabling Hardware EC\n");
|
||||
dsp_cancel_hw_message(dsp, HW_ECHOCAN_OFF, deftaps);
|
||||
} else {
|
||||
bchdev_echocancel_deactivate(dsp);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
if (dsp->features.hfc_echocanhw) {
|
||||
printk(KERN_NOTICE "Using Hardware EC taps [%d]\n",deftaps);
|
||||
dsp_cancel_hw_message(dsp, HW_ECHOCAN_ON, deftaps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dsp->txbuflen=0;
|
||||
dsp->rxbuflen=0;
|
||||
|
||||
|
|
|
@ -631,6 +631,17 @@ dsp_from_down(mISDNinstance_t *inst, struct sk_buff *skb)
|
|||
dev_kfree_skb(skb);
|
||||
break;
|
||||
|
||||
case VOL_CHANGE_TX: /* change volume */
|
||||
if (skb->len != sizeof(int)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
dsp->tx_volume = *((int *)skb->data);
|
||||
if (dsp_debug & DEBUG_DSP_CORE)
|
||||
printk(KERN_DEBUG "%s: change tx volume to %d\n", __FUNCTION__, dsp->tx_volume);
|
||||
printk(KERN_DEBUG "%s: change tx volume to %d\n", __FUNCTION__, dsp->tx_volume);
|
||||
dsp_cmx_hardware(dsp->conf, dsp);
|
||||
break;
|
||||
default:
|
||||
if (dsp_debug & DEBUG_DSP_CORE)
|
||||
printk(KERN_DEBUG "%s: ctrl ind %x unhandled %s\n", __FUNCTION__, hh->dinfo, dsp->inst.name);
|
||||
|
@ -771,14 +782,16 @@ dsp_feat(void *arg)
|
|||
break;
|
||||
case FEAT_STATE_WAIT:
|
||||
if (dsp_debug & DEBUG_DSP_MGR)
|
||||
printk(KERN_DEBUG "%s: features of %s are: hfc_id=%d hfc_dtmf=%d hfc_loops=%d pcm_id=%d pcm_slots=%d pcm_banks=%d\n",
|
||||
printk(KERN_DEBUG "%s: features of %s are: hfc_id=%d hfc_dtmf=%d hfc_loops=%d hfc_echocanhw:%d pcm_id=%d pcm_slots=%d pcm_banks=%d\n",
|
||||
__FUNCTION__, dsp->inst.name,
|
||||
dsp->features.hfc_id,
|
||||
dsp->features.hfc_dtmf,
|
||||
dsp->features.hfc_loops,
|
||||
dsp->features.hfc_echocanhw,
|
||||
dsp->features.pcm_id,
|
||||
dsp->features.pcm_slots,
|
||||
dsp->features.pcm_banks);
|
||||
|
||||
spin_lock(&dsp->feature_lock);
|
||||
dsp->feature_state = FEAT_STATE_RECEIVED;
|
||||
spin_unlock(&dsp->feature_lock);
|
||||
|
@ -789,6 +802,15 @@ dsp_feat(void *arg)
|
|||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
dsp_cmx_debug(dsp);
|
||||
}
|
||||
|
||||
if (dsp->queue_cancel[2]) {
|
||||
dsp_cancel_init(dsp,
|
||||
dsp->queue_cancel[0],
|
||||
dsp->queue_cancel[1],
|
||||
dsp->queue_cancel[2]
|
||||
);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,9 @@
|
|||
//#define IRQCOUNT_DEBUG
|
||||
|
||||
#include "hfc_multi.h"
|
||||
#ifdef ECHOPREP
|
||||
#include "gaintab.h"
|
||||
#endif
|
||||
|
||||
//#warning
|
||||
|
||||
|
@ -184,6 +187,8 @@ static const PCI_ENTRY id_list[] =
|
|||
"HFC-4S", 4, 1, 2},
|
||||
{CCAG_VID, CCAG_VID, HFC4S_ID, 0xB560, VENDOR_CCD,
|
||||
"HFC-4S Beronet Card", 4, 1, 2},
|
||||
{0xD161, 0xD161, 0xB410, 0xB410, VENDOR_CCD,
|
||||
"HFC-4S Digium Card", 4, 0, 2},
|
||||
{CCAG_VID, CCAG_VID, HFC8S_ID, 0xB521, VENDOR_CCD,
|
||||
"HFC-8S IOB4ST Recording", 8, 1, 0},
|
||||
{CCAG_VID, CCAG_VID, HFC8S_ID, 0xB522, VENDOR_CCD,
|
||||
|
@ -278,6 +283,324 @@ disable_hwirq(hfc_multi_t *hc)
|
|||
HFC_outb(hc, R_IRQ_CTRL, hc->hw.r_irq_ctrl);
|
||||
}
|
||||
|
||||
|
||||
#define B410P_CARD
|
||||
|
||||
#define NUM_EC 2
|
||||
#define MAX_TDM_CHAN 32
|
||||
|
||||
|
||||
#ifdef B410P_CARD
|
||||
inline void enablepcibridge(hfc_multi_t *c)
|
||||
{
|
||||
HFC_outb(c, R_BRG_PCM_CFG, (0x0 << 6) | 0x3); /*was _io before*/
|
||||
}
|
||||
|
||||
inline void disablepcibridge(hfc_multi_t *c)
|
||||
{
|
||||
HFC_outb(c, R_BRG_PCM_CFG, (0x0 << 6) | 0x2); /*was _io before*/
|
||||
}
|
||||
|
||||
inline unsigned char readpcibridge(hfc_multi_t *c, unsigned char address)
|
||||
{
|
||||
unsigned short cipv;
|
||||
unsigned char data;
|
||||
|
||||
// slow down a PCI read access by 1 PCI clock cycle
|
||||
HFC_outb(c, R_CTRL, 0x4); /*was _io before*/
|
||||
|
||||
if (address == 0)
|
||||
cipv=0x4000;
|
||||
else
|
||||
cipv=0x5800;
|
||||
|
||||
// select local bridge port address by writing to CIP port
|
||||
//data = HFC_inb(c, cipv); /*was _io before*/
|
||||
outw(cipv, c->pci_iobase + 4);
|
||||
data = inb(c->pci_iobase);
|
||||
|
||||
// restore R_CTRL for normal PCI read cycle speed
|
||||
HFC_outb(c, R_CTRL, 0x0); /*was _io before*/
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
inline void writepcibridge(hfc_multi_t *hc, unsigned char address, unsigned char data)
|
||||
{
|
||||
unsigned short cipv;
|
||||
unsigned int datav;
|
||||
|
||||
if (address == 0)
|
||||
cipv=0x4000;
|
||||
else
|
||||
cipv=0x5800;
|
||||
|
||||
// select local bridge port address by writing to CIP port
|
||||
outw(cipv, hc->pci_iobase + 4);
|
||||
|
||||
// define a 32 bit dword with 4 identical bytes for write sequence
|
||||
datav=data | ( (__u32) data <<8) | ( (__u32) data <<16) | ( (__u32) data <<24);
|
||||
|
||||
|
||||
// write this 32 bit dword to the bridge data port
|
||||
// this will initiate a write sequence of up to 4 writes to the same address on the local bus
|
||||
// interface
|
||||
// the number of write accesses is undefined but >=1 and depends on the next PCI transaction
|
||||
// during write sequence on the local bus
|
||||
outl(datav, hc->pci_iobase);
|
||||
}
|
||||
|
||||
inline void cpld_set_reg(hfc_multi_t *hc, unsigned char reg)
|
||||
{
|
||||
/* Do data pin read low byte */
|
||||
HFC_outb(hc, R_GPIO_OUT1, reg);
|
||||
}
|
||||
|
||||
inline void cpld_write_reg(hfc_multi_t *hc, unsigned char reg, unsigned char val)
|
||||
{
|
||||
cpld_set_reg(hc, reg);
|
||||
|
||||
enablepcibridge(hc);
|
||||
writepcibridge(hc, 1, val);
|
||||
disablepcibridge(hc);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
inline unsigned char cpld_read_reg(hfc_multi_t *hc, unsigned char reg)
|
||||
{
|
||||
unsigned char bytein;
|
||||
|
||||
cpld_set_reg(hc, reg);
|
||||
|
||||
/* Do data pin read low byte */
|
||||
HFC_outb(hc, R_GPIO_OUT1, reg);
|
||||
|
||||
enablepcibridge(hc);
|
||||
bytein = readpcibridge(hc, 1);
|
||||
disablepcibridge(hc);
|
||||
|
||||
return bytein;
|
||||
}
|
||||
|
||||
inline void vpm_write_address(hfc_multi_t *hc, unsigned short addr)
|
||||
{
|
||||
cpld_write_reg(hc, 0, 0xff & addr);
|
||||
cpld_write_reg(hc, 1, 0x01 & (addr >> 8));
|
||||
}
|
||||
|
||||
inline unsigned short vpm_read_address(hfc_multi_t *c)
|
||||
{
|
||||
unsigned short addr;
|
||||
unsigned short highbit;
|
||||
|
||||
addr = cpld_read_reg(c, 0);
|
||||
highbit = cpld_read_reg(c, 1);
|
||||
|
||||
addr = addr | (highbit << 8);
|
||||
|
||||
return addr & 0x1ff;
|
||||
}
|
||||
|
||||
inline unsigned char vpm_in(hfc_multi_t *c, int which, unsigned short addr)
|
||||
{
|
||||
unsigned char res;
|
||||
|
||||
vpm_write_address(c, addr);
|
||||
|
||||
if (!which)
|
||||
cpld_set_reg(c, 2);
|
||||
else
|
||||
cpld_set_reg(c, 3);
|
||||
|
||||
enablepcibridge(c);
|
||||
res = readpcibridge(c, 1);
|
||||
disablepcibridge(c);
|
||||
|
||||
cpld_set_reg(c, 0);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
inline void vpm_out(hfc_multi_t *c, int which, unsigned short addr, unsigned char data)
|
||||
{
|
||||
vpm_write_address(c, addr);
|
||||
|
||||
enablepcibridge(c);
|
||||
|
||||
if (!which)
|
||||
cpld_set_reg(c, 2);
|
||||
else
|
||||
cpld_set_reg(c, 3);
|
||||
|
||||
writepcibridge(c, 1, data);
|
||||
|
||||
cpld_set_reg(c, 0);
|
||||
|
||||
disablepcibridge(c);
|
||||
|
||||
{
|
||||
unsigned char regin;
|
||||
regin = vpm_in(c, which, addr);
|
||||
if (regin != data)
|
||||
printk("Wrote 0x%x to register 0x%x but got back 0x%x\n", data, addr, regin);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void vpm_init(hfc_multi_t *wc)
|
||||
{
|
||||
unsigned char reg;
|
||||
unsigned int mask;
|
||||
unsigned int i, x, y;
|
||||
unsigned int ver;
|
||||
|
||||
for (x=0;x<NUM_EC;x++) {
|
||||
/* Setup GPIO's */
|
||||
if (!x) {
|
||||
ver = vpm_in(wc, x, 0x1a0);
|
||||
printk("VPM: Chip %d: ver %02x\n", x, ver);
|
||||
}
|
||||
|
||||
for (y=0;y<4;y++) {
|
||||
vpm_out(wc, x, 0x1a8 + y, 0x00); /* GPIO out */
|
||||
vpm_out(wc, x, 0x1ac + y, 0x00); /* GPIO dir */
|
||||
vpm_out(wc, x, 0x1b0 + y, 0x00); /* GPIO sel */
|
||||
}
|
||||
|
||||
/* Setup TDM path - sets fsync and tdm_clk as inputs */
|
||||
reg = vpm_in(wc, x, 0x1a3); /* misc_con */
|
||||
vpm_out(wc, x, 0x1a3, reg & ~2);
|
||||
|
||||
/* Setup Echo length (256 taps) */
|
||||
vpm_out(wc, x, 0x022, 1);
|
||||
vpm_out(wc, x, 0x023, 0xff);
|
||||
|
||||
/* Setup timeslots */
|
||||
vpm_out(wc, x, 0x02f, 0x00);
|
||||
mask = 0x02020202 << (x * 4);
|
||||
|
||||
/* Setup the tdm channel masks for all chips*/
|
||||
for (i = 0; i < 4; i++)
|
||||
vpm_out(wc, x, 0x33 - i, (mask >> (i << 3)) & 0xff);
|
||||
|
||||
/* Setup convergence rate */
|
||||
printk("VPM: A-law mode\n");
|
||||
reg = 0x00 | 0x10 | 0x01;
|
||||
vpm_out(wc,x,0x20,reg);
|
||||
printk("VPM reg 0x20 is %x\n", reg);
|
||||
//vpm_out(wc,x,0x20,(0x00 | 0x08 | 0x20 | 0x10));
|
||||
|
||||
vpm_out(wc, x, 0x24, 0x02);
|
||||
reg = vpm_in(wc, x, 0x24);
|
||||
printk("NLP Thresh is set to %d (0x%x)\n", reg, reg);
|
||||
|
||||
/* Initialize echo cans */
|
||||
for (i = 0 ; i < MAX_TDM_CHAN; i++) {
|
||||
if (mask & (0x00000001 << i))
|
||||
vpm_out(wc,x,i,0x00);
|
||||
}
|
||||
|
||||
udelay(10000);
|
||||
|
||||
/* Put in bypass mode */
|
||||
for (i = 0 ; i < MAX_TDM_CHAN ; i++) {
|
||||
if (mask & (0x00000001 << i)) {
|
||||
vpm_out(wc,x,i,0x01);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable bypass */
|
||||
for (i = 0 ; i < MAX_TDM_CHAN ; i++) {
|
||||
if (mask & (0x00000001 << i))
|
||||
vpm_out(wc,x,0x78 + i,0x01);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void vpm_check(hfc_multi_t *hctmp)
|
||||
{
|
||||
unsigned char gpi2;
|
||||
|
||||
gpi2 = HFC_inb(hctmp, R_GPI_IN2);
|
||||
|
||||
if ((gpi2 & 0x3) != 0x3) {
|
||||
printk("Got interrupt 0x%x from VPM!\n", gpi2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Interface to enable/disable the HW Echocan
|
||||
*
|
||||
* these functions are called within a spin_lock_irqsave on
|
||||
* the channel instance lock, so we are not disturbed by irqs
|
||||
*
|
||||
* we can later easily change the interface to make other
|
||||
* things configurable, for now we configure the taps
|
||||
*
|
||||
*/
|
||||
|
||||
void vpm_echocan_on(hfc_multi_t *hc, int ch, int taps)
|
||||
{
|
||||
unsigned int timeslot;
|
||||
unsigned int unit;
|
||||
channel_t *bch = hc->chan[ch].ch;
|
||||
struct sk_buff *skb;
|
||||
int txadj = -4;
|
||||
|
||||
if (hc->chan[ch].protocol != ISDN_PID_L1_B_64TRANS)
|
||||
return;
|
||||
|
||||
if (!bch)
|
||||
return;
|
||||
|
||||
skb = create_link_skb(PH_CONTROL | INDICATION, VOL_CHANGE_TX, sizeof(int), &txadj, 0);
|
||||
|
||||
if (mISDN_queue_up(&bch->inst, 0, skb))
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
timeslot = ((ch/4)*8) + ((ch%4)*4) + 1;
|
||||
unit = ch % 4;
|
||||
|
||||
printk(KERN_NOTICE "vpm_echocan_on called taps [%d] on timeslot %d\n", taps, timeslot);
|
||||
|
||||
vpm_out(hc, unit, timeslot, 0x7e);
|
||||
}
|
||||
|
||||
void vpm_echocan_off(hfc_multi_t *hc, int ch)
|
||||
{
|
||||
unsigned int timeslot;
|
||||
unsigned int unit;
|
||||
channel_t *bch = hc->chan[ch].ch;
|
||||
struct sk_buff *skb;
|
||||
int txadj = 0;
|
||||
|
||||
if (hc->chan[ch].protocol != ISDN_PID_L1_B_64TRANS)
|
||||
return;
|
||||
|
||||
if (!bch)
|
||||
return;
|
||||
|
||||
skb = create_link_skb(PH_CONTROL | INDICATION, VOL_CHANGE_TX, sizeof(int), &txadj, 0);
|
||||
|
||||
if (mISDN_queue_up(&bch->inst, 0, skb))
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
timeslot = ((ch/4)*8) + ((ch%4)*4) + 1;
|
||||
unit = ch % 4;
|
||||
|
||||
printk(KERN_NOTICE "vpm_echocan_off called on timeslot %d\n", timeslot);
|
||||
/*FILLME*/
|
||||
vpm_out(hc, unit, timeslot, 0x01);
|
||||
}
|
||||
|
||||
#endif /* B410_CARD */
|
||||
|
||||
|
||||
|
||||
/******************************************/
|
||||
/* free hardware resources used by driver */
|
||||
/******************************************/
|
||||
|
@ -328,7 +651,7 @@ init_chip(hfc_multi_t *hc)
|
|||
u_long flags, val, val2 = 0, rev;
|
||||
int cnt = 0;
|
||||
int i, err = 0;
|
||||
u_char r_conf_en, rval;
|
||||
u_char r_conf_en,rval;
|
||||
|
||||
spin_lock_irqsave(&hc->lock, flags);
|
||||
/* reset all registers */
|
||||
|
@ -354,7 +677,7 @@ init_chip(hfc_multi_t *hc)
|
|||
printk(KERN_WARNING "HFC_multi: WARNING: This driver doesn't consider chip revision = %ld. The chip / bridge may not work.\n", rev);
|
||||
}
|
||||
|
||||
/* set s-ram size */
|
||||
/* set s-ram size */
|
||||
hc->Flen = 0x10;
|
||||
hc->Zmin = 0x80;
|
||||
hc->Zlen = 384;
|
||||
|
@ -434,17 +757,36 @@ init_chip(hfc_multi_t *hc)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (test_bit(HFC_CHIP_DIGICARD,&hc->chip)) {
|
||||
HFC_outb(hc, R_BRG_PCM_CFG, 0x2);
|
||||
HFC_outb(hc, R_PCM_MD0, (0x9<<4) | 0x1);
|
||||
HFC_outb(hc, R_PCM_MD1, 0);
|
||||
|
||||
printk(KERN_NOTICE "Setting GPIOs\n");
|
||||
HFC_outb(hc, R_GPIO_SEL, 0x30);
|
||||
HFC_outb(hc, R_GPIO_EN1, 0x3);
|
||||
|
||||
udelay(1000);
|
||||
|
||||
printk(KERN_NOTICE "calling vpm_init\n");
|
||||
|
||||
vpm_init(hc);
|
||||
|
||||
} else {
|
||||
HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x90);
|
||||
if (hc->slots == 32)
|
||||
HFC_outb(hc, R_PCM_MD1, 0x00);
|
||||
if (hc->slots == 64)
|
||||
HFC_outb(hc, R_PCM_MD1, 0x10);
|
||||
if (hc->slots == 128)
|
||||
HFC_outb(hc, R_PCM_MD1, 0x20);
|
||||
HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0xa0);
|
||||
HFC_outb(hc, R_PCM_MD2, 0x00);
|
||||
HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x00);
|
||||
|
||||
}
|
||||
|
||||
i = 0;
|
||||
HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x90);
|
||||
if (hc->slots == 32)
|
||||
HFC_outb(hc, R_PCM_MD1, 0x00);
|
||||
if (hc->slots == 64)
|
||||
HFC_outb(hc, R_PCM_MD1, 0x10);
|
||||
if (hc->slots == 128)
|
||||
HFC_outb(hc, R_PCM_MD1, 0x20);
|
||||
HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0xa0);
|
||||
HFC_outb(hc, R_PCM_MD2, 0x00);
|
||||
HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x00);
|
||||
while (i < 256) {
|
||||
HFC_outb_(hc, R_SLOT, i);
|
||||
HFC_outb_(hc, A_SL_CFG, 0);
|
||||
|
@ -478,14 +820,20 @@ init_chip(hfc_multi_t *hc)
|
|||
}
|
||||
if (debug & DEBUG_HFCMULTI_INIT)
|
||||
printk(KERN_DEBUG "HFC_multi F0_CNT %ld after %dms\n", val2, cnt);
|
||||
|
||||
if (val2 < val+4) {
|
||||
printk(KERN_ERR "HFC_multi ERROR 125us pulse not counting.\n");
|
||||
if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) {
|
||||
printk(KERN_ERR "HFC_multi This happens in PCM slave mode without connected master.\n");
|
||||
}
|
||||
if (!test_bit(HFC_CHIP_CLOCK_IGNORE, &hc->chip)) {
|
||||
err = -EIO;
|
||||
goto out;
|
||||
if (test_bit(HFC_CHIP_DIGICARD, &hc->chip)) {
|
||||
printk(KERN_ERR "HFC_multi ingoring PCM clock for digicard.\n");
|
||||
|
||||
} else {
|
||||
if (!test_bit(HFC_CHIP_CLOCK_IGNORE, &hc->chip) ){
|
||||
err = -EIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -691,13 +1039,27 @@ hfcmulti_leds(hfc_multi_t *hc)
|
|||
led[i] = 0; /* led off */
|
||||
i++;
|
||||
}
|
||||
//printk("leds %d %d %d %d\n", led[0], led[1], led[2], led[3]);
|
||||
HFC_outb(hc, R_GPIO_EN1,
|
||||
((led[0]>0)<<0) | ((led[1]>0)<<1) |
|
||||
((led[2]>0)<<2) | ((led[3]>0)<<3));
|
||||
HFC_outb(hc, R_GPIO_OUT1,
|
||||
((led[0]&1)<<0) | ((led[1]&1)<<1) |
|
||||
((led[2]&1)<<2) | ((led[3]&1)<<3));
|
||||
|
||||
if (test_bit(HFC_CHIP_DIGICARD, &hc->chip)) {
|
||||
int leds=0;
|
||||
for (i=0; i<4; i++) {
|
||||
if (led[i]==1) {
|
||||
/*green*/
|
||||
leds |=( 0x2 <<(i*2));
|
||||
} else if (led[i]==2) {
|
||||
/*red*/
|
||||
leds |=( 0x1 <<(i*2));
|
||||
}
|
||||
}
|
||||
vpm_out(hc, 0, 0x1a8+3,leds);
|
||||
} else {
|
||||
HFC_outb(hc, R_GPIO_EN1,
|
||||
((led[0]>0)<<0) | ((led[1]>0)<<1) |
|
||||
((led[2]>0)<<2) | ((led[3]>0)<<3));
|
||||
HFC_outb(hc, R_GPIO_OUT1,
|
||||
((led[0]&1)<<0) | ((led[1]&1)<<1) |
|
||||
((led[2]&1)<<2) | ((led[3]&1)<<3));
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
@ -951,7 +1313,12 @@ hfcmulti_tx(hfc_multi_t *hc, int ch, channel_t *chan)
|
|||
|
||||
//printk("debug: data: len = %d, txpending = %d!!!!\n", *len, txpending);
|
||||
/* lets see how much data we will have left in buffer */
|
||||
HFC_outb_(hc, R_FIFO, ch << 1);
|
||||
if (test_bit(HFC_CHIP_DIGICARD, &hc->chip) && (hc->chan[ch].protocol == ISDN_PID_L1_B_64TRANS) && (hc->chan[ch].slot_rx < 0) && (hc->chan[ch].bank_rx == 0)
|
||||
&& (hc->chan[ch].slot_tx < 0) && (hc->chan[ch].bank_tx == 0)) {
|
||||
HFC_outb_(hc, R_FIFO, 0x20 | (ch << 1));
|
||||
} else
|
||||
HFC_outb_(hc, R_FIFO, ch << 1);
|
||||
|
||||
HFC_wait_(hc);
|
||||
if (txpending == 2) {
|
||||
/* reset fifo */
|
||||
|
@ -1058,6 +1425,7 @@ next_frame:
|
|||
__FUNCTION__, ch, Zspace, z1, z2, ii-i, len-i,
|
||||
test_bit(FLG_HDLC, &chan->Flags) ? "HDLC":"TRANS");
|
||||
|
||||
/* Have to prep the audio data */
|
||||
write_fifo_data(hc, d, ii - i);
|
||||
chan->tx_idx = ii;
|
||||
|
||||
|
@ -1180,7 +1548,11 @@ hfcmulti_rx(hfc_multi_t *hc, int ch, channel_t *chan)
|
|||
struct sk_buff *skb;
|
||||
|
||||
/* lets see how much data we received */
|
||||
HFC_outb_(hc, R_FIFO, (ch<<1)|1);
|
||||
if (test_bit(HFC_CHIP_DIGICARD, &hc->chip) && (hc->chan[ch].protocol == ISDN_PID_L1_B_64TRANS) && (hc->chan[ch].slot_rx < 0) && (hc->chan[ch].bank_rx == 0)
|
||||
&& (hc->chan[ch].slot_tx < 0) && (hc->chan[ch].bank_tx == 0)) {
|
||||
HFC_outb_(hc, R_FIFO, 0x20 | (ch<<1) | 1);
|
||||
} else
|
||||
HFC_outb_(hc, R_FIFO, (ch<<1)|1);
|
||||
HFC_wait_(hc);
|
||||
next_frame:
|
||||
if (test_bit(FLG_HDLC, &chan->Flags)) {
|
||||
|
@ -1593,6 +1965,11 @@ hfcmulti_interrupt(int intno, void *dev_id, struct pt_regs *regs)
|
|||
j = 0;
|
||||
while(j < 8) {
|
||||
ch = (i<<2) + (j>>1);
|
||||
if (ch >= 16) {
|
||||
if (ch == 16)
|
||||
printk("Shouldn't be servicing high FIFOs. Continuing.\n");
|
||||
continue;
|
||||
}
|
||||
chan = hc->chan[ch].ch;
|
||||
if (r_irq_fifo_bl & (1 << j)) {
|
||||
if (chan && hc->created[hc->chan[ch].port] &&
|
||||
|
@ -1769,23 +2146,70 @@ mode_hfcmulti(hfc_multi_t *hc, int ch, int protocol, int slot_tx, int bank_tx, i
|
|||
}
|
||||
break;
|
||||
case (ISDN_PID_L1_B_64TRANS): /* B-channel */
|
||||
/* enable TX fifo */
|
||||
HFC_outb(hc, R_FIFO, ch<<1);
|
||||
HFC_wait(hc);
|
||||
HFC_outb(hc, A_CON_HDLC, flow_tx | 0x00 | V_HDLC_TRP | V_IFF);
|
||||
HFC_outb(hc, A_SUBCH_CFG, 0);
|
||||
HFC_outb(hc, A_IRQ_MSK, 0);
|
||||
HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
|
||||
HFC_wait(hc);
|
||||
HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence); /* tx silence */
|
||||
/* enable RX fifo */
|
||||
HFC_outb(hc, R_FIFO, (ch<<1)|1);
|
||||
HFC_wait(hc);
|
||||
HFC_outb(hc, A_CON_HDLC, flow_rx | 0x00 | V_HDLC_TRP);
|
||||
HFC_outb(hc, A_SUBCH_CFG, 0);
|
||||
HFC_outb(hc, A_IRQ_MSK, 0);
|
||||
HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
|
||||
HFC_wait(hc);
|
||||
if (test_bit(HFC_CHIP_DIGICARD, &hc->chip) && (hc->chan[ch].slot_rx < 0) && (hc->chan[ch].bank_rx == 0)
|
||||
&& (hc->chan[ch].slot_tx < 0) && (hc->chan[ch].bank_tx == 0)) {
|
||||
|
||||
printk("Setting B-channel %d to echo cancelable state on PCM slot %d\n", ch,
|
||||
((ch/4)*8) + ((ch%4)*4) + 1);
|
||||
printk("Enabling pass through for channel\n");
|
||||
vpm_out(hc, ch, ((ch/4)*8) + ((ch%4)*4) + 1, 0x01);
|
||||
/* rx path */
|
||||
/* S/T -> PCM */
|
||||
HFC_outb(hc, R_FIFO, (ch << 1));
|
||||
HFC_wait(hc);
|
||||
HFC_outb(hc, A_CON_HDLC, 0xc0 | V_HDLC_TRP | V_IFF);
|
||||
HFC_outb(hc, R_SLOT, (((ch/4)*8) + ((ch%4)*4) + 1) << 1);
|
||||
HFC_outb(hc, A_SL_CFG, 0x80 | (ch << 1));
|
||||
|
||||
/* PCM -> FIFO */
|
||||
HFC_outb(hc, R_FIFO, 0x20 | (ch << 1) | 1);
|
||||
HFC_wait(hc);
|
||||
HFC_outb(hc, A_CON_HDLC, 0x20 | V_HDLC_TRP | V_IFF);
|
||||
HFC_outb(hc, A_SUBCH_CFG, 0);
|
||||
HFC_outb(hc, A_IRQ_MSK, 0);
|
||||
HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
|
||||
HFC_wait(hc);
|
||||
HFC_outb(hc, R_SLOT, ((((ch/4)*8) + ((ch%4)*4) + 1) << 1) | 1);
|
||||
HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1) | 1);
|
||||
|
||||
/* tx path */
|
||||
/* PCM -> S/T */
|
||||
HFC_outb(hc, R_FIFO, (ch << 1) | 1);
|
||||
HFC_wait(hc);
|
||||
HFC_outb(hc, A_CON_HDLC, 0xc0 | V_HDLC_TRP | V_IFF);
|
||||
HFC_outb(hc, R_SLOT, ((((ch/4)*8) + ((ch%4)*4)) << 1) | 1);
|
||||
HFC_outb(hc, A_SL_CFG, 0x80 | 0x40 | (ch << 1) | 1);
|
||||
|
||||
/* FIFO -> PCM */
|
||||
HFC_outb(hc, R_FIFO, 0x20 | (ch << 1));
|
||||
HFC_wait(hc);
|
||||
HFC_outb(hc, A_CON_HDLC, 0x20 | V_HDLC_TRP | V_IFF);
|
||||
HFC_outb(hc, A_SUBCH_CFG, 0);
|
||||
HFC_outb(hc, A_IRQ_MSK, 0);
|
||||
HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
|
||||
HFC_wait(hc);
|
||||
HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence); /* tx silence */
|
||||
HFC_outb(hc, R_SLOT, (((ch/4)*8) + ((ch%4)*4)) << 1);
|
||||
HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1));
|
||||
} else {
|
||||
/* enable TX fifo */
|
||||
HFC_outb(hc, R_FIFO, ch<<1);
|
||||
HFC_wait(hc);
|
||||
HFC_outb(hc, A_CON_HDLC, flow_tx | 0x00 | V_HDLC_TRP | V_IFF);
|
||||
HFC_outb(hc, A_SUBCH_CFG, 0);
|
||||
HFC_outb(hc, A_IRQ_MSK, 0);
|
||||
HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
|
||||
HFC_wait(hc);
|
||||
HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence); /* tx silence */
|
||||
/* enable RX fifo */
|
||||
HFC_outb(hc, R_FIFO, (ch<<1)|1);
|
||||
HFC_wait(hc);
|
||||
HFC_outb(hc, A_CON_HDLC, flow_rx | 0x00 | V_HDLC_TRP);
|
||||
HFC_outb(hc, A_SUBCH_CFG, 0);
|
||||
HFC_outb(hc, A_IRQ_MSK, 0);
|
||||
HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
|
||||
HFC_wait(hc);
|
||||
}
|
||||
if (hc->type != 1) {
|
||||
hc->hw.a_st_ctrl0[hc->chan[ch].port] |= ((ch&0x3)==0)?V_B1_EN:V_B2_EN;
|
||||
HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
|
||||
|
@ -2094,7 +2518,9 @@ handle_dmsg(channel_t *ch, struct sk_buff *skb)
|
|||
__FUNCTION__, hc->chan[ch->channel].port, hc->type-1);
|
||||
spin_lock_irqsave(ch->inst.hwlock, flags);
|
||||
hw_deactivate:
|
||||
ch->state = 0;
|
||||
//ch->state = 0;
|
||||
ch->state = 1;
|
||||
|
||||
/* start deactivation */
|
||||
if (hc->type == 1) {
|
||||
if (debug & DEBUG_HFCMULTI_MSG)
|
||||
|
@ -2160,6 +2586,7 @@ handle_bmsg(channel_t *ch, struct sk_buff *skb)
|
|||
int slot_tx, slot_rx, bank_tx, bank_rx;
|
||||
int ret = -EAGAIN;
|
||||
struct dsp_features *features;
|
||||
int taps;
|
||||
|
||||
if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
|
||||
(hh->prim == (DL_ESTABLISH | REQUEST))) {
|
||||
|
@ -2255,6 +2682,10 @@ handle_bmsg(channel_t *ch, struct sk_buff *skb)
|
|||
features->pcm_id = hc->pcm;
|
||||
features->pcm_slots = hc->slots;
|
||||
features->pcm_banks = 2;
|
||||
|
||||
if (test_bit(HFC_CHIP_DIGICARD, &hc->chip))
|
||||
features->hfc_echocanhw=1;
|
||||
|
||||
ret = 0;
|
||||
break;
|
||||
case HW_PCM_CONN: /* connect interface to pcm timeslot (0..N) */
|
||||
|
@ -2323,6 +2754,24 @@ handle_bmsg(channel_t *ch, struct sk_buff *skb)
|
|||
ret = 0;
|
||||
break;
|
||||
|
||||
case HW_ECHOCAN_ON:
|
||||
|
||||
if (skb->len < sizeof(u32)) {
|
||||
printk(KERN_WARNING "%s: HW_ECHOCAN_ON lacks parameters\n",
|
||||
__FUNCTION__);
|
||||
}
|
||||
|
||||
taps = ((u32 *)skb->data)[0];
|
||||
|
||||
vpm_echocan_on(hc, ch->channel, taps);
|
||||
ret=0;
|
||||
break;
|
||||
|
||||
case HW_ECHOCAN_OFF:
|
||||
vpm_echocan_off(hc, ch->channel);
|
||||
ret=0;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_DEBUG "%s: unknown PH_CONTROL info %x\n",
|
||||
__FUNCTION__, hh->dinfo);
|
||||
|
@ -2750,7 +3199,7 @@ init_card(hfc_multi_t *hc)
|
|||
}
|
||||
printk(KERN_WARNING "HFC PCI: IRQ(%d) getting no interrupts during init (try %d)\n", hc->irq, cnt);
|
||||
|
||||
if (test_bit(HFC_CHIP_CLOCK_IGNORE, &hc->chip)) {
|
||||
if (test_bit(HFC_CHIP_CLOCK_IGNORE, &hc->chip) || test_bit(HFC_CHIP_DIGICARD, &hc->chip)) {
|
||||
printk(KERN_WARNING "HFC PCI: Ignoring Clock so we go on here\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -2871,6 +3320,12 @@ setup_pci(hfc_multi_t *hc, struct pci_dev *pdev, int id_idx)
|
|||
hc->pci_dev = pdev;
|
||||
if (id_list[id_idx].clock2)
|
||||
test_and_set_bit(HFC_CHIP_CLOCK2, &hc->chip);
|
||||
|
||||
#if 1
|
||||
if (id_list[id_idx].device_id == 0xB410)
|
||||
test_and_set_bit(HFC_CHIP_DIGICARD, &hc->chip);
|
||||
#endif
|
||||
|
||||
if (hc->pci_dev->irq <= 0) {
|
||||
printk(KERN_WARNING "HFC-multi: No IRQ for PCI card found.\n");
|
||||
return (-EIO);
|
||||
|
@ -3662,6 +4117,7 @@ static int __devinit hfcpci_probe(struct pci_dev *pdev, const struct pci_device_
|
|||
|
||||
if (debug & DEBUG_HFCMULTI_INIT)
|
||||
printk(KERN_DEBUG "%s: Init modes card(%d)\n", __FUNCTION__, HFC_idx+1);
|
||||
|
||||
hfcmulti_initmode(hc);
|
||||
|
||||
/* check if Port Jumper config matches module param 'protocol' */
|
||||
|
@ -3679,6 +4135,9 @@ static int __devinit hfcpci_probe(struct pci_dev *pdev, const struct pci_device_
|
|||
// Port mode (TE/NT) jumpers
|
||||
pmj = ((HFC_inb(hc, R_GPI_IN3) >> 4) & 0xf);
|
||||
|
||||
if (test_bit(HFC_CHIP_DIGICARD, &hc->chip))
|
||||
pmj = ~pmj & 0xf;
|
||||
|
||||
printk(KERN_INFO "%s: DIPs(0x%x) jumpers(0x%x)\n", __FUNCTION__, dips, pmj);
|
||||
|
||||
pt = 0;
|
||||
|
@ -3842,6 +4301,7 @@ static struct pci_device_id hfmultipci_ids[] __devinitdata = {
|
|||
{ CCAG_VID, 0x08B4 , CCAG_VID, 0x08B4, 0, 0, 0 }, //Old Eval
|
||||
{ CCAG_VID, 0x08B4 , CCAG_VID, 0xB520, 0, 0, 0 }, //IOB4ST
|
||||
{ CCAG_VID, 0x08B4 , CCAG_VID, 0xB620, 0, 0, 0 }, //4S
|
||||
{ 0xD161, 0xB410 , 0xD161, 0xB410, 0, 0, 0 }, //4S - Digium
|
||||
|
||||
/** Cards with HFC-8S Chip**/
|
||||
{ CCAG_VID, 0x16B8 , CCAG_VID, 0xB562, 0, 0, 0 }, //BN8S
|
||||
|
|
|
@ -99,6 +99,8 @@ typedef struct hfcmulti_hw hfcmulti_hw_t;
|
|||
#define HFC_CHIP_CRYSTAL_CLOCK 9 /* autarc clocking mode */
|
||||
#define HFC_CHIP_WATCHDOG 10 /* wether we should send signals
|
||||
to the watchdog */
|
||||
#define HFC_CHIP_DIGICARD 11 /* wether we have a b410p with echocan in
|
||||
hw */
|
||||
|
||||
struct hfc_multi {
|
||||
struct list_head list;
|
||||
|
@ -1235,31 +1237,37 @@ static void _HFC_wait(hfc_multi_t *a, char *function, int line)
|
|||
#endif
|
||||
|
||||
/* usage: HFC_outX(card,register,value); */
|
||||
static inline void HFC_outb(hfc_multi_t *a, u_char b, u_char c)
|
||||
static inline void HFC_outb(hfc_multi_t *a, unsigned short b, u_char c)
|
||||
{
|
||||
outb(b,(a->pci_iobase)+4);
|
||||
outw(b,(a->pci_iobase)+4);
|
||||
outb(c,a->pci_iobase);
|
||||
}
|
||||
static inline void HFC_outl(hfc_multi_t *a, u_char b, u_long c)
|
||||
static inline void HFC_outl(hfc_multi_t *a, unsigned short b, u_long c)
|
||||
{
|
||||
outb(b,(a->pci_iobase)+4);
|
||||
outw(b,(a->pci_iobase)+4);
|
||||
outl(c,a->pci_iobase);
|
||||
}
|
||||
|
||||
/* usage: value=HFC_inX(card,register); */
|
||||
static inline u_char HFC_inb(hfc_multi_t *a, u_char b)
|
||||
static inline void HFC_outw(hfc_multi_t *a, unsigned short b, u_long c)
|
||||
{
|
||||
outb(b,(a->pci_iobase)+4);
|
||||
outw(b,(a->pci_iobase)+4);
|
||||
outw(c,a->pci_iobase);
|
||||
}
|
||||
|
||||
/* usage: value=HFC_inX(card,register); */
|
||||
static inline u_char HFC_inb(hfc_multi_t *a, unsigned short b)
|
||||
{
|
||||
outw(b,(a->pci_iobase)+4);
|
||||
return (inb((volatile u_int)a->pci_iobase));
|
||||
}
|
||||
static inline u_short HFC_inw(hfc_multi_t *a, u_char b)
|
||||
static inline u_short HFC_inw(hfc_multi_t *a, unsigned short b)
|
||||
{
|
||||
outb(b,(a->pci_iobase)+4);
|
||||
outw(b,(a->pci_iobase)+4);
|
||||
return (inw((volatile u_int)a->pci_iobase));
|
||||
}
|
||||
static inline u_long HFC_inl(hfc_multi_t *a, u_char b)
|
||||
static inline u_long HFC_inl(hfc_multi_t *a, unsigned short b)
|
||||
{
|
||||
outb(b,(a->pci_iobase)+4);
|
||||
outw(b,(a->pci_iobase)+4);
|
||||
return (inl((volatile u_int)a->pci_iobase));
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ mISDN_unregister_sysfs_inst(mISDNinstance_t *inst)
|
|||
{
|
||||
char name[8];
|
||||
|
||||
if (inst->id) {
|
||||
if (inst && inst->id) {
|
||||
if (inst->st) {
|
||||
sprintf(name,"layer.%d", inst->id & LAYER_ID_MASK);
|
||||
|
||||
|
|
|
@ -238,11 +238,13 @@ mISDN_register_sysfs_stack(mISDNstack_t *st)
|
|||
mISDNstack_attr_parameter_new_pid.store = store_st_parameter;
|
||||
mISDNstack_attr_layermask_new_pid.attr.mode |= S_IWUSR;
|
||||
mISDNstack_attr_layermask_new_pid.store = store_st_layermask;
|
||||
|
||||
#ifdef SYSFS_SUPPORT
|
||||
err = sysfs_create_group(&st->class_dev.kobj, &new_pid_group);
|
||||
if (err)
|
||||
goto out_unreg;
|
||||
#endif
|
||||
|
||||
class_device_create_file(&st->class_dev, &class_device_attr_id);
|
||||
class_device_create_file(&st->class_dev, &class_device_attr_qlen);
|
||||
class_device_create_file(&st->class_dev, &class_device_attr_status);
|
||||
|
|
|
@ -158,6 +158,8 @@
|
|||
#define HW_RECEIVE_ON 0x0585
|
||||
#define HW_SPL_LOOP_ON 0x0586
|
||||
#define HW_SPL_LOOP_OFF 0x0587
|
||||
#define HW_ECHOCAN_ON 0x0588
|
||||
#define HW_ECHOCAN_OFF 0x0589
|
||||
#define HW_TESTLOOP 0xFF00
|
||||
#define HW_FIRM_START 0xFF10
|
||||
#define HW_FIRM_DATA 0xFF11
|
||||
|
|
|
@ -390,6 +390,11 @@ function create_misdn_init_conf {
|
|||
|
||||
portcount=0
|
||||
|
||||
for line in $(${LSPCI} -n -d 0xd161:b410); do
|
||||
addcard "0x4"
|
||||
addport 4
|
||||
done
|
||||
|
||||
for line in $(${LSPCI} -n | sed -n 's/^\(0000:\|\)\([0-9a-f]\{2\}:[0-9a-f]\{2\}.[0-9a-f]\{1\}\)\( Class \| \)[0-9a-f]\{4\}: 1397:\([0-9a-f]\{4\}\).*$/\4 \2/p'); do
|
||||
case "${line}" in
|
||||
30b1*)
|
||||
|
@ -524,6 +529,7 @@ function create_misdn_init_conf {
|
|||
#
|
||||
# set this to 2 and you'll have software bridging instead of
|
||||
# hardware bridging.
|
||||
#
|
||||
#
|
||||
# dtmftreshold=<milliseconds>
|
||||
#
|
||||
|
@ -582,7 +588,6 @@ case "$1" in
|
|||
|
||||
echo "modprobe mISDN_dsp debug=0x0 options=$dsp_options $poll_option $dtmftreshold_option"
|
||||
modprobe mISDN_dsp debug=0x0 options=$dsp_options $poll_option $dtmftreshold_option
|
||||
|
||||
sleep 1
|
||||
|
||||
if [ ! -e /dev/mISDN ]; then
|
||||
|
|
Loading…
Reference in New Issue