[Pkg-voip-commits] r3042 - in zaptel/trunk: cwain debian debian/patches qozap ztgsm

Tzafrir Cohen tzafrir-guest at alioth.debian.org
Sat Jan 20 20:53:31 CET 2007


Author: tzafrir-guest
Date: 2007-01-20 20:53:28 +0100 (Sat, 20 Jan 2007)
New Revision: 3042

Modified:
   zaptel/trunk/cwain/Makefile
   zaptel/trunk/cwain/cwain.c
   zaptel/trunk/cwain/cwain.h
   zaptel/trunk/debian/changelog
   zaptel/trunk/debian/patches/bristuff.dpatch
   zaptel/trunk/qozap/qozap.c
   zaptel/trunk/ztgsm/ztgsm.c
Log:
Bristuff 0.3.0-PRE-1x


Modified: zaptel/trunk/cwain/Makefile
===================================================================
--- zaptel/trunk/cwain/Makefile	2007-01-19 22:30:20 UTC (rev 3041)
+++ zaptel/trunk/cwain/Makefile	2007-01-20 19:53:28 UTC (rev 3042)
@@ -3,7 +3,9 @@
 
 ZAP = $(shell [ -f $(BRISTUFFBASE)/zaptel/zaptel.h ] && echo "-I$(BRISTUFFBASE)/zaptel")
 
-CFLAGS+=-I. $(ZAP) -DRELAXED_LOCKING -O2 -g -Wall #-DBLINKYBLINK
+HOSTCC=gcc
+
+CFLAGS+=-I. $(ZAP) -DRELAXED_LOCKING -O4 -g -Wall #-DBLINKYBLINK
 CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi)
 
 KFLAGS=-D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -DRELAXED_LOCKING -fomit-frame-pointer -O2 -Wall -I$(KINCLUDES) $(ZAP) 

Modified: zaptel/trunk/cwain/cwain.c
===================================================================
--- zaptel/trunk/cwain/cwain.c	2007-01-19 22:30:20 UTC (rev 3041)
+++ zaptel/trunk/cwain/cwain.c	2007-01-20 19:53:28 UTC (rev 3042)
@@ -21,10 +21,18 @@
 #include <zaptel.h>
 #include "cwain.h"
 
+#ifdef LINUX26
+#include <linux/moduleparam.h>
+#endif
+
 #if CONFIG_PCI
 
 static int ports=-1; /* autodetect */
 static int debug=0;
+static int hw_hdlc=0;
+static int pwm0 = 0x50;	/* TX level */
+static int pwm1 = 0xff; /* RX level */
+static int dacs = 0; /* 0 = no dacs, 1 = oncard dacs */
 static struct zt_cwain *cwain_span_list = NULL;
 static int cwain_span_count = 0;
 static struct zt_cwain_card *cwain_card_list = NULL;
@@ -97,8 +105,6 @@
 	cwainspan->pcidev = NULL;
     }
 
-//    iounmap((void *) cwainspan->pci_io);
-//    cwainspan->pci_io = NULL;
 }
 
 void cwain_shutdown_card(struct zt_cwain_card *cwaintmp) {
@@ -110,21 +116,19 @@
 	return;
     }
 
-    for (i=0;i<cwaintmp->spans;i++) {
-	cwain_unregister_zap_span(cwaintmp->span[i]);
-    }
-
     spin_lock_irqsave(&cwaintmp->lock,flags);
 
     // turn off irqs
     cwain_outb(cwaintmp->span[0],cwain_R_IRQ_CTRL, 0); 
     cwain_outb(cwaintmp->span[0],cwain_R_IRQMSK_MISC, 0); 
 
+    spin_unlock_irqrestore(&cwaintmp->lock,flags);
+
     for (i=0;i<cwaintmp->spans;i++) {
-	cwain_shutdown_span(cwaintmp->span[i]);
+	cwain_unregister_zap_span(cwaintmp->span[i]);
     }
-    spin_unlock_irqrestore(&cwaintmp->lock,flags);
 
+
     for (i=0;i<cwaintmp->spans;i++) {
 	release_region(cwaintmp->span[i]->ioport, 8);
 	cwaintmp->span[i]->ioport = 0;
@@ -177,6 +181,7 @@
 
 void cwain_reset_span(struct zt_cwain *cwaintmp) {
     int i = 0;
+
     pci_write_config_word(cwaintmp->pcidev, PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_IO);	// enable memio
 
     /* FIFO, HDLC reset */
@@ -189,7 +194,7 @@
     cwain_outb(cwaintmp,cwain_R_CIRM,0x0); 
     cwain_waitbusy(cwaintmp);
 
-    for (i=0; i<128; i++) {
+    for (i=0; i<256; i++) {
 	cwain_outb(cwaintmp,cwain_R_SLOT, i);
 	cwain_outb(cwaintmp,cwain_A_SL_CFG, 0x0);
     }
@@ -328,12 +333,14 @@
     int chan = 15;
     int x=0;
     char fifo = 0;
+    unsigned long flags = 0;
 
     fifo = 0x1F;
 
     if (cwaintmp->chans[chan].bytes2transmit < 1) {
 	return 0;
     } else {
+	spin_lock_irqsave(&cwaintmp->lock,flags);
 	/* select fifo */
 	cwain_outb(cwaintmp,cwain_R_FIFO,fifo << 1);    
 	cwain_waitbusy(cwaintmp);
@@ -356,24 +363,28 @@
     	    cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x1);    
     	    cwain_waitbusy(cwaintmp);
 	}
+	spin_unlock_irqrestore(&cwaintmp->lock,flags);
     }
     return 0;
 }
 
 static int cwain_fifo_tx(struct zt_cwain *cwaintmp, char fifo) {
     int chan,f;
+    unsigned long flags = 0;
     if (fifo >= 15) {
 	chan = fifo;
     } else {
 	chan = fifo;
     }
-    /* select fifo */
-    cwain_outb(cwaintmp,cwain_R_FIFO,0x80 | (fifo << 1));    
-    cwain_waitbusy(cwaintmp);
+    spin_lock_irqsave(&cwaintmp->lock,flags);
+	/* select fifo */
+	cwain_outb(cwaintmp,cwain_R_FIFO,0x80 | (fifo << 1));    
+	cwain_waitbusy(cwaintmp);
     
-    for (f=0; f < (cwain_FRAME_SIZE/4); f++) {
-	cwain_outdw(cwaintmp,cwain_A_FIFO_DATA0,*((unsigned int *) &cwaintmp->ftxbuf[chan][f * 4]));
-    }
+	for (f=0; f < (cwain_FRAME_SIZE/4); f++) {
+	    cwain_outdw(cwaintmp,cwain_A_FIFO_DATA0,*((unsigned int *) &cwaintmp->ftxbuf[chan][f * 4]));
+	}
+    spin_unlock_irqrestore(&cwaintmp->lock,flags);
     return 0;
 }
 
@@ -385,9 +396,11 @@
     unsigned short z1=1,z2=1;
     unsigned short oz1=0,oz2=0;
     char fifo = 0;
+    unsigned long flags = 0;
 
     fifo = 0x1F;
     
+    spin_lock_irqsave(&cwaintmp->lock,flags);
     /* select fifo */
     cwain_outb(cwaintmp,cwain_R_FIFO,(fifo << 1) | 1);    
     cwain_waitbusy(cwaintmp);
@@ -442,10 +455,10 @@
 
     /* frame received */
     cwaintmp->drx--;
+    spin_unlock_irqrestore(&cwaintmp->lock,flags);
     return 0;
 }
 
-
 static int cwain_fifo_rx(struct zt_cwain *cwaintmp, char fifo) {
     int chan;
     unsigned int data;
@@ -453,12 +466,14 @@
     unsigned short z1=1,z2=1;
     unsigned short oz1=0,oz2=0;
     int mumbojumbo=0;
+    unsigned long flags = 0;
     int x = 1000;
 
     chan = fifo;
 
     // select rx fifo
     
+    spin_lock_irqsave(&cwaintmp->lock,flags);
 	// no hdlc, transparent data
 	cwain_outb(cwaintmp,cwain_R_FIFO,0x80 | (fifo << 1) | 1);    
         cwain_waitbusy(cwaintmp);
@@ -493,6 +508,7 @@
 	    if ((cwaintmp->clicks > 600) && (cwaintmp->span.alarms == ZT_ALARM_NONE)) {
 		printk(KERN_INFO "cwain: not enough to receive (%d bytes)\n",len);
 	    }
+	    spin_unlock_irqrestore(&cwaintmp->lock,flags);
 	    return 0;
 	} else {
 	    for (f=0;f<(cwain_FRAME_SIZE / 4);f++) {
@@ -507,28 +523,31 @@
 	    cwaintmp->clicks = 0;
 	}
 //    printk(KERN_INFO "s/t port %d, channel %d, dbufi=%d, f1=%d, f2=%d, z1=%d, z2=%d  => len = %d stat=%#x, hdlc=%d\n",stport,chan,cwaintmp->st[stport].dbufi,f1,f2,z1,z2,len,stat,hdlc);    
+    spin_unlock_irqrestore(&cwaintmp->lock,flags);
     return 0;
 }
 
 void cwain_set_master(struct zt_cwain_card *cwaintmp, int span) {
     int i=0;
+    unsigned long flags = 0;
 
     if (cwaintmp->syncsrc == span) return;
     
+    spin_lock_irqsave(&cwaintmp->lock,flags);
     for (i=0; i < cwaintmp->spans; i++) {
 	if (i != span) {
 	    if (cwaintmp->syncs[i] > 0) {
 		/* enable PCM slave mode, PCM32, synced to E1 receive */
     		cwain_outb(cwaintmp->span[i],cwain_R_PCM_MD0, 0x90);
-		cwain_outb(cwaintmp->span[i],cwain_R_PCM_MD1, 0x0);
-		cwain_outb(cwaintmp->span[span],cwain_R_PCM_MD0, 0xA0);
-		cwain_outb(cwaintmp->span[i],cwain_R_PCM_MD2, 0x00);
+		cwain_outb(cwaintmp->span[i],cwain_R_PCM_MD1, 0x20);
+		cwain_outb(cwaintmp->span[i],cwain_R_PCM_MD0, 0xA0);
+		cwain_outb(cwaintmp->span[i],cwain_R_PCM_MD2, 0x0);
 	    } else {
 		/* enable PCM slave mode, PCM32 */
     		cwain_outb(cwaintmp->span[i],cwain_R_PCM_MD0, 0x90);
-		cwain_outb(cwaintmp->span[i],cwain_R_PCM_MD1, 0x0);
-		cwain_outb(cwaintmp->span[span],cwain_R_PCM_MD0, 0xA0);
-		cwain_outb(cwaintmp->span[i],cwain_R_PCM_MD2, 0x00);
+		cwain_outb(cwaintmp->span[i],cwain_R_PCM_MD1, 0x20);
+		cwain_outb(cwaintmp->span[i],cwain_R_PCM_MD0, 0xA0);
+		cwain_outb(cwaintmp->span[i],cwain_R_PCM_MD2, 0x04 | 0x8);
 	    }
 	    cwaintmp->master[i] = 0;
 	    cwaintmp->span[i]->span.syncsrc = 0;
@@ -540,7 +559,7 @@
 	if (debug)
 	    printk(KERN_INFO "cwain: cardID %d span %d, PCM master E1 sync\n", cwaintmp->cardID, span);
 	cwain_outb(cwaintmp->span[span],cwain_R_PCM_MD0, 0x91);
-        cwain_outb(cwaintmp->span[span],cwain_R_PCM_MD1, 0x0);
+        cwain_outb(cwaintmp->span[span],cwain_R_PCM_MD1, 0x20);
 	cwain_outb(cwaintmp->span[span],cwain_R_PCM_MD0, 0xA1);
         cwain_outb(cwaintmp->span[span],cwain_R_PCM_MD2, 0x00);
 	cwaintmp->span[span]->span.syncsrc = 1;
@@ -549,7 +568,7 @@
 	if (debug)
 	    printk(KERN_INFO "cwain: cardID %d span %d, PCM master\n", cwaintmp->cardID, span);
 	cwain_outb(cwaintmp->span[span],cwain_R_PCM_MD0, 0x91);
-        cwain_outb(cwaintmp->span[span],cwain_R_PCM_MD1, 0x0);
+        cwain_outb(cwaintmp->span[span],cwain_R_PCM_MD1, 0x20);
 	cwain_outb(cwaintmp->span[span],cwain_R_PCM_MD0, 0xA1);
         cwain_outb(cwaintmp->span[span],cwain_R_PCM_MD2, 0x04);
 	cwaintmp->span[span]->span.syncsrc = 0;
@@ -557,6 +576,7 @@
     
     cwaintmp->master[span] = 1;
     cwaintmp->syncsrc = span;
+    spin_unlock_irqrestore(&cwaintmp->lock,flags);
 }
 
 void cwain_check_timing(struct zt_cwain_card *cwaintmp) {
@@ -634,42 +654,201 @@
     }
 }
 
+
+static void cwain_assign(struct zt_cwain_card *cwaincard, int src_span, int src_chan, int dst_span, int dst_chan, int timeslot, int use_pcm_bus) {
+    int dst_fifo = dst_chan - 1; 
+    int src_fifo = src_chan - 1; 
+    int src_hfc_chan = src_chan;
+    int dst_hfc_chan = dst_chan;
+    struct zt_cwain *cwain_src = NULL, *cwain_dst = NULL;
+    unsigned long flags = 0;
+
+    if (hw_hdlc) {
+	if (dst_chan > 0x10) {
+	    dst_fifo--; 
+	}
+	if (src_chan > 0x10) {
+	    src_fifo--; 
+	}
+    }
+
+    if (cwaincard) {
+	cwain_src = cwaincard->span[src_span];
+	cwain_dst = cwaincard->span[dst_span];
+    } else {
+	return;
+    }
+    
+    if (debug)
+	printk(KERN_INFO "cwain: assign(src_span %d, src_chan %d, dst_span %d, dst_chan %d, use_pcm_bus %d\n", src_span, src_chan, dst_span, dst_chan, use_pcm_bus);
+    
+    spin_lock_irqsave(&cwaincard->lock,flags);
+	cwain_outb(cwain_src,cwain_R_FIFO,(src_fifo << 1) | 1); 
+	cwain_waitbusy(cwain_src);
+	cwain_outb(cwain_src,cwain_R_INC_RES_FIFO,0x2);
+        cwain_waitbusy(cwain_src);
+        cwain_outb(cwain_src,cwain_A_CHANNEL,(src_hfc_chan << 1) | 1); 
+        cwain_outb(cwain_src,cwain_A_CON_HDLC,0xDE); 
+
+        cwain_outb(cwain_src,cwain_R_SLOT,timeslot << 1);
+	if (use_pcm_bus) {
+	    cwain_outb(cwain_src,cwain_A_SL_CFG, (src_hfc_chan << 1) | 0 | 0x80);
+	} else {
+	    cwain_outb(cwain_src,cwain_A_SL_CFG, (src_hfc_chan << 1) | 0 | 0x40);
+	}
+
+	cwain_outb(cwain_dst,cwain_R_FIFO, dst_fifo << 1);
+	cwain_waitbusy(cwain_dst);
+	cwain_outb(cwain_dst,cwain_R_INC_RES_FIFO,0x2);
+        cwain_waitbusy(cwain_dst);
+        cwain_outb(cwain_dst,cwain_A_CHANNEL,dst_hfc_chan << 1);
+        cwain_outb(cwain_dst,cwain_A_CON_HDLC,0xDE); 
+    
+        cwain_outb(cwain_dst,cwain_R_SLOT,(timeslot << 1) | 1); 
+
+        if (use_pcm_bus) {
+    	    cwain_outb(cwain_dst,cwain_A_SL_CFG, (dst_hfc_chan << 1) | 1 | 0xC0);
+	} else {
+	    cwain_outb(cwain_dst,cwain_A_SL_CFG, (dst_hfc_chan << 1) | 1 | 0x40);
+	}
+    spin_unlock_irqrestore(&cwaincard->lock,flags);
+}
+
+static void cwain_unassign(struct zt_cwain *cwaintmp, int chan, int timeslot, int lock) {
+    int fifo = chan - 1;
+    int hfc_chan = chan;
+    unsigned long flags = 0;
+
+    if (hw_hdlc && (chan > 0x10)) {
+	fifo--; 
+    }
+
+    if (lock) spin_lock_irqsave(&cwaintmp->lock,flags);
+	cwain_outb(cwaintmp,cwain_R_FIFO,(fifo << 1));
+	cwain_waitbusy(cwaintmp);
+	cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
+	cwain_waitbusy(cwaintmp);
+	cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x02);
+	cwain_outb(cwaintmp,cwain_A_CHANNEL,(hfc_chan << 1)); 
+	cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x1);
+
+	cwain_outb(cwaintmp,cwain_R_FIFO,(fifo << 1) | 1);
+	cwain_waitbusy(cwaintmp);
+	cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
+	cwain_waitbusy(cwaintmp);
+	cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x02);
+	cwain_outb(cwaintmp,cwain_A_CHANNEL,(hfc_chan << 1) | 1); 
+	cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x1);
+    if (lock) spin_unlock_irqrestore(&cwaintmp->lock,flags);
+}
+
+
+static int ztcwain_dacs(struct zt_chan *dst, struct zt_chan *src) {
+	struct zt_cwain *cwaintmp = NULL;
+	int use_pcm_bus = 0;
+	int timeslot = 0;
+	if (!dacs) return 0;
+
+	if (src) {
+		cwaintmp = src->pvt;
+
+		if ((src->pvt != dst->pvt) && (src->span->pvt != dst->span->pvt)) {
+		    if (dacs == 2) {
+			if (debug)
+			    printk("cwain: Assigning %d/%d -> %d/%d, different cards!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
+			timeslot = src->channo;
+			use_pcm_bus = 1;
+		    } else {
+			if (debug)
+			    printk("cwain: Not Assigning %d/%d -> %d/%d, different cards!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
+			return -1;
+		    }
+		} else {
+		    if (debug)
+			printk("cwain: Assigning %d/%d -> %d/%d, same cwain card!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
+		    timeslot = src->channo;
+		//    timeslot = (src->span->offset * 30) + (src->chanpos - 1);
+		    use_pcm_bus = 0;
+		}
+	
+		if (hw_hdlc && ((src->chanpos == 16) || (dst->chanpos == 16))) {
+		    if (debug)
+			printk("cwain: Not Assigning D-channel %d/%d -> %d/%d!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
+		} else {
+		    cwain_assign(src->span->pvt, src->span->offset, src->chanpos, dst->span->offset, dst->chanpos, timeslot, use_pcm_bus);
+		    if (debug)
+			printk("cwain: Assigning channel %d/%d -> %d/%d!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
+		}
+	} else {
+		cwaintmp = dst->pvt;
+		if (hw_hdlc && (dst->chanpos == 16)) {
+		    if (debug)
+			printk("cwain: Not Unassigning D-channel %d/%d!\n", dst->span->offset, dst->chanpos);
+		} else {
+		    timeslot = dst->channo;
+		    cwain_unassign(cwaintmp, dst->chanpos, timeslot, 1);
+		    if (debug)
+			printk("cwain: Unassigning channel %d/%d!\n", dst->span->offset, dst->chanpos);
+		}
+	}
+	return 0;
+}
+
 static inline void cwain_isr_run(struct zt_cwain *cwaintmp, int ticks) {
     int fifo=0;
     if (cwaintmp->span.flags & ZT_FLAG_RUNNING) {
         /* oh zaptel! tell us what to transmit... */
         zt_transmit(&cwaintmp->span);
-	/* B chans 1-15 mapped to fifos 0-14 */
-	/* B chans 17-31 mapped to fifos 15-29 */
-	for (fifo=0; fifo < 30; fifo++) {
-	    /* copy to fbuffer */
-	    if ((ticks < 1) || (ticks > 8)) {
-		printk(KERN_INFO "cwain: whicked ticks make whicked tricks (%d)\n",cwaintmp->ticks);
-	    } else {
-		memcpy(&cwaintmp->ftxbuf[fifo][(ticks-1)*8], cwaintmp->txbuf[fifo], ZT_CHUNKSIZE);
+
+	if (hw_hdlc) {
+	    /* B chans 1-15 mapped to fifos 0-14 */
+	    /* B chans 17-31 mapped to fifos 15-29 */
+	    for (fifo=0; fifo < 30; fifo++) {
+		/* copy to fbuffer */
+	        if ((ticks < 1) || (ticks > 8)) {
+		    printk(KERN_INFO "cwain: whicked ticks make whicked tricks (%d)\n",cwaintmp->ticks);
+		} else {
+		    memcpy(&cwaintmp->ftxbuf[fifo][(ticks-1)*8], cwaintmp->txbuf[fifo], ZT_CHUNKSIZE);
+		}
 	    }
+	
+	    if (cwaintmp->sync) {
+		cwain_dfifo_tx(cwaintmp);
+	    }
 
-	}
-	if (cwaintmp->sync) {
-	    cwain_dfifo_tx(cwaintmp);
-	}
+    	    cwaintmp->chans[15].bytes2receive = 0;
+	    cwaintmp->chans[15].bytes2transmit = 0;
+	    cwaintmp->chans[15].eofrx = 0;
+	    cwaintmp->chans[15].eoftx = 0;
 
-        cwaintmp->chans[15].bytes2receive = 0;
-	cwaintmp->chans[15].bytes2transmit = 0;
-	cwaintmp->chans[15].eofrx = 0;
-	cwaintmp->chans[15].eoftx = 0;
+	    for (fifo=0; fifo < 30; fifo++) {
+		/* copy from fbuffer */
+	        memcpy(cwaintmp->rxbuf[fifo], &cwaintmp->frxbuf[fifo][(ticks-1)*8], ZT_CHUNKSIZE);
+		zt_ec_chunk(&cwaintmp->span.chans[fifo], cwaintmp->span.chans[fifo].readchunk, cwaintmp->span.chans[fifo].writechunk);
+	    }
 
-	for (fifo=0; fifo < 30; fifo++) {
-	    /* copy from fbuffer */
-	    memcpy(cwaintmp->rxbuf[fifo], &cwaintmp->frxbuf[fifo][(ticks-1)*8], ZT_CHUNKSIZE);
-	    zt_ec_chunk(&cwaintmp->span.chans[fifo], cwaintmp->span.chans[fifo].readchunk, cwaintmp->span.chans[fifo].writechunk);
-	}
+	    /* d-chan data */
+	    if ((cwaintmp->drx > 0) && cwaintmp->sync){
+		if (debug > 2)
+		    printk(KERN_CRIT "drx = %d\n", cwaintmp->drx);
+		cwain_dfifo_rx(cwaintmp);
+	    }
+	} else {
+	    /* software HDLC */
+            for (fifo=0; fifo < 31; fifo++) {
+        	/* copy to fbuffer */
+                if ((ticks < 1) || (ticks > 8)) {
+                    printk(KERN_INFO "cwain: whicked ticks make whicked tricks (%d)\n",cwaintmp->ticks);
+                } else {
+                    memcpy(&cwaintmp->ftxbuf[fifo][(ticks-1)*8], cwaintmp->txbuf[fifo], ZT_CHUNKSIZE);
+                }
+            }
 
-	/* d-chan data */
-	if ((cwaintmp->drx > 0) && cwaintmp->sync){
-	    if (debug > 2)
-	    	printk(KERN_CRIT "drx = %d\n", cwaintmp->drx);
-	    cwain_dfifo_rx(cwaintmp);
+            for (fifo=0; fifo < 31; fifo++) {
+                /* copy from fbuffer */
+                memcpy(cwaintmp->rxbuf[fifo], &cwaintmp->frxbuf[fifo][(ticks-1)*8], ZT_CHUNKSIZE);
+                zt_ec_chunk(&cwaintmp->span.chans[fifo], cwaintmp->span.chans[fifo].readchunk, cwaintmp->span.chans[fifo].writechunk);
+            }
 	}
 	/* oh zaptel! thou shall receive! */
 	zt_receive(&(cwaintmp->span));
@@ -677,12 +856,15 @@
 }
 
 static inline void cwain_isr_err(struct zt_cwain *cwaintmp) {
+    unsigned long flags = 0;
     unsigned short crc, vio, ebit, fas;
 
+    spin_lock_irqsave(&cwaintmp->lock,flags);
     crc = (cwain_inb(cwaintmp, cwain_R_CRC_ECH) << 8) | cwain_inb(cwaintmp, cwain_R_CRC_ECL);
     vio = (cwain_inb(cwaintmp, cwain_R_VIO_ECH) << 8) | cwain_inb(cwaintmp, cwain_R_VIO_ECL);
     ebit = (cwain_inb(cwaintmp, cwain_R_E_ECH) << 8) | cwain_inb(cwaintmp, cwain_R_E_ECL);
     fas = (cwain_inb(cwaintmp, cwain_R_FAS_ECH) << 8) | cwain_inb(cwaintmp, cwain_R_FAS_ECL);
+    spin_unlock_irqrestore(&cwaintmp->lock,flags);
 			
     cwaintmp->span.crc4count += crc;
     cwaintmp->span.bpvcount += vio;
@@ -696,8 +878,9 @@
 
 static inline void cwain_audio_run(struct zt_cwain *cwaintmp) {
     int fifo=0;
+    if (hw_hdlc) {
 	for (fifo=0; fifo < 30; fifo++) {
-	    /* B xmit */
+	    /* B tx */
 	    cwain_fifo_tx(cwaintmp, fifo);
 	}
 
@@ -705,18 +888,33 @@
 	    /* B rx */
 	    cwain_fifo_rx(cwaintmp, fifo);
 	}
+    } else {
+	/* software HDLC */
+	for (fifo=0; fifo < 31; fifo++) {
+	    /* B tx */
+	    cwain_fifo_tx(cwaintmp, fifo);
+	}
+
+	for (fifo=0; fifo < 31; fifo++) {
+	    /* B rx */
+	    cwain_fifo_rx(cwaintmp, fifo);
+	}
+    }
 }
 
 int cwain_isr_sync(struct zt_cwain *cwainspan) {
     unsigned char sync_sta;
     unsigned char sync_ok = 0;
     unsigned char jatt_sta = 0;
+    unsigned long flags = 0;
+    int chan = 0;
     int res = 0; /* assume no l1event */
 
     if (!cwainspan->span.flags & ZT_FLAG_RUNNING) {
 	return res;
     }
 
+    spin_lock_irqsave(&cwainspan->lock,flags);
     sync_sta = cwain_inb(cwainspan, cwain_R_SYNC_STA);
 
     if ((!cwainspan->sync) || (sync_sta != cwainspan->sync_sta)) {
@@ -770,18 +968,37 @@
 	    cwain_outb(cwainspan,cwain_R_RX_OFFS,0x06);
 	    cwain_outb(cwainspan,cwain_R_TX_OFFS,0x06);
 
-	    if (debug > 2)
-		printk(KERN_INFO "cwain: enabling D channel fifos\n");
-	    cwain_outb(cwainspan,cwain_R_FIFO,0x1F << 1);
-	    cwain_waitbusy(cwainspan);
-	    cwain_outb(cwainspan,cwain_A_CON_HDLC,0xd);
-	    cwain_outb(cwainspan,cwain_A_IRQ_MSK,0x1);
+	    if (hw_hdlc) {
+	        if (debug > 2)
+		    printk(KERN_INFO "cwain: enabling D channel fifos\n");
+		cwain_outb(cwainspan,cwain_R_FIFO,0x1F << 1);
+		cwain_waitbusy(cwainspan);
+		cwain_outb(cwainspan,cwain_R_INC_RES_FIFO,0x2);
+		cwain_waitbusy(cwainspan);
+    		cwain_outb(cwainspan,cwain_A_CON_HDLC,0xd);
+		cwain_outb(cwainspan,cwain_A_IRQ_MSK,0x1);
 	
-	    cwain_outb(cwainspan,cwain_R_FIFO,(0x1F << 1) | 1);
-	    cwain_waitbusy(cwainspan);
-	    cwain_outb(cwainspan,cwain_A_CON_HDLC,0xd);
-	    cwain_outb(cwainspan,cwain_A_IRQ_MSK,0x1);
+		cwain_outb(cwainspan,cwain_R_FIFO,(0x1F << 1) | 1);
+		cwain_waitbusy(cwainspan);
+		cwain_outb(cwainspan,cwain_R_INC_RES_FIFO,0x2);
+		cwain_waitbusy(cwainspan);
+		cwain_outb(cwainspan,cwain_A_CON_HDLC,0xd);
+	        cwain_outb(cwainspan,cwain_A_IRQ_MSK,0x1);
+	    }
 
+	    if (hw_hdlc) {
+	        for (chan=1;chan<=15;chan++) {
+		    cwain_unassign(cwainspan, chan, chan, 0);
+		}
+		for (chan=17;chan<=31;chan++) {
+		    cwain_unassign(cwainspan, chan, chan, 0);
+		}
+	    } else {
+	        for (chan=1;chan<=31;chan++) {
+		    cwain_unassign(cwainspan, chan, chan, 0);
+		}
+	    }
+
 	    cwainspan->span.crc4count = 0;
     	    cwainspan->span.bpvcount = 0;
 	    cwainspan->span.ebitcount = 0;
@@ -791,16 +1008,19 @@
 	    res = 1;
 	}
 	if (!sync_ok && cwainspan->sync) {
-	    if (debug > 2)
-		printk(KERN_INFO "cwain: disabling D channel fifos\n");
-	    cwain_outb(cwainspan,cwain_R_FIFO,0x1F << 1);
-	    cwain_waitbusy(cwainspan);
-	    cwain_outb(cwainspan,cwain_A_CON_HDLC,0x1);
-	    cwain_outb(cwainspan,cwain_A_IRQ_MSK,0x0);
-	    cwain_outb(cwainspan,cwain_R_FIFO,(0x1F << 1) | 1);
-	    cwain_waitbusy(cwainspan);
-	    cwain_outb(cwainspan,cwain_A_CON_HDLC,0x1);
-	    cwain_outb(cwainspan,cwain_A_IRQ_MSK,0x0);
+	    if (hw_hdlc) {
+		if (debug > 2)
+		    printk(KERN_INFO "cwain: disabling D channel fifos\n");
+		cwain_outb(cwainspan,cwain_R_FIFO,0x1F << 1);
+		cwain_waitbusy(cwainspan);
+		cwain_outb(cwainspan,cwain_A_CON_HDLC,0x1);
+		cwain_outb(cwainspan,cwain_A_IRQ_MSK,0x0);
+		cwain_outb(cwainspan,cwain_R_FIFO,(0x1F << 1) | 1);
+		cwain_waitbusy(cwainspan);
+		cwain_outb(cwainspan,cwain_A_CON_HDLC,0x1);
+		cwain_outb(cwainspan,cwain_A_IRQ_MSK,0x0);
+	    }
+	    
 	    cwainspan->span.alarms = ZT_ALARM_RED;
 	    zt_alarm_notify(&cwainspan->span);
 	    res = 1;
@@ -828,9 +1048,33 @@
 	}
 	cwain_doLEDs(cwainspan);
     }
+    spin_unlock_irqrestore(&cwainspan->lock,flags);
     return res;
 }
 
+static int ztcwain_proc_read(struct zt_span *span, char *output) {
+    struct zt_cwain_card *cwaincard = span->pvt;
+    struct zt_cwain *cwaintmp;
+    unsigned long flags;
+    unsigned char fstate;
+
+    if (cwaincard == NULL) {
+	printk(KERN_CRIT "cwain: cwaincard == NULL!\n");
+	return 0;
+    }
+    cwaintmp = cwaincard->span[span->offset];
+    if (cwaintmp == NULL) {
+	printk(KERN_CRIT "cwain: cwaintmp == NULL!\n");
+	return 0;
+    }
+
+    spin_lock_irqsave(&cwaintmp->lock,flags);
+	fstate = cwain_inb(cwaintmp, cwain_R_E1_RD_STA);
+    spin_unlock_irqrestore(&cwaintmp->lock,flags);
+    return sprintf(output, "cwain: span state = F%d.", fstate & 0x7);
+}
+
+/* called locked */
 int cwain_isr_fifo(struct zt_cwain *cwainspan, unsigned char status) {
     unsigned char irq_foview,fi;
 
@@ -878,9 +1122,7 @@
 #endif
     struct zt_cwain_card *cwaintmp = dev_id;
     unsigned char status, status2, status_tmp, irq_misc, irq_misc2 = 0;
-#ifndef RELAXED_LOCKING    
     unsigned long flags;
-#endif
     int i = 0;
     int l1event = 0;
     
@@ -892,32 +1134,23 @@
 #endif		
     }
     
-#ifdef RELAXED_LOCKING    
-    spin_lock(&(cwaintmp->lock));
-#else
     spin_lock_irqsave(&(cwaintmp->lock),flags);
-#endif
-    status = cwain_inb(cwaintmp->span[0],cwain_R_STATUS);
+	status = cwain_inb(cwaintmp->span[0],cwain_R_STATUS);
+	status2 = 0;
 
-    status2 = 0;
-
-    for (i=0;i<cwaintmp->spans;i++) {
-	if (i == 0) {
-	    status_tmp = status;
-	} else {
-	    status_tmp = cwain_inb(cwaintmp->span[i],cwain_R_STATUS);
-	    status2 = status_tmp;
+	for (i=0;i<cwaintmp->spans;i++) {
+	    if (i == 0) {
+		status_tmp = status;
+	    } else {
+		status_tmp = cwain_inb(cwaintmp->span[i],cwain_R_STATUS);
+		status2 = status_tmp;
+	    }
+	    cwain_isr_fifo(cwaintmp->span[i], status_tmp);
 	}
-	cwain_isr_fifo(cwaintmp->span[i], status_tmp);
-    }
+    spin_unlock_irqrestore(&(cwaintmp->lock),flags);
 
     if (!(status & 0x80) && !(status & 0x40)) {
 	// it's not us!
-#ifdef RELAXED_LOCKING    
-	spin_unlock(&(cwaintmp->lock));
-#else 
-	spin_unlock_irqrestore(&(cwaintmp->lock),flags);
-#endif
 #ifdef LINUX26
 		return IRQ_NONE;
 #else
@@ -927,7 +1160,9 @@
 
     // misc irq
     if (status & 0x40) {
-	irq_misc = cwain_inb(cwaintmp->span[0],cwain_R_IRQ_MISC);
+	spin_lock_irqsave(&(cwaintmp->lock),flags);
+	    irq_misc = cwain_inb(cwaintmp->span[0],cwain_R_IRQ_MISC);
+	spin_unlock_irqrestore(&(cwaintmp->lock),flags);
 	if (irq_misc & 0x2)  {
 	    /* cwain timer */
 	    cwaintmp->ticks++;
@@ -962,7 +1197,9 @@
     // misc irq
     if (status2 & 0x40) {
 	if (cwaintmp->spans == 2) {
-	    irq_misc2 = cwain_inb(cwaintmp->span[1],cwain_R_IRQ_MISC);
+	    spin_lock_irqsave(&(cwaintmp->lock),flags);
+		irq_misc2 = cwain_inb(cwaintmp->span[1],cwain_R_IRQ_MISC);
+	    spin_unlock_irqrestore(&(cwaintmp->lock),flags);
 	}
 	if (irq_misc2 & 0x1) {
 	    /* state machine 2 */
@@ -982,11 +1219,6 @@
         }
     }
 
-#ifdef RELAXED_LOCKING    
-    spin_unlock(&(cwaintmp->lock));
-#else
-    spin_unlock_irqrestore(&(cwaintmp->lock),flags);
-#endif
 #ifdef LINUX26
 	return IRQ_RETVAL(1);
 #endif		
@@ -1049,31 +1281,40 @@
 //    printk(KERN_CRIT "already running %d flags %d\n", alreadyrunning, span->flags);
 
     if (!alreadyrunning) {
-	span->chans[15].flags &= ~ZT_FLAG_HDLC;
-	span->chans[15].flags |= ZT_FLAG_BRIDCHAN; /* yes! */
+	if (hw_hdlc) {
+	    span->chans[15].flags &= ~ZT_FLAG_HDLC;
+	    span->chans[15].flags |= ZT_FLAG_BRIDCHAN; /* yes! */
     
-	/* setup B channel buffers (8 bytes each) */
-	for (i=0; i<15 ; i++) {
-	    memset(cwaintmp->rxbuf[i],0x0,sizeof(cwaintmp->rxbuf[i]));
-    	    memset(cwaintmp->txbuf[i],0x0,sizeof(cwaintmp->txbuf[i]));
+	    /* setup B channel buffers (8 bytes each) */
+	    for (i=0; i<15 ; i++) {
+		memset(cwaintmp->rxbuf[i],0x0,sizeof(cwaintmp->rxbuf[i]));
+    		memset(cwaintmp->txbuf[i],0x0,sizeof(cwaintmp->txbuf[i]));
+    		span->chans[i].readchunk = cwaintmp->rxbuf[i];
+		span->chans[i].writechunk = cwaintmp->txbuf[i];
+	    }
+	    for (i=16; i<31 ; i++) {
+		memset(cwaintmp->rxbuf[i-1],0x0,sizeof(cwaintmp->rxbuf[i-1]));
+    		memset(cwaintmp->txbuf[i-1],0x0,sizeof(cwaintmp->txbuf[i-1]));
+    		span->chans[i].readchunk = cwaintmp->rxbuf[i-1];
+		span->chans[i].writechunk = cwaintmp->txbuf[i-1];
+	    }
+	    /* setup D channel buffer */
+    	    memset(cwaintmp->dtxbuf,0x0,sizeof(cwaintmp->dtxbuf));
+	    span->chans[15].writechunk = cwaintmp->dtxbuf;
+	    cwaintmp->chans[15].maxbytes2transmit = sizeof(cwaintmp->dtxbuf);
 
-    	    span->chans[i].readchunk = cwaintmp->rxbuf[i];
-	    span->chans[i].writechunk = cwaintmp->txbuf[i];
+	    memset(cwaintmp->drxbuf,0x0,sizeof(cwaintmp->drxbuf));
+    	    span->chans[15].readchunk = cwaintmp->drxbuf;
+	} else 	{
+	    /* software HDLC */
+    	    /* setup B channel buffers (8 bytes each) */
+    	    for (i=0; i<31 ; i++) {
+        	memset(cwaintmp->rxbuf[i],0x0,sizeof(cwaintmp->rxbuf[i]));
+    		memset(cwaintmp->txbuf[i],0x0,sizeof(cwaintmp->txbuf[i]));
+        	span->chans[i].readchunk = cwaintmp->rxbuf[i];
+        	span->chans[i].writechunk = cwaintmp->txbuf[i];
+    	    }	    
 	}
-	for (i=16; i<31 ; i++) {
-	    memset(cwaintmp->rxbuf[i-1],0x0,sizeof(cwaintmp->rxbuf[i-1]));
-    	    memset(cwaintmp->txbuf[i-1],0x0,sizeof(cwaintmp->txbuf[i-1]));
-    	    span->chans[i].readchunk = cwaintmp->rxbuf[i-1];
-	    span->chans[i].writechunk = cwaintmp->txbuf[i-1];
-	}
-	/* setup D channel buffer */
-    	memset(cwaintmp->dtxbuf,0x0,sizeof(cwaintmp->dtxbuf));
-	span->chans[15].writechunk = cwaintmp->dtxbuf;
-	cwaintmp->chans[15].maxbytes2transmit = sizeof(cwaintmp->dtxbuf);
-
-	memset(cwaintmp->drxbuf,0x0,sizeof(cwaintmp->drxbuf));
-    	span->chans[15].readchunk = cwaintmp->drxbuf;
-
 	span->flags |= ZT_FLAG_RUNNING;
     } else {
 	printk(KERN_CRIT "already running\n");
@@ -1084,69 +1325,95 @@
     // irqs off
     cwain_outb(cwaintmp,cwain_R_IRQ_CTRL, 0); 
 
-    /* setup D-FIFO TX */
-    cwain_outb(cwaintmp,cwain_R_FIFO,0x1F << 1);
-    cwain_waitbusy(cwaintmp);
-    cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
-    cwain_waitbusy(cwaintmp);
-    cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x1);
-    cwain_outb(cwaintmp,cwain_A_SUBCH_CFG,0x0);
-    cwain_outb(cwaintmp,cwain_A_CHANNEL,0x10 << 1);
-    cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x0);
+    if (hw_hdlc) {
 
-    /* setup D-FIFO RX */
-    cwain_outb(cwaintmp,cwain_R_FIFO,(0x1F << 1) | 1);
-    cwain_waitbusy(cwaintmp);
-    cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
-    cwain_waitbusy(cwaintmp);
-    cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x1);
-    cwain_outb(cwaintmp,cwain_A_SUBCH_CFG,0x0);
-    cwain_outb(cwaintmp,cwain_A_CHANNEL,(0x10 << 1) | 1);
-    cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x0);
-
-    /* setup B-FIFOs TX */
-    /* map ts 1 to 15 to fifos 0 to 14 */
-    for (i=1; i<16 ; i++) {
-	cwain_outb(cwaintmp,cwain_R_FIFO,(i - 1) << 1);
+	/* setup D-FIFO TX */
+	cwain_outb(cwaintmp,cwain_R_FIFO,0x1F << 1);
 	cwain_waitbusy(cwaintmp);
-    	cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
+        cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
 	cwain_waitbusy(cwaintmp);
-	cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x2);
-	cwain_outb(cwaintmp,cwain_A_CHANNEL,i << 1);
-	cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x1);
-    }
-    /* map ts 17 to 31 to fifos 15 to 29 */
-    for (i=17; i<32 ; i++) {
-	cwain_outb(cwaintmp,cwain_R_FIFO,(i - 2) << 1);
-	cwain_waitbusy(cwaintmp);
-    	cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
-	cwain_waitbusy(cwaintmp);
-	cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x2);
-	cwain_outb(cwaintmp,cwain_A_CHANNEL,i << 1);
-	cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x1);
-    }
+        cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x1);
+	cwain_outb(cwaintmp,cwain_A_SUBCH_CFG,0x0);
+        cwain_outb(cwaintmp,cwain_A_CHANNEL,0x10 << 1);
+	cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x0);
 
-    /* setup B-FIFOs RX */
-    /* map ts 1 to 15 to fifos 0 to 14 */
-    for (i=1; i<16 ; i++) {
-	cwain_outb(cwaintmp,cwain_R_FIFO,((i-1) << 1) | 1);
-    	cwain_waitbusy(cwaintmp);
-    	cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
-    	cwain_waitbusy(cwaintmp);
-    	cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x2);
-    	cwain_outb(cwaintmp,cwain_A_CHANNEL,(i << 1) | 1);
-    	cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x1);
+        /* setup D-FIFO RX */
+	cwain_outb(cwaintmp,cwain_R_FIFO,(0x1F << 1) | 1);
+        cwain_waitbusy(cwaintmp);
+	cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
+        cwain_waitbusy(cwaintmp);
+        cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x1);
+        cwain_outb(cwaintmp,cwain_A_SUBCH_CFG,0x0);
+        cwain_outb(cwaintmp,cwain_A_CHANNEL,(0x10 << 1) | 1);
+        cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x0);
+
+        /* setup B-FIFOs TX */
+        /* map ts 1 to 15 to fifos 0 to 14 */
+	for (i=1; i<16 ; i++) {
+	    cwain_outb(cwaintmp,cwain_R_FIFO,(i - 1) << 1);
+	    cwain_waitbusy(cwaintmp);
+    	    cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
+	    cwain_waitbusy(cwaintmp);
+	    cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x2);
+	    cwain_outb(cwaintmp,cwain_A_CHANNEL,i << 1);
+	    cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x1);
+        }
+	/* map ts 17 to 31 to fifos 15 to 29 */
+        for (i=17; i<32 ; i++) {
+	    cwain_outb(cwaintmp,cwain_R_FIFO,(i - 2) << 1);
+	    cwain_waitbusy(cwaintmp);
+    	    cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
+	    cwain_waitbusy(cwaintmp);
+	    cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x2);
+	    cwain_outb(cwaintmp,cwain_A_CHANNEL,i << 1);
+	    cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x1);
+	}
+
+	/* setup B-FIFOs RX */
+	/* map ts 1 to 15 to fifos 0 to 14 */
+	for (i=1; i<16 ; i++) {
+	    cwain_outb(cwaintmp,cwain_R_FIFO,((i-1) << 1) | 1);
+    	    cwain_waitbusy(cwaintmp);
+    	    cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
+    	    cwain_waitbusy(cwaintmp);
+    	    cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x2);
+    	    cwain_outb(cwaintmp,cwain_A_CHANNEL,(i << 1) | 1);
+    	    cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x1);
+	}
+        /* map ts 17 to 31 to fifos 15 to 29 */
+	for (i=17; i<32 ; i++) {
+	    cwain_outb(cwaintmp,cwain_R_FIFO,((i-2) << 1) | 1);
+    	    cwain_waitbusy(cwaintmp);
+    	    cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
+    	    cwain_waitbusy(cwaintmp);
+    	    cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x2);
+    	    cwain_outb(cwaintmp,cwain_A_CHANNEL,(i << 1) | 1);
+	    cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x1);
+	}
+    } else {
+	/* software HDLC */
+        /* setup B-FIFOs TX */
+        for (i=1; i<32 ; i++) {
+            cwain_outb(cwaintmp,cwain_R_FIFO,(i - 1) << 1);
+            cwain_waitbusy(cwaintmp);
+            cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
+            cwain_waitbusy(cwaintmp);
+            cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x2);
+            cwain_outb(cwaintmp,cwain_A_CHANNEL,i << 1);
+            cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x1);
+        }
+        /* setup B-FIFOs RX */
+        for (i=1; i<32 ; i++) {
+            cwain_outb(cwaintmp,cwain_R_FIFO,((i-1) << 1) | 1);
+            cwain_waitbusy(cwaintmp);
+            cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
+            cwain_waitbusy(cwaintmp);
+	    cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x2);
+            cwain_outb(cwaintmp,cwain_A_CHANNEL,(i << 1) | 1);
+            cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x1);
+        }
+
     }
-    /* map ts 17 to 31 to fifos 15 to 29 */
-    for (i=17; i<32 ; i++) {
-	cwain_outb(cwaintmp,cwain_R_FIFO,((i-2) << 1) | 1);
-    	cwain_waitbusy(cwaintmp);
-    	cwain_outb(cwaintmp,cwain_R_INC_RES_FIFO,0x2);
-    	cwain_waitbusy(cwaintmp);
-    	cwain_outb(cwaintmp,cwain_A_CON_HDLC,0x2);
-    	cwain_outb(cwaintmp,cwain_A_CHANNEL,(i << 1) | 1);
-    	cwain_outb(cwaintmp,cwain_A_IRQ_MSK,0x1);
-    }
 
     if (debug)
         printk(KERN_INFO "cwain: starting card %d span %d/%d.\n",cwaintmp->cardno,span->spanno,span->offset);
@@ -1157,8 +1424,8 @@
     
     /* setup E1 amplitude */
     cwain_outb(cwaintmp,cwain_R_PWM_MD,0x20);
-    cwain_outb(cwaintmp,cwain_R_PWM0,0x50);
-    cwain_outb(cwaintmp,cwain_R_PWM1,0xff);
+    cwain_outb(cwaintmp,cwain_R_PWM0,pwm0);
+    cwain_outb(cwaintmp,cwain_R_PWM1,pwm1);
 
     /* setup E1 transceiver */
     cwain_outb(cwaintmp,cwain_R_TX_SL0,0xf8);  // R_TX_FR1
@@ -1325,6 +1592,8 @@
         cwaintmp->span.open = ztcwain_open;
         cwaintmp->span.close = ztcwain_close;
         cwaintmp->span.ioctl = ztcwain_ioctl;
+        cwaintmp->span.proc_read = ztcwain_proc_read;
+	cwaintmp->span.dacs = ztcwain_dacs;
 
         cwaintmp->span.chans = cwaintmp->chans;
         cwaintmp->span.channels = 31;
@@ -1338,7 +1607,7 @@
 	    memset(&(cwaintmp->chans[i]),0x0,sizeof(struct zt_chan));
 	    sprintf(cwaintmp->chans[i].name,"cwain%d/%d",cwain_span_count + 1,i + 1);
 	    cwaintmp->chans[i].pvt = cwaintmp;
-	    cwaintmp->chans[i].sigcap =  ZT_SIG_CLEAR;
+	    cwaintmp->chans[i].sigcap =  ZT_SIG_CLEAR | ZT_SIG_DACS;
 	    cwaintmp->chans[i].chanpos = i + 1; 
 	}
 
@@ -1579,7 +1848,7 @@
     if (cwain_card_count == 0) {
 	printk(KERN_INFO "cwain: no cwain cards found.\n");
     } else {
-	printk(KERN_INFO "cwain: %d cwain card(s) in this box, %d E1 ports total.\n", cwain_card_count, cwain_span_count);
+	printk(KERN_INFO "cwain: %d cwain card(s) in this box, %d E1 ports total, hw_hdcl = %d.\n", cwain_card_count, cwain_span_count, hw_hdlc);
     }
     return 0;
 }
@@ -1617,9 +1886,17 @@
 #ifdef LINUX26
 module_param(ports, int, 0600);
 module_param(debug, int, 0600);
+module_param(hw_hdlc, int, 0600);
+module_param(pwm0, int, 0600);
+module_param(pwm1, int, 0600);
+module_param(dacs, int, 0600);
 #else
 MODULE_PARM(ports,"i");
 MODULE_PARM(debug,"i");
+MODULE_PARM(hw_hdlc,"i");
+MODULE_PARM(pwm0,"i");
+MODULE_PARM(pwm1,"i");
+MODULE_PARM(dacs,"i");
 #endif
 
 MODULE_DESCRIPTION("cwain zaptel driver");

Modified: zaptel/trunk/cwain/cwain.h
===================================================================
--- zaptel/trunk/cwain/cwain.h	2007-01-19 22:30:20 UTC (rev 3041)
+++ zaptel/trunk/cwain/cwain.h	2007-01-20 19:53:28 UTC (rev 3042)
@@ -1,6 +1,6 @@
 #define cwain_FIFO_SIZE	128
 #define cwain_DFIFO_SIZE	4096
-#define cwain_FRAME_SIZE 16	/* has to be %4==0 */
+#define cwain_FRAME_SIZE 64	/* has to be %4==0 */
 #define cwain_FIFO_HW cwain_FRAME_SIZE * 2 + ZT_CHUNKSIZE
 
 typedef struct zt_cwain {
@@ -32,12 +32,12 @@
     unsigned char leds[4];
 
     /* B chan buffers */
-    unsigned char rxbuf[30][ZT_CHUNKSIZE];
-    unsigned char txbuf[30][ZT_CHUNKSIZE];
+    unsigned char rxbuf[31][ZT_CHUNKSIZE];
+    unsigned char txbuf[31][ZT_CHUNKSIZE];
 
     /* buffers */
-    unsigned char frxbuf[30][cwain_FRAME_SIZE];
-    unsigned char ftxbuf[30][cwain_FRAME_SIZE];
+    unsigned char frxbuf[31][cwain_FRAME_SIZE];
+    unsigned char ftxbuf[31][cwain_FRAME_SIZE];
     
     /* number of RXed dchan frames */
     unsigned char drx;

Modified: zaptel/trunk/debian/changelog
===================================================================
--- zaptel/trunk/debian/changelog	2007-01-19 22:30:20 UTC (rev 3041)
+++ zaptel/trunk/debian/changelog	2007-01-20 19:53:28 UTC (rev 3042)
@@ -1,3 +1,10 @@
+zaptel (1:1.2.12~dfsg-4) UNRELEASED; urgency=low
+
+  [Tzafrir Cohen]
+  * Bristuff 0.3.0-PRE-1x 
+
+ -- Tzafrir Cohen <tzafrir.cohen at xorcom.com>  Sat, 20 Jan 2007 21:16:04 +0200
+
 zaptel (1:1.2.12~dfsg-3) UNRELEASED; urgency=low
 
   * NOT RELEASED YET

Modified: zaptel/trunk/debian/patches/bristuff.dpatch
===================================================================
--- zaptel/trunk/debian/patches/bristuff.dpatch	2007-01-19 22:30:20 UTC (rev 3041)
+++ zaptel/trunk/debian/patches/bristuff.dpatch	2007-01-20 19:53:28 UTC (rev 3042)
@@ -3,12 +3,12 @@
 ##
 ## All lines beginning with `## DP:' are a description of the patch.
 ## DP: This is the patch zaptel.patch from bristuff, with the Makefile
-## DP: patch removed. Version: bristuff-0.3.0-PRE-1w
+## DP: patch removed. Version: bristuff-0.3.0-PRE-1x
 
 @DPATCH@
 diff -urN zaptel-1.2.10.orig/zaptel.c zaptel-1.2.10/zaptel.c
 --- zaptel-1.2.10.orig/zaptel.c	2006-09-16 09:45:04.000000000 +0200
-+++ zaptel-1.2.10/zaptel.c	2006-10-19 11:16:47.000000000 +0200
++++ zaptel-1.2.10/zaptel.c	2006-12-20 17:59:51.000000000 +0100
 @@ -139,6 +139,7 @@
  EXPORT_SYMBOL(zt_qevent_lock);
  EXPORT_SYMBOL(zt_hooksig);
@@ -17,7 +17,18 @@
  EXPORT_SYMBOL(zt_set_dynamic_ioctl);
  EXPORT_SYMBOL(zt_ec_chunk);
  EXPORT_SYMBOL(zt_ec_span);
-@@ -2700,6 +2701,30 @@
+@@ -556,6 +557,10 @@
+ 		len += sprintf(page + len, "\tIRQ misses: %d\n", spans[span]->irqmisses);
+ 	len += sprintf(page + len, "\n");
+ 
++	if (spans[span]->proc_read) {
++		len += spans[span]->proc_read(spans[span], page + len);
++	}
++
+ 
+         for (x=1;x<ZT_MAX_CHANNELS;x++) {	
+ 		if (chans[x]) {
+@@ -2700,6 +2705,30 @@
  	}
  }
  
@@ -48,7 +59,7 @@
  #define VALID_SPAN(j) do { \
  	if ((j >= ZT_MAX_SPANS) || (j < 1)) \
  		return -EINVAL; \
-@@ -4928,11 +4953,40 @@
+@@ -4928,11 +4957,40 @@
  					*(txb++) = fasthdlc_tx_run_nocheck(&ms->txhdlc);
  				}
  				bytes -= left;
@@ -89,7 +100,7 @@
  			}
  			/* Check buffer status */
  			if (ms->writeidx[ms->outwritebuf] >= ms->writen[ms->outwritebuf]) {
-@@ -4977,6 +5031,17 @@
+@@ -4977,6 +5035,17 @@
  				/* Transmit a flag if this is an HDLC channel */
  				if (ms->flags & ZT_FLAG_HDLC)
  					fasthdlc_tx_frame_nocheck(&ms->txhdlc);
@@ -107,16 +118,7 @@
  #ifdef CONFIG_ZAPATA_NET
  				if (ms->flags & ZT_FLAG_NETDEV)
  					netif_wake_queue(ztchan_to_dev(ms));
-@@ -4987,7 +5052,7 @@
- 					tasklet_schedule(&ms->ppp_calls);
- 				}
- #endif
--			}
-+			} 
- 		} else if (ms->curtone && !(ms->flags & ZT_FLAG_PSEUDO)) {
- 			left = ms->curtone->tonesamples - ms->tonep;
- 			if (left > bytes)
-@@ -5033,6 +5098,10 @@
+@@ -5033,6 +5102,10 @@
  				memset(txb, 0xFF, bytes);
  			}
  			bytes = 0;
@@ -127,7 +129,7 @@
  		} else {
  			memset(txb, ZT_LIN2X(0, ms), bytes);	/* Lastly we use silence on telephony channels */
  			bytes = 0;
-@@ -5758,6 +5827,13 @@
+@@ -5758,6 +5831,13 @@
  	int left, x;
  
  	int bytes = ZT_CHUNKSIZE;
@@ -141,7 +143,7 @@
  
  	while(bytes) {
  #if defined(CONFIG_ZAPATA_NET)  || defined(CONFIG_ZAPATA_PPP)
-@@ -5816,6 +5892,19 @@
+@@ -5816,6 +5896,19 @@
  						}
  					}
  				}
@@ -163,7 +165,7 @@
  				memcpy(buf + ms->readidx[ms->inreadbuf], rxb, left);
 diff -urN zaptel-1.2.10.orig/zaptel.h zaptel-1.2.10/zaptel.h
 --- zaptel-1.2.10.orig/zaptel.h	2005-12-17 03:04:05.000000000 +0100
-+++ zaptel-1.2.10/zaptel.h	2006-10-19 11:16:47.000000000 +0200
++++ zaptel-1.2.10/zaptel.h	2006-12-19 13:36:19.000000000 +0100
 @@ -994,6 +994,13 @@
  	int do_ppp_error;
  	struct sk_buff_head ppp_rq;
@@ -189,7 +191,18 @@
  struct zt_span {
  	spinlock_t lock;
  	void *pvt;			/* Private stuff */
-@@ -1404,6 +1415,9 @@
+@@ -1331,6 +1342,10 @@
+ 	int watchcounter;
+ 	int watchstate;
+ #endif	
++#ifdef CONFIG_PROC_FS
++	/* Allow subordinate drivers to print out their own stuff */
++	int (*proc_read)(struct zt_span *span, char *start);
++#endif
+ };
+ 
+ #define ZT_WATCHDOG_NOINTS		(1 << 0)
+@@ -1404,6 +1419,9 @@
  /* Notify a change possible change in alarm status */
  extern void zt_alarm_notify(struct zt_span *span);
  
@@ -229,7 +242,7 @@
  #endif
 diff -urN zaptel-1.2.10.orig/ztcfg.c zaptel-1.2.10/ztcfg.c
 --- zaptel-1.2.10.orig/ztcfg.c	2006-02-01 03:33:54.000000000 +0100
-+++ zaptel-1.2.10/ztcfg.c	2006-12-05 12:37:31.536696070 +0100
++++ zaptel-1.2.10/ztcfg.c	2006-12-05 12:37:31.000000000 +0100
 @@ -90,6 +90,10 @@
  
  static int stopmode = 0;

Modified: zaptel/trunk/qozap/qozap.c
===================================================================
--- zaptel/trunk/qozap/qozap.c	2007-01-19 22:30:20 UTC (rev 3041)
+++ zaptel/trunk/qozap/qozap.c	2007-01-20 19:53:28 UTC (rev 3042)
@@ -29,7 +29,7 @@
 static int pcmslave=0;
 static int bloop=0;
 static int debug=0;
-static int dacs=1;
+static int dacs=1; /* 0 = no dacs, 1 = oncard dacs */
 static struct qoz_card *qoz_dev_list = NULL;
 static int qoz_dev_count = 0;
 static int totalBRIs = 0;
@@ -215,9 +215,13 @@
     qoz_outb(qoztmp,qoz_R_IRQMSK_MISC, 0x2); 
 
     if (pcmslave) {
-	qoz_outb(qoztmp,qoz_R_PCM_MD0, 0x0);
+	qoz_outb(qoztmp,qoz_R_PCM_MD0, 0x90);
+	qoz_outb(qoztmp,qoz_R_PCM_MD1, 0x20);
+	qoz_outb(qoztmp,qoz_R_PCM_MD0, 0xA0);
+	qoz_outb(qoztmp,qoz_R_PCM_MD2, 0x4 | 0x8);
     } else {
-	qoz_outb(qoztmp,qoz_R_PCM_MD0, 0x1);
+	qoz_outb(qoztmp,qoz_R_PCM_MD0, 0x91);
+	qoz_outb(qoztmp,qoz_R_PCM_MD1, 0x20);
     }
 
     for (i=0; i<256; i++) {
@@ -495,7 +499,7 @@
     		data = qoz_inb(qoztmp,qoz_A_FIFO_DATA0);
 	    }
 	    qoztmp->clicks++;
-	    if ((qoztmp->clicks > 50) && (debug > 0)) {
+	    if ((qoztmp->clicks > 50) && (debug > 1)) {
 		printk(KERN_CRIT "qozap: dropped audio card %d cardid %d bytes %d z1 %d z2 %d\n", qoztmp->cardno, qoztmp->cardID, mumbojumbo, z1, z2);
 		qoztmp->clicks = 0;
 	    }
@@ -524,9 +528,8 @@
     return 0;
 }
 
-static void qoz_assign(struct qoz_card *qoztmp, int src_span, int src_chan, int dst_span, int dst_chan) {
+static void qoz_assign(struct qoz_card *qoztmp, int src_span, int src_chan, int dst_span, int dst_chan, int timeslot, int use_pcm_bus) {
     unsigned long flags;
-    int timeslot = src_span * 2 + (src_chan - 1);
     int dst_fifo = dst_span * 2 + (dst_chan - 1); 
     int src_fifo = src_span * 2 + (src_chan - 1); 
     int src_hfc_chan = src_span * 4 + (src_chan - 1);
@@ -557,10 +560,10 @@
     spin_unlock_irqrestore(&qoztmp->lock, flags);
 }
 
-static void qoz_unassign(struct qoz_card *qoztmp, int span, int chan) {
+static void qoz_unassign(struct qoz_card *qoztmp, int span, int chan, int timeslot) {
     unsigned long flags;
 
-    int timeslot = span * 2 + (chan - 1);
+//    int timeslot = span * 2 + (chan - 1);
     int fifo = span * 2 + (chan - 1);
     int hfc_chan = span * 4 + (chan - 1);
 
@@ -595,36 +598,48 @@
 static int ztqoz_dacs(struct zt_chan *dst, struct zt_chan *src)
 {
 	struct qoz_card *qoztmp = NULL;
+	int use_pcm_bus = 0;
+	int timeslot = 0;
 	if (!dacs) return 0;
 
-	if (src) { 
+	if (src) {
 	    qoztmp = src->pvt;
-	}
-	if (src && (src->pvt != dst->pvt)) {
-		/* cross card bridging */
-		if (debug)
-		    printk("Not Assigning %d/%d -> %d/%d, different cards!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
-		return -1;
-	}
 
-	if (src) {
-		if ((src->chanpos == 3) || (dst->chanpos == 3)) {
+	    if (src->pvt != dst->pvt) {
+		if (dacs == 2) {
+		    use_pcm_bus = 1;
+		    timeslot = src->channo;
 		    if (debug)
-			printk("Not Assigning D-channel %d/%d -> %d/%d!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
+			printk("qozap: Assigning channel %d/%d -> %d/%d, timeslot %d, different cards!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos, timeslot);
 		} else {
 		    if (debug)
-			printk("Assigning channel %d/%d -> %d/%d!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
-		    qoz_assign(qoztmp, src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
+			printk("qozap: Not Assigning %d/%d -> %d/%d, different cards!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
+		    return -1;
 		}
+	    } else {
+		use_pcm_bus = 0;
+//		timeslot = src->span->offset * 2 + (src->chanpos);
+		timeslot = src->channo;
+	        if (debug)
+	    	    printk("qozap: Assigning channel %d/%d -> %d/%d, timeslot %d, same card!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos, timeslot);
+	    }
+
+	    if ((src->chanpos == 3) || (dst->chanpos == 3)) {
+	        if (debug)
+			printk("qozap: Not Assigning D-channel %d/%d -> %d/%d!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
+	    } else {
+		qoz_assign(qoztmp, src->span->offset, src->chanpos, dst->span->offset, dst->chanpos, timeslot, use_pcm_bus);
+	    }
 	} else {
 		qoztmp = dst->pvt;
 		if (dst->chanpos == 3) {
 		    if (debug)
-			printk("Not Unassigning D-channel %d/%d!\n", dst->span->offset, dst->chanpos);
+			printk("qozap: Not Unassigning D-channel %d/%d!\n", dst->span->offset, dst->chanpos);
 		} else {
-		    qoz_unassign(qoztmp, dst->span->offset, dst->chanpos);
+		    timeslot = dst->channo;
+		    qoz_unassign(qoztmp, dst->span->offset, dst->chanpos, timeslot);
 		    if (debug)
-			printk("Unassigning channel %d/%d!\n", dst->span->offset, dst->chanpos);
+			printk("qozap: Unassigning channel %d/%d, timeslot %d!\n", dst->span->offset, dst->chanpos, timeslot);
 		}
 	}
 	return 0;
@@ -1370,7 +1385,7 @@
 	    memset(&(qoztmp->chans[s][i]),0x0,sizeof(struct zt_chan));
 	    sprintf(qoztmp->chans[s][i].name,"ztqoz%d/%d/%d",qoz_dev_count + 1,s + 1,i + 1);
 	    qoztmp->chans[s][i].pvt = qoztmp;
-	    qoztmp->chans[s][i].sigcap =  ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF;
+	    qoztmp->chans[s][i].sigcap =  ZT_SIG_CLEAR | ZT_SIG_DACS;
 	    qoztmp->chans[s][i].chanpos = i + 1; 
 	}
 

Modified: zaptel/trunk/ztgsm/ztgsm.c
===================================================================
--- zaptel/trunk/ztgsm/ztgsm.c	2007-01-19 22:30:20 UTC (rev 3041)
+++ zaptel/trunk/ztgsm/ztgsm.c	2007-01-20 19:53:28 UTC (rev 3042)
@@ -25,6 +25,7 @@
 
 static int debug=0;
 static int pcm_xbar=0;
+static int sim = 0;
 static struct ztgsm_card *ztgsm_dev_list = NULL;
 static int ztgsm_dev_count = 0;
 static int ztgsm_spans = 0;
@@ -91,11 +92,15 @@
     spin_unlock_irqrestore(&(gsmtmp->lock),flags);
 
     printk(" done.\n");
+    gsmtmp->gsmspan[span].span.alarms = ZT_ALARM_NONE;
+    zt_alarm_notify(&gsmtmp->gsmspan[span].span);
 }
 
 void ztgsm_switch_off(struct ztgsm_card *gsmtmp, int span) {
     unsigned int dtr_on_off = 0;
     unsigned long flags;
+    gsmtmp->gsmspan[span].span.alarms = ZT_ALARM_RED;
+    zt_alarm_notify(&gsmtmp->gsmspan[span].span);
 
     spin_lock_irqsave(&(gsmtmp->lock),flags);
 	gsmtmp->gsmspan[span].led = 0xC0;
@@ -119,9 +124,10 @@
     printk(" done.\n");
 }
 
-void ztgsm_switch_on_all(struct ztgsm_card *gsmtmp) {
+void ztgsm_switch_on_all(struct ztgsm_card *gsmtmp, int verbose) {
     unsigned long flags;
-    printk(KERN_INFO "ztgsm: Powering up all spans...");
+    if (verbose)
+	printk(KERN_INFO "ztgsm: Powering up all spans...");
     spin_lock_irqsave(&(gsmtmp->lock),flags);
 	gsmtmp->gsmspan[0].led = 0xC1;
         gsmtmp->gsmspan[1].led = 0xC1;
@@ -174,20 +180,22 @@
 	gsmtmp->gsmspan[3].led = 0x81;
     spin_unlock_irqrestore(&(gsmtmp->lock),flags);
 
-    printk(" done.\n");
+    if (verbose)
+	printk(" done.\n");
 }
 
-void ztgsm_switch_off_all(struct ztgsm_card *gsmtmp) {
+void ztgsm_switch_off_all(struct ztgsm_card *gsmtmp, int verbose) {
     unsigned long flags;
 
     if (gsmtmp->power[0] || gsmtmp->power[1] || gsmtmp->power[2] || gsmtmp->power[3]) { 
+    if (verbose)
+        printk(KERN_INFO "ztgsm: Powering down all spans...");
     spin_lock_irqsave(&(gsmtmp->lock),flags);
 	gsmtmp->gsmspan[0].led = 0xC0;
         gsmtmp->gsmspan[1].led = 0xC0;
 	gsmtmp->gsmspan[2].led = 0xC0;
         gsmtmp->gsmspan[3].led = 0xC0;
 	
-	printk(KERN_INFO "ztgsm: Powering down all spans...");
 	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, 0x0);
     spin_unlock_irqrestore(&(gsmtmp->lock),flags);
 
@@ -196,7 +204,6 @@
 
     spin_lock_irqsave(&(gsmtmp->lock),flags);
 	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, 0xf);
-	printk(" done.\n");
 
 	gsmtmp->power[0] = 0;
 	gsmtmp->power[1] = 0;
@@ -208,6 +215,8 @@
         gsmtmp->gsmspan[2].led = 0x80;
 	gsmtmp->gsmspan[3].led = 0x80;
     spin_unlock_irqrestore(&(gsmtmp->lock),flags);
+    if (verbose)
+        printk(" done.\n");
     }
 }
 
@@ -216,58 +225,45 @@
     unsigned long flags;
     struct ztgsm_span *gsmspan = NULL;
     int i = 0;
+    unsigned long ioport;
+    unsigned long pci_io_phys;
+    unsigned long iomem_size;
+    void *pci_io;
+
     if (gsmtmp == NULL) {
 	printk(KERN_INFO "ztgsm: shutting down NULL card!\n");
 	return;
     }
 
-    ztgsm_switch_off_all(gsmtmp);
+    ztgsm_switch_off_all(gsmtmp, 1);
 
     spin_lock_irqsave(&gsmtmp->lock,flags);
 
-    gsmtmp->dead = 1;
+	gsmtmp->dead = 1;
 
-    if ((!gsmtmp->pci_io) || (gsmtmp->ioport == 0)) {
-	return;
-    }
-    ztgsm_outdw_io(gsmtmp, ztgsm_SER_INT_MASK, 0x0);
-    ztgsm_outdw_io(gsmtmp, ztgsm_PCM_FC_TOG_BIT, 0x0);
-    ztgsm_outdw_io(gsmtmp, ztgsm_PCM_SAP_EN, 0x0);
+        if ((!gsmtmp->pci_io) || (gsmtmp->ioport == 0)) {
+	    return;
+	}
+	ztgsm_outdw_io(gsmtmp, ztgsm_SER_INT_MASK, 0x0);
+	ztgsm_outdw_io(gsmtmp, ztgsm_PCM_FC_TOG_BIT, 0x0);
+	ztgsm_outdw_io(gsmtmp, ztgsm_PCM_SAP_EN, 0x0);
 
+	ztgsm_outdw_io(gsmtmp, ztgsm_LED_DUAL, 0xFF00);
 
-/*    for (i=0; i < gsmtmp->gsmspans; i++) {
-	ztgsm_switch_off(gsmtmp, i);
-    }  */
+	ioport = gsmtmp->ioport;
+	pci_io = gsmtmp->pci_io;
+	pci_io_phys = gsmtmp->pci_io_phys;
+        iomem_size = gsmtmp->iomem_size;
 
+	gsmtmp->pci_io = 0;
+	gsmtmp->ioport = 0;
 
-    ztgsm_outdw_io(gsmtmp, ztgsm_LED_DUAL, 0xFF00);
+    spin_unlock_irqrestore(&gsmtmp->lock,flags);
 
 
-    // softreset
-
-    release_region(gsmtmp->ioport, 0x100);
-    iounmap((void *) gsmtmp->pci_io);
-    release_mem_region(gsmtmp->pci_io_phys, gsmtmp->iomem_size);
-
-    gsmtmp->pci_io = 0;
-    gsmtmp->ioport = 0;
-
-    // turn off irqs
-
-    free_irq(gsmtmp->irq,gsmtmp);
-
-    pci_write_config_word(gsmtmp->pcidev, PCI_COMMAND, 0);	
-
-    if (gsmtmp->pcidev != NULL) {
-        pci_disable_device(gsmtmp->pcidev);
-    }
-    
-    spin_unlock_irqrestore(&gsmtmp->lock,flags);
-
     for (i=0; i < gsmtmp->gsmspans; i++) {
 	gsmspan = &gsmtmp->gsmspan[i];
         if(gsmspan->span.flags & ZT_FLAG_RUNNING) {
-//	    ztgsm_shutdown(&gsmspan->span);
 	    if (debug)
 	        printk(KERN_INFO "ztgsm: shutdown card %d span %d.\n",gsmtmp->cardno,i);
 	}
@@ -278,6 +274,23 @@
 	}
     }
 
+
+    release_region(ioport, 0x100);
+    iounmap((void *) pci_io);
+    release_mem_region(pci_io_phys, iomem_size);
+
+
+    spin_lock_irqsave(&gsmtmp->lock,flags);
+
+	free_irq(gsmtmp->irq,gsmtmp);
+
+	pci_write_config_word(gsmtmp->pcidev, PCI_COMMAND, 0);	
+
+	if (gsmtmp->pcidev != NULL) {
+    	    pci_disable_device(gsmtmp->pcidev);
+	}
+
+    spin_unlock_irqrestore(&gsmtmp->lock,flags);
 }
 
 void ztgsm_register_card(struct ztgsm_card *gsmtmp) {
@@ -326,7 +339,11 @@
     ztgsm_outdw_io(gsmtmp, ztgsm_PCM_FC_TOG_BIT, 0x03);
     ztgsm_outdw_io(gsmtmp, ztgsm_SER_INT_MASK, 0x1FFFF);
     ztgsm_outdw_io(gsmtmp, ztgsm_SER_RX_WATERMARK, 0x0A);
-    ztgsm_outdw_io(gsmtmp, ztgsm_SIM_SEL, 0x0);
+    if (sim) {
+	ztgsm_outdw_io(gsmtmp, ztgsm_SIM_SEL, sim);
+    } else {
+	ztgsm_outdw_io(gsmtmp, ztgsm_SIM_SEL, 0x0);
+    }
     ztgsm_outdw_io(gsmtmp, ztgsm_PCM_SAP_EN, 0x0);
     ztgsm_outdw_io(gsmtmp, ztgsm_PCM_MASK_LAST, 0x001F0000 | 0x1F); /* PCM32 0x100 frames */
 //    ztgsm_outdw_io(gsmtmp, ztgsm_PCM_MASK_LAST, (0x001FC000 | 0x1F)); /* PCM32 0x40 frames */
@@ -926,9 +943,10 @@
     running = span->flags & ZT_FLAG_RUNNING;
 
     if (running) {
-	span->flags |= ZT_FLAG_RUNNING;
-	if (gsmtmp->power[span->offset]) 
+	span->flags &= ~ZT_FLAG_RUNNING;
+	if (gsmtmp->power[span->offset]) {
 	    ztgsm_switch_off(gsmtmp, span->offset);
+	}
     }
     return 0;
 }
@@ -1151,7 +1169,20 @@
 	ztgsm_register_card(gsmtmp);
 
 	ztgsm_startCard(gsmtmp);
-	ztgsm_switch_on_all(gsmtmp);
+
+	if (sim >= 0x10) {
+	    printk(KERN_INFO "ztgsm: Invalid value for parameter sim.\n");
+	    sim = 0;
+	}
+
+	if (sim) {
+	    ztgsm_switch_off_all(gsmtmp, 0);
+	    printk(KERN_INFO "ztgsm: Initializing SIM extensions...");
+	    ztgsm_switch_on_all(gsmtmp, 0);
+	    printk("done\n");
+	} else {
+	    ztgsm_switch_on_all(gsmtmp, 1);
+	}
 	
 	tmp = pci_find_device(PCI_VENDOR_ID_CCD,pcidid,multi_gsm);
     }
@@ -1193,9 +1224,11 @@
 #ifdef LINUX26
 module_param(debug, int, 0600);
 module_param(pcm_xbar, int, 0600);
+module_param(sim, int, 0600);
 #else
 MODULE_PARM(debug,"i");
 MODULE_PARM(pcm_xbar,"i");
+MODULE_PARM(sim,"i");
 #endif
 
 MODULE_DESCRIPTION("uno/duao/quad GSM zaptel driver");




More information about the Pkg-voip-commits mailing list