diff options
Diffstat (limited to 'drivers/isdn/hardware')
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfc_multi.h | 3 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfc_pci.h | 1 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfcmulti.c | 45 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfcpci.c | 41 |
4 files changed, 78 insertions, 12 deletions
diff --git a/drivers/isdn/hardware/mISDN/hfc_multi.h b/drivers/isdn/hardware/mISDN/hfc_multi.h index 6d74951a1797..4aa6a8b41f50 100644 --- a/drivers/isdn/hardware/mISDN/hfc_multi.h +++ b/drivers/isdn/hardware/mISDN/hfc_multi.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #define DEBUG_HFCMULTI_MODE 0x00100000 | 9 | #define DEBUG_HFCMULTI_MODE 0x00100000 |
10 | #define DEBUG_HFCMULTI_MSG 0x00200000 | 10 | #define DEBUG_HFCMULTI_MSG 0x00200000 |
11 | #define DEBUG_HFCMULTI_STATE 0x00400000 | 11 | #define DEBUG_HFCMULTI_STATE 0x00400000 |
12 | #define DEBUG_HFCMULTI_FILL 0x00800000 | ||
12 | #define DEBUG_HFCMULTI_SYNC 0x01000000 | 13 | #define DEBUG_HFCMULTI_SYNC 0x01000000 |
13 | #define DEBUG_HFCMULTI_DTMF 0x02000000 | 14 | #define DEBUG_HFCMULTI_DTMF 0x02000000 |
14 | #define DEBUG_HFCMULTI_LOCK 0x80000000 | 15 | #define DEBUG_HFCMULTI_LOCK 0x80000000 |
@@ -166,6 +167,8 @@ struct hfc_multi { | |||
166 | 167 | ||
167 | u_long chip; /* chip configuration */ | 168 | u_long chip; /* chip configuration */ |
168 | int masterclk; /* port that provides master clock -1=off */ | 169 | int masterclk; /* port that provides master clock -1=off */ |
170 | unsigned char silence;/* silence byte */ | ||
171 | unsigned char silence_data[128];/* silence block */ | ||
169 | int dtmf; /* flag that dtmf is currently in process */ | 172 | int dtmf; /* flag that dtmf is currently in process */ |
170 | int Flen; /* F-buffer size */ | 173 | int Flen; /* F-buffer size */ |
171 | int Zlen; /* Z-buffer size (must be int for calculation)*/ | 174 | int Zlen; /* Z-buffer size (must be int for calculation)*/ |
diff --git a/drivers/isdn/hardware/mISDN/hfc_pci.h b/drivers/isdn/hardware/mISDN/hfc_pci.h index 5783d22a18fe..fd9241ab1802 100644 --- a/drivers/isdn/hardware/mISDN/hfc_pci.h +++ b/drivers/isdn/hardware/mISDN/hfc_pci.h | |||
@@ -27,6 +27,7 @@ | |||
27 | */ | 27 | */ |
28 | #define HFCPCI_BTRANS_THRESHOLD 128 | 28 | #define HFCPCI_BTRANS_THRESHOLD 128 |
29 | #define HFCPCI_BTRANS_MAX 256 | 29 | #define HFCPCI_BTRANS_MAX 256 |
30 | #define HFCPCI_FILLEMPTY 64 | ||
30 | #define HFCPCI_BTRANS_THRESMASK 0x00 | 31 | #define HFCPCI_BTRANS_THRESMASK 0x00 |
31 | 32 | ||
32 | /* defines for PCI config */ | 33 | /* defines for PCI config */ |
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index ff5ec3cbeb77..3fc2e9d95341 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c | |||
@@ -180,7 +180,6 @@ static int nt_t1_count[] = { 3840, 1920, 960, 480, 240, 120, 60, 30 }; | |||
180 | #define CLKDEL_TE 0x0f /* CLKDEL in TE mode */ | 180 | #define CLKDEL_TE 0x0f /* CLKDEL in TE mode */ |
181 | #define CLKDEL_NT 0x6c /* CLKDEL in NT mode | 181 | #define CLKDEL_NT 0x6c /* CLKDEL in NT mode |
182 | (0x60 MUST be included!) */ | 182 | (0x60 MUST be included!) */ |
183 | static u_char silence = 0xff; /* silence by LAW */ | ||
184 | 183 | ||
185 | #define DIP_4S 0x1 /* DIP Switches for Beronet 1S/2S/4S cards */ | 184 | #define DIP_4S 0x1 /* DIP Switches for Beronet 1S/2S/4S cards */ |
186 | #define DIP_8S 0x2 /* DIP Switches for Beronet 8S+ cards */ | 185 | #define DIP_8S 0x2 /* DIP Switches for Beronet 8S+ cards */ |
@@ -1975,6 +1974,17 @@ next_frame: | |||
1975 | return; /* no data */ | 1974 | return; /* no data */ |
1976 | } | 1975 | } |
1977 | 1976 | ||
1977 | /* "fill fifo if empty" feature */ | ||
1978 | if (bch && test_bit(FLG_FILLEMPTY, &bch->Flags) | ||
1979 | && !test_bit(FLG_HDLC, &bch->Flags) && z2 == z1) { | ||
1980 | if (debug & DEBUG_HFCMULTI_FILL) | ||
1981 | printk(KERN_DEBUG "%s: buffer empty, so we have " | ||
1982 | "underrun\n", __func__); | ||
1983 | /* fill buffer, to prevent future underrun */ | ||
1984 | hc->write_fifo(hc, hc->silence_data, poll >> 1); | ||
1985 | Zspace -= (poll >> 1); | ||
1986 | } | ||
1987 | |||
1978 | /* if audio data and connected slot */ | 1988 | /* if audio data and connected slot */ |
1979 | if (bch && (!test_bit(FLG_HDLC, &bch->Flags)) && (!*txpending) | 1989 | if (bch && (!test_bit(FLG_HDLC, &bch->Flags)) && (!*txpending) |
1980 | && slot_tx >= 0) { | 1990 | && slot_tx >= 0) { |
@@ -2011,7 +2021,6 @@ next_frame: | |||
2011 | __func__, hc->id + 1, ch, Zspace, z1, z2, ii-i, len-i, | 2021 | __func__, hc->id + 1, ch, Zspace, z1, z2, ii-i, len-i, |
2012 | temp ? "HDLC":"TRANS"); | 2022 | temp ? "HDLC":"TRANS"); |
2013 | 2023 | ||
2014 | |||
2015 | /* Have to prep the audio data */ | 2024 | /* Have to prep the audio data */ |
2016 | hc->write_fifo(hc, d, ii - i); | 2025 | hc->write_fifo(hc, d, ii - i); |
2017 | *idxp = ii; | 2026 | *idxp = ii; |
@@ -2050,7 +2059,7 @@ next_frame: | |||
2050 | * no more data at all. this prevents sending an undefined value. | 2059 | * no more data at all. this prevents sending an undefined value. |
2051 | */ | 2060 | */ |
2052 | if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags)) | 2061 | if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags)) |
2053 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence); | 2062 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence); |
2054 | } | 2063 | } |
2055 | 2064 | ||
2056 | 2065 | ||
@@ -2932,7 +2941,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, | |||
2932 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); | 2941 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); |
2933 | HFC_wait(hc); | 2942 | HFC_wait(hc); |
2934 | /* tx silence */ | 2943 | /* tx silence */ |
2935 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence); | 2944 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence); |
2936 | HFC_outb(hc, R_SLOT, (((ch / 4) * 8) + | 2945 | HFC_outb(hc, R_SLOT, (((ch / 4) * 8) + |
2937 | ((ch % 4) * 4)) << 1); | 2946 | ((ch % 4) * 4)) << 1); |
2938 | HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1)); | 2947 | HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1)); |
@@ -2947,7 +2956,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, | |||
2947 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); | 2956 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); |
2948 | HFC_wait(hc); | 2957 | HFC_wait(hc); |
2949 | /* tx silence */ | 2958 | /* tx silence */ |
2950 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence); | 2959 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence); |
2951 | /* enable RX fifo */ | 2960 | /* enable RX fifo */ |
2952 | HFC_outb(hc, R_FIFO, (ch<<1)|1); | 2961 | HFC_outb(hc, R_FIFO, (ch<<1)|1); |
2953 | HFC_wait(hc); | 2962 | HFC_wait(hc); |
@@ -3439,7 +3448,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) | |||
3439 | switch (cq->op) { | 3448 | switch (cq->op) { |
3440 | case MISDN_CTRL_GETOP: | 3449 | case MISDN_CTRL_GETOP: |
3441 | cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP | 3450 | cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP |
3442 | | MISDN_CTRL_RX_OFF; | 3451 | | MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY; |
3443 | break; | 3452 | break; |
3444 | case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */ | 3453 | case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */ |
3445 | hc->chan[bch->slot].rx_off = !!cq->p1; | 3454 | hc->chan[bch->slot].rx_off = !!cq->p1; |
@@ -3454,6 +3463,12 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) | |||
3454 | printk(KERN_DEBUG "%s: RX_OFF request (nr=%d off=%d)\n", | 3463 | printk(KERN_DEBUG "%s: RX_OFF request (nr=%d off=%d)\n", |
3455 | __func__, bch->nr, hc->chan[bch->slot].rx_off); | 3464 | __func__, bch->nr, hc->chan[bch->slot].rx_off); |
3456 | break; | 3465 | break; |
3466 | case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */ | ||
3467 | test_and_set_bit(FLG_FILLEMPTY, &bch->Flags); | ||
3468 | if (debug & DEBUG_HFCMULTI_MSG) | ||
3469 | printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d " | ||
3470 | "off=%d)\n", __func__, bch->nr, !!cq->p1); | ||
3471 | break; | ||
3457 | case MISDN_CTRL_HW_FEATURES: /* fill features structure */ | 3472 | case MISDN_CTRL_HW_FEATURES: /* fill features structure */ |
3458 | if (debug & DEBUG_HFCMULTI_MSG) | 3473 | if (debug & DEBUG_HFCMULTI_MSG) |
3459 | printk(KERN_DEBUG "%s: HW_FEATURE request\n", | 3474 | printk(KERN_DEBUG "%s: HW_FEATURE request\n", |
@@ -3970,6 +3985,7 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch, | |||
3970 | } | 3985 | } |
3971 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) | 3986 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) |
3972 | return -EBUSY; /* b-channel can be only open once */ | 3987 | return -EBUSY; /* b-channel can be only open once */ |
3988 | test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); | ||
3973 | bch->ch.protocol = rq->protocol; | 3989 | bch->ch.protocol = rq->protocol; |
3974 | hc->chan[ch].rx_off = 0; | 3990 | hc->chan[ch].rx_off = 0; |
3975 | rq->ch = &bch->ch; | 3991 | rq->ch = &bch->ch; |
@@ -4806,6 +4822,7 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4806 | struct hfc_multi *hc; | 4822 | struct hfc_multi *hc; |
4807 | u_long flags; | 4823 | u_long flags; |
4808 | u_char dips = 0, pmj = 0; /* dip settings, port mode Jumpers */ | 4824 | u_char dips = 0, pmj = 0; /* dip settings, port mode Jumpers */ |
4825 | int i; | ||
4809 | 4826 | ||
4810 | if (HFC_cnt >= MAX_CARDS) { | 4827 | if (HFC_cnt >= MAX_CARDS) { |
4811 | printk(KERN_ERR "too many cards (max=%d).\n", | 4828 | printk(KERN_ERR "too many cards (max=%d).\n", |
@@ -4839,11 +4856,11 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4839 | hc->id = HFC_cnt; | 4856 | hc->id = HFC_cnt; |
4840 | hc->pcm = pcm[HFC_cnt]; | 4857 | hc->pcm = pcm[HFC_cnt]; |
4841 | hc->io_mode = iomode[HFC_cnt]; | 4858 | hc->io_mode = iomode[HFC_cnt]; |
4842 | if (dslot[HFC_cnt] < 0) { | 4859 | if (dslot[HFC_cnt] < 0 && hc->type == 1) { |
4843 | hc->dslot = 0; | 4860 | hc->dslot = 0; |
4844 | printk(KERN_INFO "HFC-E1 card has disabled D-channel, but " | 4861 | printk(KERN_INFO "HFC-E1 card has disabled D-channel, but " |
4845 | "31 B-channels\n"); | 4862 | "31 B-channels\n"); |
4846 | } if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32) { | 4863 | } if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32 && hc->type == 1) { |
4847 | hc->dslot = dslot[HFC_cnt]; | 4864 | hc->dslot = dslot[HFC_cnt]; |
4848 | printk(KERN_INFO "HFC-E1 card has alternating D-channel on " | 4865 | printk(KERN_INFO "HFC-E1 card has alternating D-channel on " |
4849 | "time slot %d\n", dslot[HFC_cnt]); | 4866 | "time slot %d\n", dslot[HFC_cnt]); |
@@ -4854,9 +4871,17 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4854 | hc->masterclk = -1; | 4871 | hc->masterclk = -1; |
4855 | if (type[HFC_cnt] & 0x100) { | 4872 | if (type[HFC_cnt] & 0x100) { |
4856 | test_and_set_bit(HFC_CHIP_ULAW, &hc->chip); | 4873 | test_and_set_bit(HFC_CHIP_ULAW, &hc->chip); |
4857 | silence = 0xff; /* ulaw silence */ | 4874 | hc->silence = 0xff; /* ulaw silence */ |
4858 | } else | 4875 | } else |
4859 | silence = 0x2a; /* alaw silence */ | 4876 | hc->silence = 0x2a; /* alaw silence */ |
4877 | if ((poll >> 1) > sizeof(hc->silence_data)) { | ||
4878 | printk(KERN_ERR "HFCMULTI error: silence_data too small, " | ||
4879 | "please fix\n"); | ||
4880 | return -EINVAL; | ||
4881 | } | ||
4882 | for (i = 0; i < (poll >> 1); i++) | ||
4883 | hc->silence_data[i] = hc->silence; | ||
4884 | |||
4860 | if (!(type[HFC_cnt] & 0x200)) | 4885 | if (!(type[HFC_cnt] & 0x200)) |
4861 | test_and_set_bit(HFC_CHIP_DTMF, &hc->chip); | 4886 | test_and_set_bit(HFC_CHIP_DTMF, &hc->chip); |
4862 | 4887 | ||
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index cd8302af40eb..80c356e5dbe1 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c | |||
@@ -751,6 +751,36 @@ hfcpci_fill_fifo(struct bchannel *bch) | |||
751 | /* fcnt contains available bytes in fifo */ | 751 | /* fcnt contains available bytes in fifo */ |
752 | fcnt = B_FIFO_SIZE - fcnt; | 752 | fcnt = B_FIFO_SIZE - fcnt; |
753 | /* remaining bytes to send (bytes in fifo) */ | 753 | /* remaining bytes to send (bytes in fifo) */ |
754 | |||
755 | /* "fill fifo if empty" feature */ | ||
756 | if (test_bit(FLG_FILLEMPTY, &bch->Flags) && !fcnt) { | ||
757 | /* printk(KERN_DEBUG "%s: buffer empty, so we have " | ||
758 | "underrun\n", __func__); */ | ||
759 | /* fill buffer, to prevent future underrun */ | ||
760 | count = HFCPCI_FILLEMPTY; | ||
761 | new_z1 = le16_to_cpu(*z1t) + count; | ||
762 | /* new buffer Position */ | ||
763 | if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) | ||
764 | new_z1 -= B_FIFO_SIZE; /* buffer wrap */ | ||
765 | dst = bdata + (le16_to_cpu(*z1t) - B_SUB_VAL); | ||
766 | maxlen = (B_FIFO_SIZE + B_SUB_VAL) - le16_to_cpu(*z1t); | ||
767 | /* end of fifo */ | ||
768 | if (bch->debug & DEBUG_HW_BFIFO) | ||
769 | printk(KERN_DEBUG "hfcpci_FFt fillempty " | ||
770 | "fcnt(%d) maxl(%d) nz1(%x) dst(%p)\n", | ||
771 | fcnt, maxlen, new_z1, dst); | ||
772 | fcnt += count; | ||
773 | if (maxlen > count) | ||
774 | maxlen = count; /* limit size */ | ||
775 | memset(dst, 0x2a, maxlen); /* first copy */ | ||
776 | count -= maxlen; /* remaining bytes */ | ||
777 | if (count) { | ||
778 | dst = bdata; /* start of buffer */ | ||
779 | memset(dst, 0x2a, count); | ||
780 | } | ||
781 | *z1t = cpu_to_le16(new_z1); /* now send data */ | ||
782 | } | ||
783 | |||
754 | next_t_frame: | 784 | next_t_frame: |
755 | count = bch->tx_skb->len - bch->tx_idx; | 785 | count = bch->tx_skb->len - bch->tx_idx; |
756 | /* maximum fill shall be HFCPCI_BTRANS_MAX */ | 786 | /* maximum fill shall be HFCPCI_BTRANS_MAX */ |
@@ -1481,11 +1511,17 @@ deactivate_bchannel(struct bchannel *bch) | |||
1481 | static int | 1511 | static int |
1482 | channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) | 1512 | channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) |
1483 | { | 1513 | { |
1484 | int ret = 0; | 1514 | int ret = 0; |
1485 | 1515 | ||
1486 | switch (cq->op) { | 1516 | switch (cq->op) { |
1487 | case MISDN_CTRL_GETOP: | 1517 | case MISDN_CTRL_GETOP: |
1488 | cq->op = 0; | 1518 | cq->op = MISDN_CTRL_FILL_EMPTY; |
1519 | break; | ||
1520 | case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */ | ||
1521 | test_and_set_bit(FLG_FILLEMPTY, &bch->Flags); | ||
1522 | if (debug & DEBUG_HW_OPEN) | ||
1523 | printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d " | ||
1524 | "off=%d)\n", __func__, bch->nr, !!cq->p1); | ||
1489 | break; | 1525 | break; |
1490 | default: | 1526 | default: |
1491 | printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op); | 1527 | printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op); |
@@ -1903,6 +1939,7 @@ open_bchannel(struct hfc_pci *hc, struct channel_req *rq) | |||
1903 | bch = &hc->bch[rq->adr.channel - 1]; | 1939 | bch = &hc->bch[rq->adr.channel - 1]; |
1904 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) | 1940 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) |
1905 | return -EBUSY; /* b-channel can be only open once */ | 1941 | return -EBUSY; /* b-channel can be only open once */ |
1942 | test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); | ||
1906 | bch->ch.protocol = rq->protocol; | 1943 | bch->ch.protocol = rq->protocol; |
1907 | rq->ch = &bch->ch; /* TODO: E-channel */ | 1944 | rq->ch = &bch->ch; /* TODO: E-channel */ |
1908 | if (!try_module_get(THIS_MODULE)) | 1945 | if (!try_module_get(THIS_MODULE)) |