--- old_base.c	2008-12-17 23:57:56.000000000 +0800
+++ base.c	2009-02-24 14:51:45.000000000 +0800
@@ -110,9 +110,16 @@
 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 @@
 	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 @@
 		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 @@
 
 	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 @@
 	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,19 @@
 
 	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;
 
+		if (b4->has_ec)
+		{
 		nt = ((gpio & (1 << (i + 4))) == 0);		/* GPIO=0 = NT mode */
+		}
+		else
+		{
+		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 +1775,15 @@
  * 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 +1800,6 @@
 {
 	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 +1851,77 @@
 static void b4xxp_setleds(struct b4xxp *b4, unsigned char val)
 {
 	ec_write(b4, 0, 0x1a8 + 3, val);
+
+}
+
+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;
+}
+	
+	if (b4->numspans == 4) 
+	    {
+	    leds = ((led[0] > 0) << 0) | ((led[1] > 0) << 1) | ((led[2] > 0) << 2) | ((led[3] > 0) << 3) | ((led[0] & 1) << 4) | ((led[1] & 1) << 5) |
+	   ((led[2] & 1) << 6) | ((led[3] & 1) << 7); /* changed by james.zhu to set the leds of B400P */
+	    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_set_span_led(struct b4xxp *b4, int span, unsigned char val)
@@ -1847,11 +1936,18 @@
 	b4xxp_setleds(b4, b4->ledreg);
 }
 
+
 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 +1979,8 @@
 	}
 }
 
+
+
 static int b4xxp_echocan(struct dahdi_chan *chan, int eclen)
 {
 	struct b4xxp *b4 = chan->pvt;
@@ -2138,7 +2236,7 @@
 		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 +2486,7 @@
 	}
 
 	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 +2581,7 @@
 /* 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 +2611,8 @@
 */
 
 /* 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 +2760,11 @@
 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 +2824,7 @@
 MODULE_PARM_DESC(timer_3_ms, "TE: msec to wait for link activation, NT: unused.");
 
 MODULE_AUTHOR("Digium Incorporated <support@digium.com>");
-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);
