Index: dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.h =================================================================== --- dahdi-linux-2.1.0.4.orig/drivers/dahdi/zaphfc.h 2009-03-17 18:13:54.000000000 +0200 +++ dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.h 2009-03-17 18:14:44.000000000 +0200 @@ -135,8 +135,12 @@ /* bits in HFCD_MST_MODE */ #define hfc_MST_MODE_MASTER 0x01 #define hfc_MST_MODE_SLAVE 0x00 +#define hfc_MST_MODE_F0_LONG_DURATION 0x08 /* remaining bits are for codecs control */ +/* bits in HFCD_MST_EMOD */ +#define hfc_MST_EMOD_SLOW_CLOCK_ADJ 0x01 + /* bits in HFCD_SCTRL */ #define hfc_SCTRL_B1_ENA 0x01 #define hfc_SCTRL_B2_ENA 0x02 @@ -236,6 +240,9 @@ #define hfc_BTRANS_THRESHOLD 128 #define hfc_BTRANS_THRESMASK 0x00 +#define hfc_FIFO_MEM_SIZE_BYTES (32*1024) +#define hfc_FIFO_MEM_SIZE_PAGES ((hfc_FIFO_MEM_SIZE_BYTES+PAGE_SIZE-1)/PAGE_SIZE) + /* Structures */ typedef struct hfc_regs { @@ -249,20 +256,67 @@ unsigned char connect; unsigned char trm; unsigned char mst_mode; + unsigned char mst_emod; unsigned char bswapped; unsigned char nt_mode; unsigned char int_drec; } hfc_regs; +struct bch { + int fill_fifo,checkcnt,initialized; + struct { + u16 z2; + struct { + volatile u16 *z1p; + volatile u8 *fifo_base; + int filled; + } c[2]; + int diff; + } rx; + struct { + u16 z1; + struct { + volatile u16 *z1p,*z2p; + volatile u8 *fifo_base; + int filled; + } c[2]; + int diff; + } tx; +}; + +struct dch { + struct { + struct { + volatile u8 *p; + } f1; + struct { + u8 v; + struct { + u16 v; + } z2; + } f2; + } rx; + struct { + struct { + u8 v; + volatile u8 *p; + struct { + u16 v; + } z1; + } f1; + struct { + volatile u8 *p; + } f2; + } tx; +}; + typedef struct hfc_card { spinlock_t lock; unsigned int irq; unsigned int iomem; int ticks; - int clicks; unsigned char *pci_io; - void *fifomem; // start of the shared mem - volatile void *fifos; // 32k aligned mem for the fifos + void *fifos; // 32k aligned mem for the fifos struct hfc_regs regs; unsigned int pcibus; unsigned int pcidevfn; @@ -274,6 +328,9 @@ unsigned char brecbuf[2][DAHDI_CHUNKSIZE]; unsigned char btransbuf[2][DAHDI_CHUNKSIZE]; unsigned char cardno; + int active; + struct bch bch; + struct dch dch; struct hfc_card *next; } hfc_card; @@ -285,6 +342,3 @@ struct hfc_card *card; } dahdi_hfc; -/* tune this */ -#define hfc_BCHAN_BUFFER 8 -#define hfc_MAX_CARDS 8 Index: dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.c =================================================================== --- dahdi-linux-2.1.0.4.orig/drivers/dahdi/zaphfc.c 2009-03-17 18:52:47.000000000 +0200 +++ dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.c 2009-03-17 18:53:43.000000000 +0200 @@ -7,19 +7,21 @@ * * Klaus-Peter Junghanns * + * Copyright (C) 2004, 2005, 2006 Florian Zumbiehl + * - support for slave mode of the HFC-S chip which allows it to + * sync its sample clock to an external source/another HFC chip + * - support for "interrupt bundling" (let only one card generate + * 8 kHz timing interrupt no matter how many cards there are + * in the system) + * - interrupt loss tolerant b channel handling + * * This program is free software and may be modified and - * distributed under the terms of the GNU Public License. + * distributed under the terms of the GNU General Public License. * */ #include #include -#ifdef RTAITIMING -#include -#include -#include -#include -#endif #include #include #include @@ -29,6 +31,8 @@ #include +#define log2(n) ffz(~(n)) + #if CONFIG_PCI #define CLKDEL_TE 0x0f /* CLKDEL in TE mode */ @@ -70,42 +74,31 @@ static struct hfc_card *hfc_dev_list = NULL; static int hfc_dev_count = 0; static int modes = 0; // all TE +static int sync_slave = 0; // all master +static int timer_card = 0; +static int jitterbuffer = 1; static int debug = 0; static struct pci_dev *multi_hfc = NULL; static spinlock_t registerlock = SPIN_LOCK_UNLOCKED; -void hfc_shutdownCard(struct hfc_card *hfctmp) { - unsigned long flags; - - if (hfctmp == NULL) { - return; - } - - if (hfctmp->pci_io == NULL) { - return; - } - - spin_lock_irqsave(&hfctmp->lock,flags); - +void hfc_shutdownCard1(struct hfc_card *hfctmp) { printk(KERN_INFO "zaphfc: shutting down card at %p.\n",hfctmp->pci_io); /* Clear interrupt mask */ hfctmp->regs.int_m2 = 0; hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2); - /* Reset pending interrupts */ - hfc_inb(hfctmp, hfc_INT_S1); + /* Remove interrupt handler */ + free_irq(hfctmp->irq,hfctmp); +} + +void hfc_shutdownCard2(struct hfc_card *hfctmp) { + unsigned long flags; - /* Wait for interrupts that might still be pending */ - spin_unlock_irqrestore(&hfctmp->lock, flags); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30 * HZ) / 1000); // wait 30 ms spin_lock_irqsave(&hfctmp->lock,flags); - /* Remove interrupt handler */ - if (hfctmp->irq) { - free_irq(hfctmp->irq, hfctmp); - } + /* Reset pending interrupts */ + hfc_inb(hfctmp, hfc_INT_S1); /* Soft-reset the card */ hfc_outb(hfctmp, hfc_CIRM, hfc_CIRM_RESET); // softreset on @@ -119,8 +112,8 @@ pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, 0); // disable memio and bustmaster - if (hfctmp->fifomem != NULL) { - kfree(hfctmp->fifomem); + if (hfctmp->fifos != NULL) { + free_pages((unsigned long)hfctmp->fifos,log2(hfc_FIFO_MEM_SIZE_PAGES)); } iounmap((void *) hfctmp->pci_io); hfctmp->pci_io = NULL; @@ -130,11 +123,24 @@ spin_unlock_irqrestore(&hfctmp->lock,flags); if (hfctmp->ztdev != NULL) { dahdi_unregister(&hfctmp->ztdev->span); - kfree(hfctmp->ztdev); + vfree(hfctmp->ztdev); printk(KERN_INFO "unregistered from DAHDI.\n"); } } +void hfc_shutdownCard(struct hfc_card *hfctmp) { + if (hfctmp == NULL) { + return; + } + + if (hfctmp->pci_io == NULL) { + return; + } + + hfc_shutdownCard1(hfctmp); + hfc_shutdownCard2(hfctmp); +} + void hfc_resetCard(struct hfc_card *hfctmp) { unsigned long flags; @@ -178,14 +184,14 @@ hfctmp->regs.ctmt = hfc_CTMT_TRANSB1 | hfc_CTMT_TRANSB2; // all bchans are transparent , no freaking hdlc hfc_outb(hfctmp, hfc_CTMT, hfctmp->regs.ctmt); - hfctmp->regs.int_m1 = 0; + hfctmp->regs.int_m1=hfc_INTS_L1STATE; + if(hfctmp->cardno==timer_card){ + hfctmp->regs.int_m2=hfc_M2_PROC_TRANS; + }else{ + hfctmp->regs.int_m1|=hfc_INTS_DREC; + hfctmp->regs.int_m2=0; + } hfc_outb(hfctmp, hfc_INT_M1, hfctmp->regs.int_m1); - -#ifdef RTAITIMING - hfctmp->regs.int_m2 = 0; -#else - hfctmp->regs.int_m2 = hfc_M2_PROC_TRANS; -#endif hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2); /* Clear already pending ints */ @@ -197,8 +203,8 @@ hfctmp->regs.sctrl = 3 | hfc_SCTRL_NONE_CAP | hfc_SCTRL_MODE_TE; /* set tx_lo mode, error in datasheet ! */ } - hfctmp->regs.mst_mode = hfc_MST_MODE_MASTER; /* HFC Master Mode */ hfc_outb(hfctmp, hfc_MST_MODE, hfctmp->regs.mst_mode); + hfc_outb(hfctmp, hfc_MST_EMOD, hfctmp->regs.mst_emod); hfc_outb(hfctmp, hfc_SCTRL, hfctmp->regs.sctrl); hfctmp->regs.sctrl_r = 3; @@ -210,10 +216,8 @@ hfc_outb(hfctmp, hfc_CIRM, 0x80 | 0x40); // bit order /* Finally enable IRQ output */ -#ifndef RTAITIMING hfctmp->regs.int_m2 |= hfc_M2_IRQ_ENABLE; hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2); -#endif /* clear pending ints */ hfc_inb(hfctmp, hfc_INT_S1); @@ -230,368 +234,210 @@ spin_unlock(®isterlock); } -static void hfc_btrans(struct hfc_card *hfctmp, char whichB) { - // we are called with irqs disabled from the irq handler - int count, maxlen, total; - unsigned char *f1, *f2; - unsigned short *z1, *z2, newz1; - int freebytes; - - if (whichB == 1) { - f1 = (char *)(hfctmp->fifos + hfc_FIFO_B1TX_F1); - f2 = (char *)(hfctmp->fifos + hfc_FIFO_B1TX_F2); - z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1TX_Z1 + (*f1 * 4)); - z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1TX_Z2 + (*f1 * 4)); - } else { - f1 = (char *)(hfctmp->fifos + hfc_FIFO_B2TX_F1); - f2 = (char *)(hfctmp->fifos + hfc_FIFO_B2TX_F2); - z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2TX_Z1 + (*f1 * 4)); - z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2TX_Z2 + (*f1 * 4)); - } - - freebytes = *z2 - *z1; - if (freebytes <= 0) { - freebytes += hfc_B_FIFO_SIZE; - } - count = DAHDI_CHUNKSIZE; - - total = count; - if (freebytes < count) { - hfctmp->clicks++; - /* only spit out this warning once per second to not make things worse! */ - if (hfctmp->clicks > 100) { - printk(KERN_CRIT "zaphfc: bchan tx fifo full, dropping audio! (z1=%d, z2=%d)\n",*z1,*z2); - hfctmp->clicks = 0; - } - return; - } - - maxlen = (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL) - *z1; - if (maxlen > count) { - maxlen = count; - } - newz1 = *z1 + total; - if (newz1 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { newz1 -= hfc_B_FIFO_SIZE; } +/*===========================================================================*/ - if (whichB == 1) { - memcpy((char *)(hfctmp->fifos + hfc_FIFO_B1TX_ZOFF + *z1),hfctmp->ztdev->chans[0].writechunk, maxlen); - } else { - memcpy((char *)(hfctmp->fifos + hfc_FIFO_B2TX_ZOFF + *z1),hfctmp->ztdev->chans[1].writechunk, maxlen); - } - - count -= maxlen; - if (count > 0) { - // Buffer wrap - if (whichB == 1) { - memcpy((char *)(hfctmp->fifos + hfc_FIFO_B1TX_ZOFF + hfc_B_SUB_VAL),hfctmp->ztdev->chans[0].writechunk+maxlen, count); - } else { - memcpy((char *)(hfctmp->fifos + hfc_FIFO_B2TX_ZOFF + hfc_B_SUB_VAL),hfctmp->ztdev->chans[1].writechunk+maxlen, count); - } - } +#if hfc_B_FIFO_SIZE%DAHDI_CHUNKSIZE +#error hfc_B_FIFO_SIZE is not a multiple of DAHDI_CHUNKSIZE even though the code assumes this +#endif + +static void hfc_dch_init(struct hfc_card *hfctmp){ + struct dch *chtmp=&hfctmp->dch; - *z1 = newz1; /* send it now */ + chtmp->rx.f1.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DRX_F1); + chtmp->rx.f2.v=0x1f; + chtmp->rx.f2.z2.v=0x1ff; -// if (count > 0) printk(KERN_CRIT "zaphfc: bchan tx fifo (f1=%d, f2=%d, z1=%d, z2=%d)\n",(*f1) & hfc_FMASK,(*f2) & hfc_FMASK, *z1, *z2); - return; + chtmp->tx.f1.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DTX_F1); + chtmp->tx.f1.v=0x1f; + chtmp->tx.f1.z1.v=0x1ff; + chtmp->tx.f2.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DTX_F2); } -static void hfc_brec(struct hfc_card *hfctmp, char whichB) { - // we are called with irqs disabled from the irq handler - int count, maxlen, drop; - volatile unsigned char *f1, *f2; - volatile unsigned short *z1, *z2, newz2; - int bytes = 0; - - if (whichB == 1) { - f1 = (char *)(hfctmp->fifos + hfc_FIFO_B1RX_F1); - f2 = (char *)(hfctmp->fifos + hfc_FIFO_B1RX_F2); - z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z1 + (*f1 * 4)); - z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z2 + (*f1 * 4)); - } else { - f1 = (char *)(hfctmp->fifos + hfc_FIFO_B2RX_F1); - f2 = (char *)(hfctmp->fifos + hfc_FIFO_B2RX_F2); - z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z1 + (*f1 * 4)); - z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z2 + (*f1 * 4)); - } +static void hfc_bch_init(struct hfc_card *hfctmp){ + struct bch *chtmp=&hfctmp->bch; - bytes = *z1 - *z2; - if (bytes < 0) { - bytes += hfc_B_FIFO_SIZE; - } - count = DAHDI_CHUNKSIZE; - - if (bytes < DAHDI_CHUNKSIZE) { -#ifndef RTAITIMING - printk(KERN_CRIT "zaphfc: bchan rx fifo not enough bytes to receive! (z1=%d, z2=%d, wanted %d got %d), probably a buffer overrun.\n",*z1,*z2,DAHDI_CHUNKSIZE,bytes); -#endif - return; - } + chtmp->checkcnt=0; + chtmp->fill_fifo=0; - /* allowing the buffering of hfc_BCHAN_BUFFER bytes of audio data works around irq jitter */ - if (bytes > hfc_BCHAN_BUFFER + DAHDI_CHUNKSIZE) { - /* if the system is too slow to handle it, we will have to drop it all (except 1 DAHDI chunk) */ - drop = bytes - DAHDI_CHUNKSIZE; - hfctmp->clicks++; - /* only spit out this warning once per second to not make things worse! */ - if (hfctmp->clicks > 100) { - printk(KERN_CRIT "zaphfc: dropped audio (z1=%d, z2=%d, wanted %d got %d, dropped %d).\n",*z1,*z2,count,bytes,drop); - hfctmp->clicks = 0; - } - /* hm, we are processing the b chan data tooooo slowly... let's drop the lost audio */ - newz2 = *z2 + drop; - if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { - newz2 -= hfc_B_FIFO_SIZE; - } - *z2 = newz2; - } + chtmp->rx.c[0].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1RX_Z1+0x1f*4); + chtmp->rx.c[0].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B1RX_ZOFF); + chtmp->rx.c[1].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2RX_Z1+0x1f*4); + chtmp->rx.c[1].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B2RX_ZOFF); + chtmp->rx.z2=hfc_B_SUB_VAL; + chtmp->rx.diff=0; - - maxlen = (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL) - *z2; - if (maxlen > count) { - maxlen = count; - } - if (whichB == 1) { - memcpy(hfctmp->ztdev->chans[0].readchunk,(char *)(hfctmp->fifos + hfc_FIFO_B1RX_ZOFF + *z2), maxlen); - } else { - memcpy(hfctmp->ztdev->chans[1].readchunk,(char *)(hfctmp->fifos + hfc_FIFO_B2RX_ZOFF + *z2), maxlen); - } - newz2 = *z2 + count; - if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { - newz2 -= hfc_B_FIFO_SIZE; + chtmp->tx.c[0].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1TX_Z1+0x1f*4); + chtmp->tx.c[0].z2p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1TX_Z2+0x1f*4); + chtmp->tx.c[0].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B1TX_ZOFF); + chtmp->tx.c[0].filled=0; + chtmp->tx.c[1].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2TX_Z1+0x1f*4); + chtmp->tx.c[1].z2p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2TX_Z2+0x1f*4); + chtmp->tx.c[1].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B2TX_ZOFF); + chtmp->tx.c[1].filled=0; + chtmp->tx.z1=hfc_B_SUB_VAL; + chtmp->tx.diff=0; + + hfc_dch_init(hfctmp); + + chtmp->initialized=0; +} + +static int hfc_bch_check(struct hfc_card *hfctmp){ + struct bch *chtmp=&hfctmp->bch; + int x,r; + + for(x=0;x<2;x++){ + chtmp->tx.c[x].filled=(chtmp->tx.z1-*chtmp->tx.c[x].z2p+hfc_B_FIFO_SIZE)%hfc_B_FIFO_SIZE; + chtmp->rx.c[x].filled=(*chtmp->rx.c[x].z1p-chtmp->rx.z2+hfc_B_FIFO_SIZE)%hfc_B_FIFO_SIZE; } - *z2 = newz2; - - count -= maxlen; - if (count > 0) { - // Buffer wrap - if (whichB == 1) { - z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z2 + (*f1 * 4)); - memcpy(hfctmp->ztdev->chans[0].readchunk + maxlen,(char *)(hfctmp->fifos + hfc_FIFO_B1RX_ZOFF + hfc_B_SUB_VAL), count); - } else { - z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z2 + (*f1 * 4)); - memcpy(hfctmp->ztdev->chans[1].readchunk + maxlen,(char *)(hfctmp->fifos + hfc_FIFO_B2RX_ZOFF + hfc_B_SUB_VAL), count); - } - newz2 = *z2 + count; - if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { - newz2 -= hfc_B_FIFO_SIZE; + if(chtmp->fill_fifo){ + chtmp->checkcnt++; + chtmp->checkcnt%=DAHDI_CHUNKSIZE; + r=!chtmp->checkcnt; + }else{ + x=chtmp->tx.c[0].filled-chtmp->tx.c[1].filled; + if(abs(x-chtmp->tx.diff)>1){ + printk(KERN_CRIT "zaphfc[%d]: tx sync changed: %d, %d\n",hfctmp->cardno,chtmp->tx.c[0].filled,chtmp->tx.c[1].filled); + chtmp->tx.diff=x; } + r=chtmp->tx.c[0].filled<=DAHDI_CHUNKSIZE*jitterbuffer&&chtmp->tx.c[1].filled<=DAHDI_CHUNKSIZE*jitterbuffer; } + return(r); +} +#define hfc_bch_inc_z(a,b) (a)=((a)-hfc_B_SUB_VAL+(b))%hfc_B_FIFO_SIZE+hfc_B_SUB_VAL - if (whichB == 1) { - dahdi_ec_chunk(&hfctmp->ztdev->chans[0], hfctmp->ztdev->chans[0].readchunk, hfctmp->ztdev->chans[0].writechunk); - } else { - dahdi_ec_chunk(&hfctmp->ztdev->chans[1], hfctmp->ztdev->chans[1].readchunk, hfctmp->ztdev->chans[1].writechunk); +static void hfc_bch_tx(struct hfc_card *hfctmp){ + struct bch *chtmp=&hfctmp->bch; + int x; + + for(x=0;x<2;x++) + memcpy((void *)(chtmp->tx.c[x].fifo_base+chtmp->tx.z1),hfctmp->ztdev->chans[x].writechunk,DAHDI_CHUNKSIZE); + hfc_bch_inc_z(chtmp->tx.z1,DAHDI_CHUNKSIZE); + if(chtmp->fill_fifo){ + chtmp->fill_fifo--; + }else if(chtmp->tx.c[0].filled<=1||chtmp->tx.c[1].filled<=1){ + chtmp->fill_fifo=jitterbuffer; + if(chtmp->initialized) + printk(KERN_CRIT "zaphfc[%d]: b channel buffer underrun: %d, %d\n",hfctmp->cardno,chtmp->tx.c[0].filled,chtmp->tx.c[1].filled); } - return; + if(!chtmp->fill_fifo) + for(x=0;x<2;x++)*chtmp->tx.c[x].z1p=chtmp->tx.z1; } - -static void hfc_dtrans(struct hfc_card *hfctmp) { - // we are called with irqs disabled from the irq handler +static void hfc_bch_rx(struct hfc_card *hfctmp){ + struct bch *chtmp=&hfctmp->bch; int x; - int count, maxlen, total; - unsigned char *f1, *f2, newf1; - unsigned short *z1, *z2, newz1; - int frames, freebytes; - if (hfctmp->ztdev->chans[2].bytes2transmit == 0) { - return; + x=chtmp->rx.c[0].filled-chtmp->rx.c[1].filled; + if(abs(x-chtmp->rx.diff)>1){ + printk(KERN_CRIT "zaphfc[%d]: rx sync changed: %d, %d\n",hfctmp->cardno,chtmp->rx.c[0].filled,chtmp->rx.c[1].filled); + chtmp->rx.diff=x; } - - f1 = (char *)(hfctmp->fifos + hfc_FIFO_DTX_F1); - f2 = (char *)(hfctmp->fifos + hfc_FIFO_DTX_F2); - z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z1 + (*f1 * 4)); - z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z2 + (*f1 * 4)); - - frames = (*f1 - *f2) & hfc_FMASK; - if (frames < 0) { - frames += hfc_MAX_DFRAMES + 1; + if(chtmp->rx.c[0].filled>=DAHDI_CHUNKSIZE&&chtmp->rx.c[1].filled>=DAHDI_CHUNKSIZE){ + if((chtmp->rx.c[0].filled>=DAHDI_CHUNKSIZE*(jitterbuffer+2)&&chtmp->rx.c[1].filled>=DAHDI_CHUNKSIZE*(jitterbuffer+2))||!chtmp->initialized){ + if(chtmp->initialized) + printk(KERN_CRIT "zaphfc[%d]: b channel buffer overflow: %d, %d\n",hfctmp->cardno,chtmp->rx.c[0].filled,chtmp->rx.c[1].filled); + hfc_bch_inc_z(chtmp->rx.z2,chtmp->rx.c[0].filled-chtmp->rx.c[0].filled%DAHDI_CHUNKSIZE-DAHDI_CHUNKSIZE); + chtmp->initialized=1; + } + for(x=0;x<2;x++){ + memcpy(hfctmp->ztdev->chans[x].readchunk,(void *)(chtmp->rx.c[x].fifo_base+chtmp->rx.z2),DAHDI_CHUNKSIZE); + dahdi_ec_chunk(&hfctmp->ztdev->chans[x],hfctmp->ztdev->chans[x].readchunk,hfctmp->ztdev->chans[x].writechunk); + } + hfc_bch_inc_z(chtmp->rx.z2,DAHDI_CHUNKSIZE); } +} - if (frames >= hfc_MAX_DFRAMES) { - printk(KERN_CRIT "zaphfc: dchan tx fifo total number of frames exceeded!\n"); - return; - } +/*===========================================================================*/ - freebytes = *z2 - *z1; - if (freebytes <= 0) { - freebytes += hfc_D_FIFO_SIZE; - } - count = hfctmp->ztdev->chans[2].bytes2transmit; - - total = count; - if (freebytes < count) { - printk(KERN_CRIT "zaphfc: dchan tx fifo not enough free bytes! (z1=%d, z2=%d)\n",*z1,*z2); - return; - } - - newz1 = (*z1 + count) & hfc_ZMASK; - newf1 = ((*f1 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); // next frame - - if (count > 0) { - if (debug) { - printk(KERN_CRIT "zaphfc: card %d TX [ ", hfctmp->cardno); - for (x=0; xdch; + u8 tx_f2_v; + u16 x; + + if(hfctmp->ztdev->chans[2].bytes2transmit){ + if(debug){ + printk(KERN_CRIT "zaphfc[%d]: card TX [ ",hfctmp->cardno); + for(x=0;xztdev->chans[2].bytes2transmit;x++){ printk("%#2x ",hfctmp->dtransbuf[x]); } - if (hfctmp->ztdev->chans[2].eoftx == 1) { - printk("] %d bytes\n", count); - } else { - printk("..] %d bytes\n", count); - } - } - maxlen = hfc_D_FIFO_SIZE - *z1; - if (maxlen > count) { - maxlen = count; + printk("] %d bytes\n",hfctmp->ztdev->chans[2].bytes2transmit); } - memcpy((char *)(hfctmp->fifos + hfc_FIFO_DTX_ZOFF + *z1),hfctmp->ztdev->chans[2].writechunk, maxlen); - count -= maxlen; - if (count > 0) { - memcpy((char *)(hfctmp->fifos + hfc_FIFO_DTX_ZOFF),(char *)(hfctmp->ztdev->chans[2].writechunk + maxlen), count); + tx_f2_v=*chtmp->tx.f2.p; + if(!(tx_f2_v-chtmp->tx.f1.v+hfc_MAX_DFRAMES+1-1)&(hfc_MAX_DFRAMES+1-1)){ + printk(KERN_CRIT "zaphfc[%d]: dchan tx fifo total number of frames exceeded!\n",hfctmp->cardno); + }else{ + if(((*(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z2+tx_f2_v*4)-chtmp->tx.f1.z1.v+hfc_D_FIFO_SIZE-1)&(hfc_D_FIFO_SIZE-1))ztdev->chans[2].bytes2transmit){ + printk(KERN_CRIT "zaphfc[%d]: dchan tx fifo not enough space for frame!\n",hfctmp->cardno); + }else{ + chtmp->tx.f1.v=((chtmp->tx.f1.v+1)&hfc_MAX_DFRAMES)|(hfc_MAX_DFRAMES+1); + x=min(hfctmp->ztdev->chans[2].bytes2transmit,hfc_D_FIFO_SIZE-chtmp->tx.f1.z1.v); + memcpy(hfctmp->fifos+hfc_FIFO_DTX_ZOFF+chtmp->tx.f1.z1.v,hfctmp->ztdev->chans[2].writechunk,x); + memcpy(hfctmp->fifos+hfc_FIFO_DTX_ZOFF,hfctmp->ztdev->chans[2].writechunk+x,hfctmp->ztdev->chans[2].bytes2transmit-x); + *(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z2+chtmp->tx.f1.v*4)=chtmp->tx.f1.z1.v; + chtmp->tx.f1.z1.v=(chtmp->tx.f1.z1.v+hfctmp->ztdev->chans[2].bytes2transmit+hfc_D_FIFO_SIZE)&(hfc_D_FIFO_SIZE-1); + *(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z1+chtmp->tx.f1.v*4)=chtmp->tx.f1.z1.v; + *chtmp->tx.f1.p=chtmp->tx.f1.v; + } } } - - *z1 = newz1; - - if (hfctmp->ztdev->chans[2].eoftx == 1) { - *f1 = newf1; - z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z1 + (*f1 * 4)); - *z1 = newz1; - hfctmp->ztdev->chans[2].eoftx = 0; - } -// printk(KERN_CRIT "zaphfc: dchan tx fifo (f1=%d, f2=%d, z1=%d, z2=%d)\n",(*f1) & hfc_FMASK,(*f2) & hfc_FMASK, *z1, *z2); - return; } -/* receive a complete hdlc frame, skip broken or short frames */ -static void hfc_drec(struct hfc_card *hfctmp) { - int count=0, maxlen=0, framelen=0; - unsigned char *f1, *f2, *crcstat; - unsigned short *z1, *z2, oldz2, newz2; +static void hfc_dch_rx(struct hfc_card *hfctmp){ + struct dch *chtmp=&hfctmp->dch; + u16 size; hfctmp->ztdev->chans[2].bytes2receive=0; - hfctmp->ztdev->chans[2].eofrx = 0; - - /* put the received data into the DAHDI buffer - we'll call dahdi_receive() later when the timer fires. */ - f1 = (char *)(hfctmp->fifos + hfc_FIFO_DRX_F1); - f2 = (char *)(hfctmp->fifos + hfc_FIFO_DRX_F2); - - if (*f1 == *f2) return; /* nothing received, strange eh? */ - - z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z1 + (*f2 * 4)); - z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4)); - - /* calculate length of frame, including 2 bytes CRC and 1 byte STAT */ - count = *z1 - *z2; - - if (count < 0) { - count += hfc_D_FIFO_SIZE; /* ring buffer wrapped */ - } - count++; - framelen = count; - - crcstat = (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF + *z1); - - if ((framelen < 4) || (*crcstat != 0x0)) { - /* the frame is too short for a valid HDLC frame or the CRC is borked */ - printk(KERN_CRIT "zaphfc: empty HDLC frame or bad CRC received (framelen = %d, stat = %#x, card = %d).\n", framelen, *crcstat, hfctmp->cardno); - oldz2 = *z2; - *f2 = ((*f2 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); /* NEXT!!! */ - // recalculate z2, because Z2 is a function of F2 Z2(F2) and we INCed F2!!! - z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4)); - *z2 = (oldz2 + framelen) & hfc_ZMASK; - hfctmp->drecinframe = 0; - hfctmp->regs.int_drec--; - /* skip short or broken frames */ - hfctmp->ztdev->chans[2].bytes2receive = 0; - return; - } - - count -= 1; /* strip STAT */ - hfctmp->ztdev->chans[2].eofrx = 1; - - if (count + *z2 <= hfc_D_FIFO_SIZE) { - maxlen = count; - } else { - maxlen = hfc_D_FIFO_SIZE - *z2; + hfctmp->ztdev->chans[2].eofrx=0; + if(*chtmp->rx.f1.p==chtmp->rx.f2.v){ + hfctmp->regs.int_drec=0; + }else{ + size=((*(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DRX_Z1+chtmp->rx.f2.v*4)-chtmp->rx.f2.z2.v+hfc_D_FIFO_SIZE)&(hfc_D_FIFO_SIZE-1))+1; + if(size<4){ + printk(KERN_CRIT "zaphfc[%d]: empty HDLC frame received.\n",hfctmp->cardno); + }else{ + u16 x=min(size,(u16)(hfc_D_FIFO_SIZE-chtmp->rx.f2.z2.v)); + memcpy(hfctmp->drecbuf,hfctmp->fifos+hfc_FIFO_DRX_ZOFF+chtmp->rx.f2.z2.v,x); + memcpy(hfctmp->drecbuf+x,hfctmp->fifos+hfc_FIFO_DRX_ZOFF,size-x); + if(hfctmp->drecbuf[size-1]){ + printk(KERN_CRIT "zaphfc[%d]: received d channel frame with bad CRC.\n",hfctmp->cardno); + }else{ + hfctmp->ztdev->chans[2].bytes2receive=size-1; + hfctmp->ztdev->chans[2].eofrx=1; + } + } + chtmp->rx.f2.z2.v=(chtmp->rx.f2.z2.v+size)&(hfc_D_FIFO_SIZE-1); + chtmp->rx.f2.v=((chtmp->rx.f2.v+1)&hfc_MAX_DFRAMES)|(hfc_MAX_DFRAMES+1); } - - /* copy first part */ - memcpy(hfctmp->drecbuf, (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF + *z2), maxlen); - hfctmp->ztdev->chans[2].bytes2receive += maxlen; - - count -= maxlen; - if (count > 0) { - /* ring buffer wrapped, copy rest from start of d fifo */ - memcpy(hfctmp->drecbuf + maxlen, (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF), count); - hfctmp->ztdev->chans[2].bytes2receive += count; - } - - /* frame read */ - oldz2 = *z2; - newz2 = (oldz2 + framelen) & hfc_ZMASK; - *f2 = ((*f2 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); /* NEXT!!! */ - /* recalculate z2, because Z2 is a function of F2 Z2(F2) and we INCed F2!!! */ - z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4)); - *z2 = newz2; - hfctmp->drecinframe = 0; - hfctmp->regs.int_drec--; } -#ifndef RTAITIMING DAHDI_IRQ_HANDLER(hfc_interrupt) { struct hfc_card *hfctmp = dev_id; - unsigned long flags = 0; - unsigned char stat; -#else -static void hfc_service(struct hfc_card *hfctmp) { -#endif + struct hfc_card *hfctmp2; struct dahdi_hfc *zthfc; - unsigned char s1, s2, l1state; + unsigned char stat, s1, s2, l1state; + unsigned long flags = 0; + unsigned long flags2 = 0; int x; if (!hfctmp) { -#ifndef RTAITIMING - return IRQ_NONE; -#else - /* rtai */ - return; -#endif + return IRQ_NONE; } if (!hfctmp->pci_io) { printk(KERN_WARNING "%s: IO-mem disabled, cannot handle interrupt\n", __FUNCTION__); -#ifndef RTAITIMING return IRQ_NONE; -#else - /* rtai */ - return; -#endif } - /* we assume a few things in this irq handler: - - the hfc-pci will only generate "timer" irqs (proc/non-proc) - - we need to use every 8th IRQ (to generate 1khz timing) - OR - - if we use rtai for timing the hfc-pci will not generate ANY irq, - instead rtai will call this "fake" irq with a 1khz realtime timer. :) - - rtai will directly service the card, not like it used to by triggering - the linux irq - */ - -#ifndef RTAITIMING spin_lock_irqsave(&hfctmp->lock, flags); stat = hfc_inb(hfctmp, hfc_STATUS); - if ((stat & hfc_STATUS_ANYINT) == 0) { // maybe we are sharing the irq spin_unlock_irqrestore(&hfctmp->lock,flags); return IRQ_NONE; } -#endif s1 = hfc_inb(hfctmp, hfc_INT_S1); s2 = hfc_inb(hfctmp, hfc_INT_S2); @@ -611,18 +457,10 @@ } switch (l1state) { case 3: -#ifdef RTAITIMING - sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 ACTIVATED (G%d) [realtime]", hfctmp->cardno, l1state); -#else sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 ACTIVATED (G%d)", hfctmp->cardno, l1state); -#endif break; default: -#ifdef RTAITIMING - sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 DEACTIVATED (G%d) [realtime]", hfctmp->cardno, l1state); -#else sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 DEACTIVATED (G%d)", hfctmp->cardno, l1state); -#endif } if (l1state == 2) { hfc_outb(hfctmp, hfc_STATES, hfc_STATES_ACTIVATE | hfc_STATES_DO_ACTION | hfc_STATES_NT_G2_G3); @@ -636,18 +474,10 @@ } switch (l1state) { case 7: -#ifdef RTAITIMING - sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 ACTIVATED (F%d) [realtime]", hfctmp->cardno, l1state); -#else sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 ACTIVATED (F%d)", hfctmp->cardno, l1state); -#endif break; default: -#ifdef RTAITIMING - sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 DEACTIVATED (F%d) [realtime]", hfctmp->cardno, l1state); -#else sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 DEACTIVATED (F%d)", hfctmp->cardno, l1state); -#endif } if (l1state == 3) { hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE); @@ -657,7 +487,7 @@ } if (s1 & hfc_INTS_DREC) { // D chan RX (bit 5) - hfctmp->regs.int_drec++; + hfctmp->regs.int_drec = 1; // mr. zapata there is something for you! // printk(KERN_CRIT "d chan rx\n"); } @@ -678,14 +508,10 @@ // B1 chan TX (bit 0) } } -#ifdef RTAITIMING - /* fake an irq */ - s2 |= hfc_M2_PROC_TRANS; -#endif if (s2 != 0) { if (s2 & hfc_M2_PMESEL) { // kaboom irq (bit 7) - printk(KERN_CRIT "zaphfc: sync lost, pci performance too low. you might have some cpu throtteling enabled.\n"); + //printk(KERN_CRIT "zaphfc: sync lost, pci performance too low. you might have some cpu throtteling enabled.\n"); } if (s2 & hfc_M2_GCI_MON_REC) { // RxR monitor channel (bit 2) @@ -693,32 +519,31 @@ if (s2 & hfc_M2_GCI_I_CHG) { // GCI I-change (bit 1) } - if (s2 & hfc_M2_PROC_TRANS) { + if((s2&hfc_M2_PROC_TRANS)&&(hfctmp->cardno==timer_card)){ // processing/non-processing transition (bit 0) - hfctmp->ticks++; -#ifndef RTAITIMING - if (hfctmp->ticks > 7) { - // welcome to DAHDI timing :) -#endif - hfctmp->ticks = 0; - - if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) { + hfctmp2=hfctmp; + hfctmp=hfc_dev_list; + while(hfctmp){ + if(hfctmp->active){ + if(hfctmp!=hfctmp2)spin_lock_irqsave(&hfctmp->lock, flags2); + if(hfc_bch_check(hfctmp)){ + if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) { // clear dchan buffer + // memset(hfctmp->drecbuf, 0x0, sizeof(hfctmp->drecbuf)); + hfctmp->ztdev->chans[2].bytes2transmit = 0; hfctmp->ztdev->chans[2].maxbytes2transmit = hfc_D_FIFO_SIZE; dahdi_transmit(&(hfctmp->ztdev->span)); - hfc_btrans(hfctmp,1); - hfc_btrans(hfctmp,2); - hfc_dtrans(hfctmp); + hfc_bch_tx(hfctmp); + hfc_dch_tx(hfctmp); } - hfc_brec(hfctmp,1); - hfc_brec(hfctmp,2); - if (hfctmp->regs.int_drec > 0) { + hfc_bch_rx(hfctmp); + if (hfctmp->regs.int_drec) { // dchan data to read - hfc_drec(hfctmp); + hfc_dch_rx(hfctmp); if (hfctmp->ztdev->chans[2].bytes2receive > 0) { if (debug) { printk(KERN_CRIT "zaphfc: card %d RX [ ", hfctmp->cardno); @@ -743,17 +568,16 @@ if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) { dahdi_receive(&(hfctmp->ztdev->span)); } - -#ifndef RTAITIMING } -#endif + if(hfctmp!=hfctmp2)spin_unlock_irqrestore(&hfctmp->lock,flags2); + } + hfctmp=hfctmp->next; + } + hfctmp=hfctmp2; } - } -#ifndef RTAITIMING spin_unlock_irqrestore(&hfctmp->lock,flags); - return IRQ_RETVAL(1); -#endif + return IRQ_RETVAL(1); } @@ -802,22 +626,22 @@ } alreadyrunning = span->flags & DAHDI_FLAG_RUNNING; - if (!alreadyrunning) { - span->chans[2]->flags &= ~DAHDI_FLAG_HDLC; - span->chans[2]->flags |= DAHDI_FLAG_BRIDCHAN; - - span->flags |= DAHDI_FLAG_RUNNING; + if (alreadyrunning) return 0; - hfctmp->ticks = -2; - hfctmp->clicks = 0; - hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2; - hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en); - } else { - return 0; - } + span->chans[2]->flags &= ~DAHDI_FLAG_HDLC; + span->chans[2]->flags |= DAHDI_FLAG_BRIDCHAN; + + span->flags |= DAHDI_FLAG_RUNNING; + + hfctmp->ticks = -2; + hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2; + hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en); + + hfc_bch_init(hfctmp); // drivers, start engines! hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE); + hfctmp->active=1; return 0; } @@ -847,17 +671,9 @@ sprintf(zthfc->span.name, "ZTHFC%d", hfc_dev_count + 1); if (hfctmp->regs.nt_mode == 1) { -#ifdef RTAITIMING - sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] [realtime]", hfc_dev_count + 1); -#else sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT]", hfc_dev_count + 1); -#endif } else { -#ifdef RTAITIMING - sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] [realtime]", hfc_dev_count + 1); -#else sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE]", hfc_dev_count + 1); -#endif } zthfc->span.spanconfig = zthfc_spanconfig; @@ -897,32 +713,6 @@ return 0; } -#ifdef RTAITIMING -#define TICK_PERIOD 1000000 -#define TICK_PERIOD2 1000000000 -#define TASK_PRIORITY 1 -#define STACK_SIZE 10000 - -static RT_TASK rt_task; -static struct hfc_card *rtai_hfc_list[hfc_MAX_CARDS]; -static unsigned char rtai_hfc_counter = 0; - -static void rtai_register_hfc(struct hfc_card *hfctmp) { - rtai_hfc_list[rtai_hfc_counter++] = hfctmp; -} - -static void rtai_loop(int t) { - int i=0; - for (;;) { - for (i=0; i < rtai_hfc_counter; i++) { - if (rtai_hfc_list[i] != NULL) - hfc_service(rtai_hfc_list[i]); - } - rt_task_wait_period(); - } -} -#endif - int hfc_findCards(int pcivendor, int pcidevice, char *vendor_name, char *card_name) { struct pci_dev *tmp; struct hfc_card *hfctmp = NULL; @@ -938,9 +728,9 @@ } pci_set_master(tmp); - hfctmp = kmalloc(sizeof(struct hfc_card), GFP_KERNEL); + hfctmp = vmalloc(sizeof(struct hfc_card)); if (!hfctmp) { - printk(KERN_WARNING "zaphfc: unable to kmalloc!\n"); + printk(KERN_WARNING "zaphfc: unable to vmalloc!\n"); pci_disable_device(tmp); multi_hfc = NULL; return -ENOMEM; @@ -948,6 +738,7 @@ memset(hfctmp, 0x0, sizeof(struct hfc_card)); spin_lock_init(&hfctmp->lock); + hfctmp->active=0; hfctmp->pcidev = tmp; hfctmp->pcibus = tmp->bus->number; hfctmp->pcidevfn = tmp->devfn; @@ -961,49 +752,39 @@ hfctmp->pci_io = (char *) tmp->resource[1].start; if (!hfctmp->pci_io) { printk(KERN_WARNING "zaphfc: no iomem!\n"); - kfree(hfctmp); + vfree(hfctmp); pci_disable_device(tmp); multi_hfc = NULL; return -1; } - - hfctmp->fifomem = kmalloc(65536, GFP_KERNEL); - if (!hfctmp->fifomem) { - printk(KERN_WARNING "zaphfc: unable to kmalloc fifomem!\n"); - kfree(hfctmp); + + hfctmp->fifos=(void *)__get_free_pages(GFP_KERNEL,log2(hfc_FIFO_MEM_SIZE_PAGES)); + if (!hfctmp->fifos) { + printk(KERN_WARNING "zaphfc: unable to __get_free_pages fifomem!\n"); + vfree(hfctmp); pci_disable_device(tmp); multi_hfc = NULL; return -ENOMEM; } else { - memset(hfctmp->fifomem, 0x0, 65536); - hfctmp->fifos = (void *)(((ulong) hfctmp->fifomem) & ~0x7FFF) + 0x8000; pci_write_config_dword(hfctmp->pcidev, 0x80, (u_int) virt_to_bus(hfctmp->fifos)); hfctmp->pci_io = ioremap((ulong) hfctmp->pci_io, 256); } -#ifdef RTAITIMING - /* we need no stinking irq */ - hfctmp->irq = 0; -#else if (request_irq(hfctmp->irq, &hfc_interrupt, DAHDI_IRQ_SHARED, "zaphfc", hfctmp)) { printk(KERN_WARNING "zaphfc: unable to register irq\n"); - kfree(hfctmp->fifomem); - kfree(hfctmp); + free_pages((unsigned long)hfctmp->fifos,log2(hfc_FIFO_MEM_SIZE_PAGES)); + vfree(hfctmp); iounmap((void *) hfctmp->pci_io); pci_disable_device(tmp); multi_hfc = NULL; return -EIO; } -#endif -#ifdef RTAITIMING - rtai_register_hfc(hfctmp); -#endif printk(KERN_INFO - "zaphfc: %s %s configured at mem %lx fifo %lx(%#x) IRQ %d HZ %d\n", + "zaphfc: %s %s configured at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", vendor_name, card_name, - (unsigned long) hfctmp->pci_io, - (unsigned long) hfctmp->fifos, + (u_int) hfctmp->pci_io, + (u_int) hfctmp->fifos, (u_int) virt_to_bus(hfctmp->fifos), hfctmp->irq, HZ); pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, PCI_COMMAND_MEMORY); // enable memio @@ -1020,11 +801,21 @@ hfctmp->regs.nt_mode = 0; } - zthfc = kmalloc(sizeof(struct dahdi_hfc),GFP_KERNEL); + if(sync_slave&(1<regs.mst_mode=hfc_MST_MODE_SLAVE|hfc_MST_MODE_F0_LONG_DURATION; + hfctmp->regs.mst_emod=hfc_MST_EMOD_SLOW_CLOCK_ADJ; + }else{ + printk(KERN_INFO "zaphfc: Card %d configured for master mode\n",hfc_dev_count); + hfctmp->regs.mst_mode=hfc_MST_MODE_MASTER|hfc_MST_MODE_F0_LONG_DURATION; + hfctmp->regs.mst_emod=0; + } + + zthfc = vmalloc(sizeof(struct dahdi_hfc)); if (!zthfc) { - printk(KERN_CRIT "zaphfc: unable to kmalloc!\n"); + printk(KERN_CRIT "zaphfc: unable to vmalloc!\n"); hfc_shutdownCard(hfctmp); - kfree(hfctmp); + vfree(hfctmp); multi_hfc = NULL; return -ENOMEM; } @@ -1050,7 +841,6 @@ memset(hfctmp->btransbuf[1], 0x0, sizeof(hfctmp->btransbuf[1])); hfctmp->ztdev->chans[1].writechunk = hfctmp->btransbuf[1]; - hfc_registerCard(hfctmp); hfc_resetCard(hfctmp); tmp = pci_get_device(pcivendor, pcidevice, multi_hfc); @@ -1058,58 +848,42 @@ return 0; } - - int init_module(void) { int i = 0; -#ifdef RTAITIMING - RTIME tick_period; - for (i=0; i < hfc_MAX_CARDS; i++) { - rtai_hfc_list[i] = NULL; + if(jitterbuffer<1){ + printk(KERN_INFO "zaphfc: invalid jitterbuffer size specified: %d - changing to minimum of 1\n",jitterbuffer); + jitterbuffer=1; + }else if(jitterbuffer>500){ + printk(KERN_INFO "zaphfc: invalid jitterbuffer size specified: %d - changing to maximum of 500\n",jitterbuffer); + jitterbuffer=500; } - rt_set_periodic_mode(); -#endif - i = 0; + printk(KERN_INFO "zaphfc: jitterbuffer size: %d\n",jitterbuffer); while (id_list[i].vendor_id) { multi_hfc = NULL; hfc_findCards(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_name, id_list[i].card_name); i++; } -#ifdef RTAITIMING - for (i=0; i < hfc_MAX_CARDS; i++) { - if (rtai_hfc_list[i]) { - printk(KERN_INFO - "zaphfc: configured %d at mem %#x fifo %#x(%#x) for realtime servicing\n", - rtai_hfc_list[i]->cardno, - (u_int) rtai_hfc_list[i]->pci_io, - (u_int) rtai_hfc_list[i]->fifos, - (u_int) virt_to_bus(rtai_hfc_list[i]->fifos)); - - } - } - rt_task_init(&rt_task, rtai_loop, 1, STACK_SIZE, TASK_PRIORITY, 0, 0); - tick_period = start_rt_timer(nano2count(TICK_PERIOD)); - rt_task_make_periodic(&rt_task, rt_get_time() + tick_period, tick_period); -#endif printk(KERN_INFO "zaphfc: %d hfc-pci card(s) in this box.\n", hfc_dev_count); return 0; } void cleanup_module(void) { struct hfc_card *tmpcard; -#ifdef RTAITIMING - stop_rt_timer(); - rt_task_delete(&rt_task); -#endif + printk(KERN_INFO "zaphfc: stop\n"); // spin_lock(®isterlock); + tmpcard=hfc_dev_list; + while(tmpcard){ + hfc_shutdownCard1(tmpcard); + tmpcard=tmpcard->next; + } while (hfc_dev_list != NULL) { if (hfc_dev_list == NULL) break; - hfc_shutdownCard(hfc_dev_list); + hfc_shutdownCard2(hfc_dev_list); tmpcard = hfc_dev_list; hfc_dev_list = hfc_dev_list->next; if (tmpcard != NULL) { - kfree(tmpcard); + vfree(tmpcard); tmpcard = NULL; printk(KERN_INFO "zaphfc: freed one card.\n"); } @@ -1119,8 +893,11 @@ #endif -module_param(modes, int, 0600); +module_param(modes, int, 0400); module_param(debug, int, 0600); +module_param(sync_slave, int, 0400); +module_param(timer_card, int, 0400); +module_param(jitterbuffer, int, 0400); MODULE_DESCRIPTION("HFC-S PCI A Zaptel Driver"); MODULE_AUTHOR("Klaus-Peter Junghanns ");