--- originales/base.c 2008-12-17 15:57:56.000000000 +0000 +++ base.c 2009-02-23 01:33:05.000000000 +0000 @@ -110,9 +110,16 @@ static struct proc_dir_entry *myproc; struct devtype { char *desc; unsigned int flags; + int ports; + int has_ec; }; -static struct devtype wcb4xxp = { "Wildcard B410P", 0 }; +static struct devtype wcb4xxp = { "Wildcard B410P", .ports = 4, .has_ec = 1 }; +static struct devtype hfc4s = { "HFC-4S Junghanns.NET quadBRI PCI", .ports = 4 }; +static struct devtype hfc2s = { "HFC-2S Junghanns.NET duoBRI PCI", .ports = 2 }; +static struct devtype hfc2s_OV ={ "OpenVox B200P", .ports = 2 }; +static struct devtype hfc4s_OV ={ "OpenVox B400P", .ports = 4 }; +static struct devtype hfc8s_OV ={ "OpenVox B800P", .ports = 8 }; #if 0 @@ -600,13 +607,16 @@ static void ec_init(struct b4xxp *b4) unsigned char b; unsigned int i, j, mask; + if (! b4->has_ec) + return; + /* Setup GPIO */ for (i=0; i < NUM_EC; i++) { b = ec_read(b4, i, 0x1a0); dev_info(b4->dev, "VPM %d/%d init: chip ver %02x\n", i, NUM_EC - 1, b); - for (j=0; j < 4; j++) { + for (j=0; j < b4->numspans; j++) { ec_write(b4, i, 0x1a8 + j, 0x00); /* GPIO out */ ec_write(b4, i, 0x1ac + j, 0x00); /* GPIO dir */ ec_write(b4, i, 0x1b0 + j, 0x00); /* GPIO sel */ @@ -625,7 +635,7 @@ static void ec_init(struct b4xxp *b4) mask = 0x02020202 << (i * 4); /* Setup the tdm channel masks for all chips*/ - for (j=0; j < 4; j++) + for (j=0; j < b4->numspans; j++) ec_write(b4, i, 0x33 - j, (mask >> (j << 3)) & 0xff); /* Setup convergence rate */ @@ -863,7 +873,8 @@ static void hfc_assign_bchan_fifo_ec(str if (first) { first = 0; - dev_info(b4->dev, "Hardware echo cancellation enabled.\n"); + if (b4->has_ec) + dev_info(b4->dev, "Hardware echo cancellation enabled.\n"); } fifo = port * 2; @@ -1192,7 +1203,7 @@ static void hfc_update_st_timers(struct int i, j; struct b4xxp_span *s; - for (i=0; i < 4; i++) { + for (i=0; i < b4->numspans; i++) { s = &b4->spans[i]; for (j=HFC_T1; j <= HFC_T3; j++) { @@ -1394,12 +1405,12 @@ static void hfc_init_all_st(struct b4xxp gpio = b4xxp_getreg8(b4, R_GPI_IN3); - for (i=0; i < 4; i++) { + for (i=0; i < b4->numspans; i++) { s = &b4->spans[i]; s->parent = b4; s->port = i; - nt = ((gpio & (1 << (i + 4))) == 0); /* GPIO=0 = NT mode */ + nt = ((gpio & (1 << (i + 4))) != 0); /* GPIO=0 = NT mode */ s->te_mode = !nt; dev_info(b4->dev, "Port %d: %s mode\n", i + 1, (nt ? "NT" : "TE")); @@ -1757,7 +1768,15 @@ static void b4xxp_init_stage1(struct b4x * set up the clock controller * we have a 24.576MHz crystal, so the PCM clock is 2x the incoming clock. */ - b4xxp_setreg8(b4, R_BRG_PCM_CFG, 0x02); + + if (b4->has_ec) + { + b4xxp_setreg8(b4, R_BRG_PCM_CFG,0x02); + } + else + { + b4xxp_setreg8(b4, R_BRG_PCM_CFG, V_PCM_CLK); + } flush_pci(); udelay(100); /* wait a bit for clock to settle */ @@ -1774,14 +1793,6 @@ static void b4xxp_init_stage2(struct b4x { int span; -/* - * set up PCM bus. - * HFC is PCM master. - * C4IO, SYNC_I and SYNC_O unused. - * 32 channels, frame signal positive polarity, active for 2 C4 clocks. - * only the first two timeslots in each quad are active - * STIO0 is transmit-only, STIO1 is receive-only. - */ b4xxp_setreg8(b4, R_PCM_MD0, V_PCM_MD | V_PCM_IDX_MD1); flush_pci(); b4xxp_setreg8(b4, R_PCM_MD1, V_PLL_ADJ_00 | V_PCM_DR_2048); @@ -1833,6 +1844,7 @@ static void b4xxp_init_stage2(struct b4x static void b4xxp_setleds(struct b4xxp *b4, unsigned char val) { ec_write(b4, 0, 0x1a8 + 3, val); + } static void b4xxp_set_span_led(struct b4xxp *b4, int span, unsigned char val) @@ -1847,11 +1859,94 @@ static void b4xxp_set_span_led(struct b4 b4xxp_setleds(b4, b4->ledreg); } +static void b4xxp_update_leds_HFC(struct b4xxp *b4) +{ + unsigned long lled; + unsigned long leddw; + int i, leds; + int led[4]; + struct b4xxp_span *bspan; + lled = 0; + + b4->blinktimer++; + for (i=0; i < b4->numspans; i++) { + bspan = &b4->spans[i]; + + if (bspan->span.flags & DAHDI_FLAG_RUNNING) { + if (bspan->span.alarms) { + if (b4->blinktimer == (led_fader_table[b4->alarmpos] >> 1)) + led[i] = 2; + lled |= 0 << i; + if (b4->blinktimer == 0xf) + led[i] = 0; + lled |= 1 << i; + } else if (bspan->span.mainttimer || bspan->span.maintstat) { + if (b4->blinktimer == (led_fader_table[b4->alarmpos] >> 1)) + led[i] = 1; + lled |= 0 << i; + if (b4->blinktimer == 0xf) + led[i] = 0; + lled |= 1 << i; + } else { + /* No Alarm */ + led[i] = 1; + lled |= 0 << i; + } + } else + led[i] = 0; + lled |=1 << i; + + } + + if (b4->numspans == 4) + { + leds = ((led[3] > 0) << 0) | ((led[1] > 0) << 1) | + ((led[0] > 0) << 2) | ((led[2] > 0) << 3) | + ((led[3] & 1) << 4) | ((led[1] & 1) << 5) | + ((led[0] & 1) << 6) | ((led[2] & 1) << 7); + b4xxp_setreg8(b4, R_GPIO_EN1, leds & 0x0f); + b4xxp_setreg8(b4, R_GPIO_OUT1, leds >> 4); + } + + if (b4->numspans == 2) + { + b4xxp_setreg8(b4, R_GPIO_SEL,0x20 | 0x10); + b4xxp_setreg8(b4, R_GPIO_EN1,0xf); + b4xxp_setreg8(b4, R_GPIO_OUT1,(led[0] | (led[1] << 1) | (led[2] << 2) | (led[3] << 3))); + } + + if (b4->numspans == 8) + { + leddw = lled << 24 | lled << 16 | lled << 8 | lled; + b4xxp_setreg8(b4, R_BRG_PCM_CFG, 0x21); + iowrite16(0x4000, b4->ioaddr + 4); + iowrite32(leddw, b4->ioaddr); + b4xxp_setreg8(b4, R_BRG_PCM_CFG, 0x20); + } + + if (b4->blinktimer == 0xf) { + b4->blinktimer = -1; + b4->alarmpos++; + if (b4->alarmpos >= (sizeof(led_fader_table) / sizeof(led_fader_table[0]))) + b4->alarmpos = 0; + } + + + +} + + static void b4xxp_update_leds(struct b4xxp *b4) { int i; struct b4xxp_span *bspan; + if (!b4->has_ec) /* Goto Modified Function */ + { + b4xxp_update_leds_HFC(b4); + return; + } + b4->blinktimer++; for (i=0; i < b4->numspans; i++) { bspan = &b4->spans[i]; @@ -1883,6 +1978,8 @@ static void b4xxp_update_leds(struct b4x } } + + static int b4xxp_echocan(struct dahdi_chan *chan, int eclen) { struct b4xxp *b4 = chan->pvt; @@ -2138,7 +2235,7 @@ static void init_spans(struct b4xxp *b4) bspan->span.close = b4xxp_close; bspan->span.ioctl = b4xxp_ioctl; bspan->span.hdlc_hard_xmit = b4xxp_hdlc_hard_xmit; - if (vpmsupport) + if (vpmsupport && b4->has_ec) bspan->span.echocan = b4xxp_echocan; /* HDLC stuff */ @@ -2388,7 +2485,7 @@ static int b4xxp_proc_read_one(char *buf } strcat(sBuf, "\nPort states:\n"); - for (i=0; i < 4; i++) { + for (i=0; i < b4->numspans; i++) { int state; char *x; struct b4xxp_span *s = &b4->spans[i]; @@ -2483,6 +2580,7 @@ static int __devinit b4xx_probe(struct p /* card found, enabled and main struct allocated. Fill it out. */ b4->magic = WCB4XXP_MAGIC; b4->variety = dt->desc; + b4->has_ec = dt->has_ec; b4->pdev = pdev; b4->dev = &pdev->dev; @@ -2512,7 +2610,8 @@ static int __devinit b4xx_probe(struct p */ /* TODO: determine whether this is a 2, 4 or 8 port card */ - b4->numspans = 4; + b4->numspans = dt->ports; + vpmsupport = dt->has_ec; b4->syncspan = -1; /* sync span is unknown */ if (b4->numspans > MAX_SPANS_PER_CARD) { dev_err(b4->dev, "Driver does not know how to handle a %d span card!\n", b4->numspans); @@ -2660,6 +2759,11 @@ static void __devexit b4xxp_remove(struc static struct pci_device_id b4xx_ids[] __devinitdata = { { 0xd161, 0xb410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb4xxp }, + { 0x1397, 0x08b4, 0x1397, 0xb520, 0, 0, (unsigned long)&hfc4s }, + { 0x1397, 0x08b4, 0x1397, 0xb556, 0, 0, (unsigned long)&hfc2s }, + { 0x1397, 0x08b4, 0x1397, 0xe884, 0, 0, (unsigned long)&hfc2s_OV }, + { 0x1397, 0x08b4, 0x1397, 0xe888, 0, 0, (unsigned long)&hfc4s_OV }, + { 0x1397, 0x08b4, 0x1397, 0xe998, 0, 0, (unsigned long)&hfc8s_OV }, { 0, } }; @@ -2719,7 +2823,7 @@ MODULE_PARM_DESC(timer_1_ms, "NT: msec t MODULE_PARM_DESC(timer_3_ms, "TE: msec to wait for link activation, NT: unused."); MODULE_AUTHOR("Digium Incorporated "); -MODULE_DESCRIPTION("B410P quad-port BRI module driver."); +MODULE_DESCRIPTION("B410P & Similars multi-port BRI module driver."); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, b4xx_ids);