diff options
Diffstat (limited to 'drivers/isdn/hardware/mISDN/hfcmulti.c')
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfcmulti.c | 206 |
1 files changed, 101 insertions, 105 deletions
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index c63e2f49da8a..97f4708b3879 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c | |||
@@ -133,6 +133,12 @@ | |||
133 | * Give the value of the clock control register (A_ST_CLK_DLY) | 133 | * Give the value of the clock control register (A_ST_CLK_DLY) |
134 | * of the S/T interfaces in TE mode. | 134 | * of the S/T interfaces in TE mode. |
135 | * This register is needed for the TBR3 certification, so don't change it. | 135 | * This register is needed for the TBR3 certification, so don't change it. |
136 | * | ||
137 | * clock: | ||
138 | * NOTE: only one clock value must be given once | ||
139 | * Selects interface with clock source for mISDN and applications. | ||
140 | * Set to card number starting with 1. Set to -1 to disable. | ||
141 | * By default, the first card is used as clock source. | ||
136 | */ | 142 | */ |
137 | 143 | ||
138 | /* | 144 | /* |
@@ -140,7 +146,7 @@ | |||
140 | * #define HFC_REGISTER_DEBUG | 146 | * #define HFC_REGISTER_DEBUG |
141 | */ | 147 | */ |
142 | 148 | ||
143 | static const char *hfcmulti_revision = "2.02"; | 149 | #define HFC_MULTI_VERSION "2.03" |
144 | 150 | ||
145 | #include <linux/module.h> | 151 | #include <linux/module.h> |
146 | #include <linux/pci.h> | 152 | #include <linux/pci.h> |
@@ -165,10 +171,6 @@ static LIST_HEAD(HFClist); | |||
165 | static spinlock_t HFClock; /* global hfc list lock */ | 171 | static spinlock_t HFClock; /* global hfc list lock */ |
166 | 172 | ||
167 | static void ph_state_change(struct dchannel *); | 173 | static void ph_state_change(struct dchannel *); |
168 | static void (*hfc_interrupt)(void); | ||
169 | static void (*register_interrupt)(void); | ||
170 | static int (*unregister_interrupt)(void); | ||
171 | static int interrupt_registered; | ||
172 | 174 | ||
173 | static struct hfc_multi *syncmaster; | 175 | static struct hfc_multi *syncmaster; |
174 | static int plxsd_master; /* if we have a master card (yet) */ | 176 | static int plxsd_master; /* if we have a master card (yet) */ |
@@ -184,7 +186,6 @@ static int nt_t1_count[] = { 3840, 1920, 960, 480, 240, 120, 60, 30 }; | |||
184 | #define CLKDEL_TE 0x0f /* CLKDEL in TE mode */ | 186 | #define CLKDEL_TE 0x0f /* CLKDEL in TE mode */ |
185 | #define CLKDEL_NT 0x6c /* CLKDEL in NT mode | 187 | #define CLKDEL_NT 0x6c /* CLKDEL in NT mode |
186 | (0x60 MUST be included!) */ | 188 | (0x60 MUST be included!) */ |
187 | static u_char silence = 0xff; /* silence by LAW */ | ||
188 | 189 | ||
189 | #define DIP_4S 0x1 /* DIP Switches for Beronet 1S/2S/4S cards */ | 190 | #define DIP_4S 0x1 /* DIP Switches for Beronet 1S/2S/4S cards */ |
190 | #define DIP_8S 0x2 /* DIP Switches for Beronet 8S+ cards */ | 191 | #define DIP_8S 0x2 /* DIP Switches for Beronet 8S+ cards */ |
@@ -195,12 +196,13 @@ static u_char silence = 0xff; /* silence by LAW */ | |||
195 | */ | 196 | */ |
196 | 197 | ||
197 | static uint type[MAX_CARDS]; | 198 | static uint type[MAX_CARDS]; |
198 | static uint pcm[MAX_CARDS]; | 199 | static int pcm[MAX_CARDS]; |
199 | static uint dslot[MAX_CARDS]; | 200 | static int dslot[MAX_CARDS]; |
200 | static uint iomode[MAX_CARDS]; | 201 | static uint iomode[MAX_CARDS]; |
201 | static uint port[MAX_PORTS]; | 202 | static uint port[MAX_PORTS]; |
202 | static uint debug; | 203 | static uint debug; |
203 | static uint poll; | 204 | static uint poll; |
205 | static int clock; | ||
204 | static uint timer; | 206 | static uint timer; |
205 | static uint clockdelay_te = CLKDEL_TE; | 207 | static uint clockdelay_te = CLKDEL_TE; |
206 | static uint clockdelay_nt = CLKDEL_NT; | 208 | static uint clockdelay_nt = CLKDEL_NT; |
@@ -209,14 +211,16 @@ static int HFC_cnt, Port_cnt, PCM_cnt = 99; | |||
209 | 211 | ||
210 | MODULE_AUTHOR("Andreas Eversberg"); | 212 | MODULE_AUTHOR("Andreas Eversberg"); |
211 | MODULE_LICENSE("GPL"); | 213 | MODULE_LICENSE("GPL"); |
214 | MODULE_VERSION(HFC_MULTI_VERSION); | ||
212 | module_param(debug, uint, S_IRUGO | S_IWUSR); | 215 | module_param(debug, uint, S_IRUGO | S_IWUSR); |
213 | module_param(poll, uint, S_IRUGO | S_IWUSR); | 216 | module_param(poll, uint, S_IRUGO | S_IWUSR); |
217 | module_param(clock, int, S_IRUGO | S_IWUSR); | ||
214 | module_param(timer, uint, S_IRUGO | S_IWUSR); | 218 | module_param(timer, uint, S_IRUGO | S_IWUSR); |
215 | module_param(clockdelay_te, uint, S_IRUGO | S_IWUSR); | 219 | module_param(clockdelay_te, uint, S_IRUGO | S_IWUSR); |
216 | module_param(clockdelay_nt, uint, S_IRUGO | S_IWUSR); | 220 | module_param(clockdelay_nt, uint, S_IRUGO | S_IWUSR); |
217 | module_param_array(type, uint, NULL, S_IRUGO | S_IWUSR); | 221 | module_param_array(type, uint, NULL, S_IRUGO | S_IWUSR); |
218 | module_param_array(pcm, uint, NULL, S_IRUGO | S_IWUSR); | 222 | module_param_array(pcm, int, NULL, S_IRUGO | S_IWUSR); |
219 | module_param_array(dslot, uint, NULL, S_IRUGO | S_IWUSR); | 223 | module_param_array(dslot, int, NULL, S_IRUGO | S_IWUSR); |
220 | module_param_array(iomode, uint, NULL, S_IRUGO | S_IWUSR); | 224 | module_param_array(iomode, uint, NULL, S_IRUGO | S_IWUSR); |
221 | module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR); | 225 | module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR); |
222 | 226 | ||
@@ -1419,19 +1423,6 @@ controller_fail: | |||
1419 | HFC_outb(hc, R_TI_WD, poll_timer); | 1423 | HFC_outb(hc, R_TI_WD, poll_timer); |
1420 | hc->hw.r_irqmsk_misc |= V_TI_IRQMSK; | 1424 | hc->hw.r_irqmsk_misc |= V_TI_IRQMSK; |
1421 | 1425 | ||
1422 | /* | ||
1423 | * set up 125us interrupt, only if function pointer is available | ||
1424 | * and module parameter timer is set | ||
1425 | */ | ||
1426 | if (timer && hfc_interrupt && register_interrupt) { | ||
1427 | /* only one chip should use this interrupt */ | ||
1428 | timer = 0; | ||
1429 | interrupt_registered = 1; | ||
1430 | hc->hw.r_irqmsk_misc |= V_PROC_IRQMSK; | ||
1431 | /* deactivate other interrupts in ztdummy */ | ||
1432 | register_interrupt(); | ||
1433 | } | ||
1434 | |||
1435 | /* set E1 state machine IRQ */ | 1426 | /* set E1 state machine IRQ */ |
1436 | if (hc->type == 1) | 1427 | if (hc->type == 1) |
1437 | hc->hw.r_irqmsk_misc |= V_STA_IRQMSK; | 1428 | hc->hw.r_irqmsk_misc |= V_STA_IRQMSK; |
@@ -1991,6 +1982,17 @@ next_frame: | |||
1991 | return; /* no data */ | 1982 | return; /* no data */ |
1992 | } | 1983 | } |
1993 | 1984 | ||
1985 | /* "fill fifo if empty" feature */ | ||
1986 | if (bch && test_bit(FLG_FILLEMPTY, &bch->Flags) | ||
1987 | && !test_bit(FLG_HDLC, &bch->Flags) && z2 == z1) { | ||
1988 | if (debug & DEBUG_HFCMULTI_FILL) | ||
1989 | printk(KERN_DEBUG "%s: buffer empty, so we have " | ||
1990 | "underrun\n", __func__); | ||
1991 | /* fill buffer, to prevent future underrun */ | ||
1992 | hc->write_fifo(hc, hc->silence_data, poll >> 1); | ||
1993 | Zspace -= (poll >> 1); | ||
1994 | } | ||
1995 | |||
1994 | /* if audio data and connected slot */ | 1996 | /* if audio data and connected slot */ |
1995 | if (bch && (!test_bit(FLG_HDLC, &bch->Flags)) && (!*txpending) | 1997 | if (bch && (!test_bit(FLG_HDLC, &bch->Flags)) && (!*txpending) |
1996 | && slot_tx >= 0) { | 1998 | && slot_tx >= 0) { |
@@ -2027,7 +2029,6 @@ next_frame: | |||
2027 | __func__, hc->id + 1, ch, Zspace, z1, z2, ii-i, len-i, | 2029 | __func__, hc->id + 1, ch, Zspace, z1, z2, ii-i, len-i, |
2028 | temp ? "HDLC":"TRANS"); | 2030 | temp ? "HDLC":"TRANS"); |
2029 | 2031 | ||
2030 | |||
2031 | /* Have to prep the audio data */ | 2032 | /* Have to prep the audio data */ |
2032 | hc->write_fifo(hc, d, ii - i); | 2033 | hc->write_fifo(hc, d, ii - i); |
2033 | *idxp = ii; | 2034 | *idxp = ii; |
@@ -2066,7 +2067,7 @@ next_frame: | |||
2066 | * no more data at all. this prevents sending an undefined value. | 2067 | * no more data at all. this prevents sending an undefined value. |
2067 | */ | 2068 | */ |
2068 | if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags)) | 2069 | if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags)) |
2069 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence); | 2070 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence); |
2070 | } | 2071 | } |
2071 | 2072 | ||
2072 | 2073 | ||
@@ -2583,7 +2584,6 @@ hfcmulti_interrupt(int intno, void *dev_id) | |||
2583 | static int iq1 = 0, iq2 = 0, iq3 = 0, iq4 = 0, | 2584 | static int iq1 = 0, iq2 = 0, iq3 = 0, iq4 = 0, |
2584 | iq5 = 0, iq6 = 0, iqcnt = 0; | 2585 | iq5 = 0, iq6 = 0, iqcnt = 0; |
2585 | #endif | 2586 | #endif |
2586 | static int count; | ||
2587 | struct hfc_multi *hc = dev_id; | 2587 | struct hfc_multi *hc = dev_id; |
2588 | struct dchannel *dch; | 2588 | struct dchannel *dch; |
2589 | u_char r_irq_statech, status, r_irq_misc, r_irq_oview; | 2589 | u_char r_irq_statech, status, r_irq_misc, r_irq_oview; |
@@ -2637,6 +2637,7 @@ hfcmulti_interrupt(int intno, void *dev_id) | |||
2637 | iqcnt = 0; | 2637 | iqcnt = 0; |
2638 | } | 2638 | } |
2639 | #endif | 2639 | #endif |
2640 | |||
2640 | if (!r_irq_statech && | 2641 | if (!r_irq_statech && |
2641 | !(status & (V_DTMF_STA | V_LOST_STA | V_EXT_IRQSTA | | 2642 | !(status & (V_DTMF_STA | V_LOST_STA | V_EXT_IRQSTA | |
2642 | V_MISC_IRQSTA | V_FR_IRQSTA))) { | 2643 | V_MISC_IRQSTA | V_FR_IRQSTA))) { |
@@ -2657,6 +2658,7 @@ hfcmulti_interrupt(int intno, void *dev_id) | |||
2657 | if (status & V_MISC_IRQSTA) { | 2658 | if (status & V_MISC_IRQSTA) { |
2658 | /* misc IRQ */ | 2659 | /* misc IRQ */ |
2659 | r_irq_misc = HFC_inb_nodebug(hc, R_IRQ_MISC); | 2660 | r_irq_misc = HFC_inb_nodebug(hc, R_IRQ_MISC); |
2661 | r_irq_misc &= hc->hw.r_irqmsk_misc; /* ignore disabled irqs */ | ||
2660 | if (r_irq_misc & V_STA_IRQ) { | 2662 | if (r_irq_misc & V_STA_IRQ) { |
2661 | if (hc->type == 1) { | 2663 | if (hc->type == 1) { |
2662 | /* state machine */ | 2664 | /* state machine */ |
@@ -2691,23 +2693,20 @@ hfcmulti_interrupt(int intno, void *dev_id) | |||
2691 | plxsd_checksync(hc, 0); | 2693 | plxsd_checksync(hc, 0); |
2692 | } | 2694 | } |
2693 | } | 2695 | } |
2694 | if (r_irq_misc & V_TI_IRQ) | 2696 | if (r_irq_misc & V_TI_IRQ) { |
2697 | if (hc->iclock_on) | ||
2698 | mISDN_clock_update(hc->iclock, poll, NULL); | ||
2695 | handle_timer_irq(hc); | 2699 | handle_timer_irq(hc); |
2700 | } | ||
2696 | 2701 | ||
2697 | if (r_irq_misc & V_DTMF_IRQ) { | 2702 | if (r_irq_misc & V_DTMF_IRQ) { |
2698 | /* -> DTMF IRQ */ | ||
2699 | hfcmulti_dtmf(hc); | 2703 | hfcmulti_dtmf(hc); |
2700 | } | 2704 | } |
2701 | /* TODO: REPLACE !!!! 125 us Interrupts are not acceptable */ | ||
2702 | if (r_irq_misc & V_IRQ_PROC) { | 2705 | if (r_irq_misc & V_IRQ_PROC) { |
2703 | /* IRQ every 125us */ | 2706 | static int irq_proc_cnt; |
2704 | count++; | 2707 | if (!irq_proc_cnt++) |
2705 | /* generate 1kHz signal */ | 2708 | printk(KERN_WARNING "%s: got V_IRQ_PROC -" |
2706 | if (count == 8) { | 2709 | " this should not happen\n", __func__); |
2707 | if (hfc_interrupt) | ||
2708 | hfc_interrupt(); | ||
2709 | count = 0; | ||
2710 | } | ||
2711 | } | 2710 | } |
2712 | 2711 | ||
2713 | } | 2712 | } |
@@ -2954,7 +2953,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, | |||
2954 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); | 2953 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); |
2955 | HFC_wait(hc); | 2954 | HFC_wait(hc); |
2956 | /* tx silence */ | 2955 | /* tx silence */ |
2957 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence); | 2956 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence); |
2958 | HFC_outb(hc, R_SLOT, (((ch / 4) * 8) + | 2957 | HFC_outb(hc, R_SLOT, (((ch / 4) * 8) + |
2959 | ((ch % 4) * 4)) << 1); | 2958 | ((ch % 4) * 4)) << 1); |
2960 | HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1)); | 2959 | HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1)); |
@@ -2969,7 +2968,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, | |||
2969 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); | 2968 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); |
2970 | HFC_wait(hc); | 2969 | HFC_wait(hc); |
2971 | /* tx silence */ | 2970 | /* tx silence */ |
2972 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence); | 2971 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence); |
2973 | /* enable RX fifo */ | 2972 | /* enable RX fifo */ |
2974 | HFC_outb(hc, R_FIFO, (ch<<1)|1); | 2973 | HFC_outb(hc, R_FIFO, (ch<<1)|1); |
2975 | HFC_wait(hc); | 2974 | HFC_wait(hc); |
@@ -3461,7 +3460,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) | |||
3461 | switch (cq->op) { | 3460 | switch (cq->op) { |
3462 | case MISDN_CTRL_GETOP: | 3461 | case MISDN_CTRL_GETOP: |
3463 | cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP | 3462 | cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP |
3464 | | MISDN_CTRL_RX_OFF; | 3463 | | MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY; |
3465 | break; | 3464 | break; |
3466 | case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */ | 3465 | case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */ |
3467 | hc->chan[bch->slot].rx_off = !!cq->p1; | 3466 | hc->chan[bch->slot].rx_off = !!cq->p1; |
@@ -3476,6 +3475,12 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) | |||
3476 | printk(KERN_DEBUG "%s: RX_OFF request (nr=%d off=%d)\n", | 3475 | printk(KERN_DEBUG "%s: RX_OFF request (nr=%d off=%d)\n", |
3477 | __func__, bch->nr, hc->chan[bch->slot].rx_off); | 3476 | __func__, bch->nr, hc->chan[bch->slot].rx_off); |
3478 | break; | 3477 | break; |
3478 | case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */ | ||
3479 | test_and_set_bit(FLG_FILLEMPTY, &bch->Flags); | ||
3480 | if (debug & DEBUG_HFCMULTI_MSG) | ||
3481 | printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d " | ||
3482 | "off=%d)\n", __func__, bch->nr, !!cq->p1); | ||
3483 | break; | ||
3479 | case MISDN_CTRL_HW_FEATURES: /* fill features structure */ | 3484 | case MISDN_CTRL_HW_FEATURES: /* fill features structure */ |
3480 | if (debug & DEBUG_HFCMULTI_MSG) | 3485 | if (debug & DEBUG_HFCMULTI_MSG) |
3481 | printk(KERN_DEBUG "%s: HW_FEATURE request\n", | 3486 | printk(KERN_DEBUG "%s: HW_FEATURE request\n", |
@@ -3992,6 +3997,7 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch, | |||
3992 | } | 3997 | } |
3993 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) | 3998 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) |
3994 | return -EBUSY; /* b-channel can be only open once */ | 3999 | return -EBUSY; /* b-channel can be only open once */ |
4000 | test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); | ||
3995 | bch->ch.protocol = rq->protocol; | 4001 | bch->ch.protocol = rq->protocol; |
3996 | hc->chan[ch].rx_off = 0; | 4002 | hc->chan[ch].rx_off = 0; |
3997 | rq->ch = &bch->ch; | 4003 | rq->ch = &bch->ch; |
@@ -4081,6 +4087,15 @@ hfcm_dctrl(struct mISDNchannel *ch, u_int cmd, void *arg) | |||
4081 | return err; | 4087 | return err; |
4082 | } | 4088 | } |
4083 | 4089 | ||
4090 | static int | ||
4091 | clockctl(void *priv, int enable) | ||
4092 | { | ||
4093 | struct hfc_multi *hc = priv; | ||
4094 | |||
4095 | hc->iclock_on = enable; | ||
4096 | return 0; | ||
4097 | } | ||
4098 | |||
4084 | /* | 4099 | /* |
4085 | * initialize the card | 4100 | * initialize the card |
4086 | */ | 4101 | */ |
@@ -4495,10 +4510,14 @@ release_card(struct hfc_multi *hc) | |||
4495 | printk(KERN_WARNING "%s: release card (%d) entered\n", | 4510 | printk(KERN_WARNING "%s: release card (%d) entered\n", |
4496 | __func__, hc->id); | 4511 | __func__, hc->id); |
4497 | 4512 | ||
4513 | /* unregister clock source */ | ||
4514 | if (hc->iclock) | ||
4515 | mISDN_unregister_clock(hc->iclock); | ||
4516 | |||
4517 | /* disable irq */ | ||
4498 | spin_lock_irqsave(&hc->lock, flags); | 4518 | spin_lock_irqsave(&hc->lock, flags); |
4499 | disable_hwirq(hc); | 4519 | disable_hwirq(hc); |
4500 | spin_unlock_irqrestore(&hc->lock, flags); | 4520 | spin_unlock_irqrestore(&hc->lock, flags); |
4501 | |||
4502 | udelay(1000); | 4521 | udelay(1000); |
4503 | 4522 | ||
4504 | /* dimm leds */ | 4523 | /* dimm leds */ |
@@ -4699,7 +4718,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m) | |||
4699 | } else | 4718 | } else |
4700 | hc->chan[hc->dslot].jitter = 2; /* default */ | 4719 | hc->chan[hc->dslot].jitter = 2; /* default */ |
4701 | snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1); | 4720 | snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1); |
4702 | ret = mISDN_register_device(&dch->dev, name); | 4721 | ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name); |
4703 | if (ret) | 4722 | if (ret) |
4704 | goto free_chan; | 4723 | goto free_chan; |
4705 | hc->created[0] = 1; | 4724 | hc->created[0] = 1; |
@@ -4807,9 +4826,9 @@ init_multi_port(struct hfc_multi *hc, int pt) | |||
4807 | test_and_set_bit(HFC_CFG_DIS_ECHANNEL, | 4826 | test_and_set_bit(HFC_CFG_DIS_ECHANNEL, |
4808 | &hc->chan[i + 2].cfg); | 4827 | &hc->chan[i + 2].cfg); |
4809 | } | 4828 | } |
4810 | snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d/%d", | 4829 | snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d-%d", |
4811 | hc->type, HFC_cnt + 1, pt + 1); | 4830 | hc->type, HFC_cnt + 1, pt + 1); |
4812 | ret = mISDN_register_device(&dch->dev, name); | 4831 | ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name); |
4813 | if (ret) | 4832 | if (ret) |
4814 | goto free_chan; | 4833 | goto free_chan; |
4815 | hc->created[pt] = 1; | 4834 | hc->created[pt] = 1; |
@@ -4828,6 +4847,7 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4828 | struct hfc_multi *hc; | 4847 | struct hfc_multi *hc; |
4829 | u_long flags; | 4848 | u_long flags; |
4830 | u_char dips = 0, pmj = 0; /* dip settings, port mode Jumpers */ | 4849 | u_char dips = 0, pmj = 0; /* dip settings, port mode Jumpers */ |
4850 | int i; | ||
4831 | 4851 | ||
4832 | if (HFC_cnt >= MAX_CARDS) { | 4852 | if (HFC_cnt >= MAX_CARDS) { |
4833 | printk(KERN_ERR "too many cards (max=%d).\n", | 4853 | printk(KERN_ERR "too many cards (max=%d).\n", |
@@ -4861,11 +4881,11 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4861 | hc->id = HFC_cnt; | 4881 | hc->id = HFC_cnt; |
4862 | hc->pcm = pcm[HFC_cnt]; | 4882 | hc->pcm = pcm[HFC_cnt]; |
4863 | hc->io_mode = iomode[HFC_cnt]; | 4883 | hc->io_mode = iomode[HFC_cnt]; |
4864 | if (dslot[HFC_cnt] < 0) { | 4884 | if (dslot[HFC_cnt] < 0 && hc->type == 1) { |
4865 | hc->dslot = 0; | 4885 | hc->dslot = 0; |
4866 | printk(KERN_INFO "HFC-E1 card has disabled D-channel, but " | 4886 | printk(KERN_INFO "HFC-E1 card has disabled D-channel, but " |
4867 | "31 B-channels\n"); | 4887 | "31 B-channels\n"); |
4868 | } if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32) { | 4888 | } if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32 && hc->type == 1) { |
4869 | hc->dslot = dslot[HFC_cnt]; | 4889 | hc->dslot = dslot[HFC_cnt]; |
4870 | printk(KERN_INFO "HFC-E1 card has alternating D-channel on " | 4890 | printk(KERN_INFO "HFC-E1 card has alternating D-channel on " |
4871 | "time slot %d\n", dslot[HFC_cnt]); | 4891 | "time slot %d\n", dslot[HFC_cnt]); |
@@ -4876,9 +4896,17 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4876 | hc->masterclk = -1; | 4896 | hc->masterclk = -1; |
4877 | if (type[HFC_cnt] & 0x100) { | 4897 | if (type[HFC_cnt] & 0x100) { |
4878 | test_and_set_bit(HFC_CHIP_ULAW, &hc->chip); | 4898 | test_and_set_bit(HFC_CHIP_ULAW, &hc->chip); |
4879 | silence = 0xff; /* ulaw silence */ | 4899 | hc->silence = 0xff; /* ulaw silence */ |
4880 | } else | 4900 | } else |
4881 | silence = 0x2a; /* alaw silence */ | 4901 | hc->silence = 0x2a; /* alaw silence */ |
4902 | if ((poll >> 1) > sizeof(hc->silence_data)) { | ||
4903 | printk(KERN_ERR "HFCMULTI error: silence_data too small, " | ||
4904 | "please fix\n"); | ||
4905 | return -EINVAL; | ||
4906 | } | ||
4907 | for (i = 0; i < (poll >> 1); i++) | ||
4908 | hc->silence_data[i] = hc->silence; | ||
4909 | |||
4882 | if (!(type[HFC_cnt] & 0x200)) | 4910 | if (!(type[HFC_cnt] & 0x200)) |
4883 | test_and_set_bit(HFC_CHIP_DTMF, &hc->chip); | 4911 | test_and_set_bit(HFC_CHIP_DTMF, &hc->chip); |
4884 | 4912 | ||
@@ -4945,9 +4973,7 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4945 | switch (m->dip_type) { | 4973 | switch (m->dip_type) { |
4946 | case DIP_4S: | 4974 | case DIP_4S: |
4947 | /* | 4975 | /* |
4948 | * get DIP Setting for beroNet 1S/2S/4S cards | 4976 | * Get DIP setting for beroNet 1S/2S/4S cards |
4949 | * check if Port Jumper config matches | ||
4950 | * module param 'protocol' | ||
4951 | * DIP Setting: (collect GPIO 13/14/15 (R_GPIO_IN1) + | 4977 | * DIP Setting: (collect GPIO 13/14/15 (R_GPIO_IN1) + |
4952 | * GPI 19/23 (R_GPI_IN2)) | 4978 | * GPI 19/23 (R_GPI_IN2)) |
4953 | */ | 4979 | */ |
@@ -4966,9 +4992,8 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4966 | break; | 4992 | break; |
4967 | case DIP_8S: | 4993 | case DIP_8S: |
4968 | /* | 4994 | /* |
4969 | * get DIP Setting for beroNet 8S0+ cards | 4995 | * Get DIP Setting for beroNet 8S0+ cards |
4970 | * | 4996 | * Enable PCI auxbridge function |
4971 | * enable PCI auxbridge function | ||
4972 | */ | 4997 | */ |
4973 | HFC_outb(hc, R_BRG_PCM_CFG, 1 | V_PCM_CLK); | 4998 | HFC_outb(hc, R_BRG_PCM_CFG, 1 | V_PCM_CLK); |
4974 | /* prepare access to auxport */ | 4999 | /* prepare access to auxport */ |
@@ -5003,6 +5028,10 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
5003 | list_add_tail(&hc->list, &HFClist); | 5028 | list_add_tail(&hc->list, &HFClist); |
5004 | spin_unlock_irqrestore(&HFClock, flags); | 5029 | spin_unlock_irqrestore(&HFClock, flags); |
5005 | 5030 | ||
5031 | /* use as clock source */ | ||
5032 | if (clock == HFC_cnt + 1) | ||
5033 | hc->iclock = mISDN_register_clock("HFCMulti", 0, clockctl, hc); | ||
5034 | |||
5006 | /* initialize hardware */ | 5035 | /* initialize hardware */ |
5007 | ret_err = init_card(hc); | 5036 | ret_err = init_card(hc); |
5008 | if (ret_err) { | 5037 | if (ret_err) { |
@@ -5137,8 +5166,7 @@ static struct pci_device_id hfmultipci_ids[] __devinitdata = { | |||
5137 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, | 5166 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, |
5138 | PCI_DEVICE_ID_CCD_HFC8S, 0, 0, H(14)}, /* old Eval */ | 5167 | PCI_DEVICE_ID_CCD_HFC8S, 0, 0, H(14)}, /* old Eval */ |
5139 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, | 5168 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, |
5140 | PCI_SUBDEVICE_ID_CCD_IOB8STR, 0, 0, H(15)}, | 5169 | PCI_SUBDEVICE_ID_CCD_IOB8STR, 0, 0, H(15)}, /* IOB8ST Recording */ |
5141 | /* IOB8ST Recording */ | ||
5142 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, | 5170 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, |
5143 | PCI_SUBDEVICE_ID_CCD_IOB8ST, 0, 0, H(16)}, /* IOB8ST */ | 5171 | PCI_SUBDEVICE_ID_CCD_IOB8ST, 0, 0, H(16)}, /* IOB8ST */ |
5144 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, | 5172 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, |
@@ -5188,18 +5216,16 @@ hfcmulti_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
5188 | struct hm_map *m = (struct hm_map *)ent->driver_data; | 5216 | struct hm_map *m = (struct hm_map *)ent->driver_data; |
5189 | int ret; | 5217 | int ret; |
5190 | 5218 | ||
5191 | if (m == NULL) { | 5219 | if (m == NULL && ent->vendor == PCI_VENDOR_ID_CCD && ( |
5192 | if (ent->vendor == PCI_VENDOR_ID_CCD) | 5220 | ent->device == PCI_DEVICE_ID_CCD_HFC4S || |
5193 | if (ent->device == PCI_DEVICE_ID_CCD_HFC4S || | 5221 | ent->device == PCI_DEVICE_ID_CCD_HFC8S || |
5194 | ent->device == PCI_DEVICE_ID_CCD_HFC8S || | 5222 | ent->device == PCI_DEVICE_ID_CCD_HFCE1)) { |
5195 | ent->device == PCI_DEVICE_ID_CCD_HFCE1) | 5223 | printk(KERN_ERR |
5196 | printk(KERN_ERR | 5224 | "Unknown HFC multiport controller (vendor:%x device:%x " |
5197 | "unknown HFC multiport controller " | 5225 | "subvendor:%x subdevice:%x)\n", ent->vendor, ent->device, |
5198 | "(vendor:%x device:%x subvendor:%x " | 5226 | ent->subvendor, ent->subdevice); |
5199 | "subdevice:%x) Please contact the " | 5227 | printk(KERN_ERR |
5200 | "driver maintainer for support.\n", | 5228 | "Please contact the driver maintainer for support.\n"); |
5201 | ent->vendor, ent->device, | ||
5202 | ent->subvendor, ent->subdevice); | ||
5203 | return -ENODEV; | 5229 | return -ENODEV; |
5204 | } | 5230 | } |
5205 | ret = hfcmulti_init(pdev, ent); | 5231 | ret = hfcmulti_init(pdev, ent); |
@@ -5222,22 +5248,9 @@ HFCmulti_cleanup(void) | |||
5222 | { | 5248 | { |
5223 | struct hfc_multi *card, *next; | 5249 | struct hfc_multi *card, *next; |
5224 | 5250 | ||
5225 | /* unload interrupt function symbol */ | 5251 | /* get rid of all devices of this driver */ |
5226 | if (hfc_interrupt) | ||
5227 | symbol_put(ztdummy_extern_interrupt); | ||
5228 | if (register_interrupt) | ||
5229 | symbol_put(ztdummy_register_interrupt); | ||
5230 | if (unregister_interrupt) { | ||
5231 | if (interrupt_registered) { | ||
5232 | interrupt_registered = 0; | ||
5233 | unregister_interrupt(); | ||
5234 | } | ||
5235 | symbol_put(ztdummy_unregister_interrupt); | ||
5236 | } | ||
5237 | |||
5238 | list_for_each_entry_safe(card, next, &HFClist, list) | 5252 | list_for_each_entry_safe(card, next, &HFClist, list) |
5239 | release_card(card); | 5253 | release_card(card); |
5240 | /* get rid of all devices of this driver */ | ||
5241 | pci_unregister_driver(&hfcmultipci_driver); | 5254 | pci_unregister_driver(&hfcmultipci_driver); |
5242 | } | 5255 | } |
5243 | 5256 | ||
@@ -5246,8 +5259,10 @@ HFCmulti_init(void) | |||
5246 | { | 5259 | { |
5247 | int err; | 5260 | int err; |
5248 | 5261 | ||
5262 | printk(KERN_INFO "mISDN: HFC-multi driver %s\n", HFC_MULTI_VERSION); | ||
5263 | |||
5249 | #ifdef IRQ_DEBUG | 5264 | #ifdef IRQ_DEBUG |
5250 | printk(KERN_ERR "%s: IRQ_DEBUG IS ENABLED!\n", __func__); | 5265 | printk(KERN_DEBUG "%s: IRQ_DEBUG IS ENABLED!\n", __func__); |
5251 | #endif | 5266 | #endif |
5252 | 5267 | ||
5253 | spin_lock_init(&HFClock); | 5268 | spin_lock_init(&HFClock); |
@@ -5256,22 +5271,11 @@ HFCmulti_init(void) | |||
5256 | if (debug & DEBUG_HFCMULTI_INIT) | 5271 | if (debug & DEBUG_HFCMULTI_INIT) |
5257 | printk(KERN_DEBUG "%s: init entered\n", __func__); | 5272 | printk(KERN_DEBUG "%s: init entered\n", __func__); |
5258 | 5273 | ||
5259 | hfc_interrupt = symbol_get(ztdummy_extern_interrupt); | ||
5260 | register_interrupt = symbol_get(ztdummy_register_interrupt); | ||
5261 | unregister_interrupt = symbol_get(ztdummy_unregister_interrupt); | ||
5262 | printk(KERN_INFO "mISDN: HFC-multi driver %s\n", | ||
5263 | hfcmulti_revision); | ||
5264 | |||
5265 | switch (poll) { | 5274 | switch (poll) { |
5266 | case 0: | 5275 | case 0: |
5267 | poll_timer = 6; | 5276 | poll_timer = 6; |
5268 | poll = 128; | 5277 | poll = 128; |
5269 | break; | 5278 | break; |
5270 | /* | ||
5271 | * wenn dieses break nochmal verschwindet, | ||
5272 | * gibt es heisse ohren :-) | ||
5273 | * "without the break you will get hot ears ???" | ||
5274 | */ | ||
5275 | case 8: | 5279 | case 8: |
5276 | poll_timer = 2; | 5280 | poll_timer = 2; |
5277 | break; | 5281 | break; |
@@ -5298,20 +5302,12 @@ HFCmulti_init(void) | |||
5298 | 5302 | ||
5299 | } | 5303 | } |
5300 | 5304 | ||
5305 | if (!clock) | ||
5306 | clock = 1; | ||
5307 | |||
5301 | err = pci_register_driver(&hfcmultipci_driver); | 5308 | err = pci_register_driver(&hfcmultipci_driver); |
5302 | if (err < 0) { | 5309 | if (err < 0) { |
5303 | printk(KERN_ERR "error registering pci driver: %x\n", err); | 5310 | printk(KERN_ERR "error registering pci driver: %x\n", err); |
5304 | if (hfc_interrupt) | ||
5305 | symbol_put(ztdummy_extern_interrupt); | ||
5306 | if (register_interrupt) | ||
5307 | symbol_put(ztdummy_register_interrupt); | ||
5308 | if (unregister_interrupt) { | ||
5309 | if (interrupt_registered) { | ||
5310 | interrupt_registered = 0; | ||
5311 | unregister_interrupt(); | ||
5312 | } | ||
5313 | symbol_put(ztdummy_unregister_interrupt); | ||
5314 | } | ||
5315 | return err; | 5311 | return err; |
5316 | } | 5312 | } |
5317 | return 0; | 5313 | return 0; |