diff options
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfc_multi.h | 6 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfcmulti.c | 396 |
2 files changed, 236 insertions, 166 deletions
diff --git a/drivers/isdn/hardware/mISDN/hfc_multi.h b/drivers/isdn/hardware/mISDN/hfc_multi.h index 09e4e77811f1..c601f880141e 100644 --- a/drivers/isdn/hardware/mISDN/hfc_multi.h +++ b/drivers/isdn/hardware/mISDN/hfc_multi.h | |||
@@ -208,7 +208,10 @@ struct hfc_multi { | |||
208 | u_long ledstate; /* save last state of leds */ | 208 | u_long ledstate; /* save last state of leds */ |
209 | int opticalsupport; /* has the e1 board */ | 209 | int opticalsupport; /* has the e1 board */ |
210 | /* an optical Interface */ | 210 | /* an optical Interface */ |
211 | int dslot; /* channel # of d-channel (E1) default 16 */ | 211 | |
212 | u_int bmask[32]; /* bitmask of bchannels for port */ | ||
213 | u_char dnum[32]; /* array of used dchannel numbers for port */ | ||
214 | u_char created[32]; /* what port is created */ | ||
212 | u_int activity_tx; /* if there is data TX / RX */ | 215 | u_int activity_tx; /* if there is data TX / RX */ |
213 | u_int activity_rx; /* bitmask according to port number */ | 216 | u_int activity_rx; /* bitmask according to port number */ |
214 | /* (will be cleared after */ | 217 | /* (will be cleared after */ |
@@ -234,7 +237,6 @@ struct hfc_multi { | |||
234 | * the bch->channel is equvalent to the hfc-channel | 237 | * the bch->channel is equvalent to the hfc-channel |
235 | */ | 238 | */ |
236 | struct hfc_chan chan[32]; | 239 | struct hfc_chan chan[32]; |
237 | u_char created[8]; /* what port is created */ | ||
238 | signed char slot_owner[256]; /* owner channel of slot */ | 240 | signed char slot_owner[256]; /* owner channel of slot */ |
239 | }; | 241 | }; |
240 | 242 | ||
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 876f7d0db26f..43013316b9b0 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c | |||
@@ -103,14 +103,26 @@ | |||
103 | * Omit this value, if all cards are interconnected or none is connected. | 103 | * Omit this value, if all cards are interconnected or none is connected. |
104 | * If unsure, don't give this parameter. | 104 | * If unsure, don't give this parameter. |
105 | * | 105 | * |
106 | * dslot: | 106 | * dmask and bmask: |
107 | * NOTE: only one dslot value must be given for every card. | 107 | * NOTE: One dmask value must be given for every HFC-E1 card. |
108 | * Also this value must be given for non-E1 cards. If omitted, the E1 | 108 | * If omitted, the E1 card has D-channel on time slot 16, which is default. |
109 | * card has D-channel on time slot 16, which is default. | 109 | * dmask is a 32 bit mask. The bit must be set for an alternate time slot. |
110 | * If 1..15 or 17..31, an alternate time slot is used for D-channel. | 110 | * If multiple bits are set, multiple virtual card fragments are created. |
111 | * In this case, the application must be able to handle this. | 111 | * For each bit set, a bmask value must be given. Each bit on the bmask |
112 | * If -1 is given, the D-channel is disabled and all 31 slots can be used | 112 | * value stands for a B-channel. The bmask may not overlap with dmask or |
113 | * for B-channel. (only for specific applications) | 113 | * with other bmask values for that card. |
114 | * Example: dmask=0x00020002 bmask=0x0000fffc,0xfffc0000 | ||
115 | * This will create one fragment with D-channel on slot 1 with | ||
116 | * B-channels on slots 2..15, and a second fragment with D-channel | ||
117 | * on slot 17 with B-channels on slot 18..31. Slot 16 is unused. | ||
118 | * If bit 0 is set (dmask=0x00000001) the D-channel is on slot 0 and will | ||
119 | * not function. | ||
120 | * Example: dmask=0x00000001 bmask=0xfffffffe | ||
121 | * This will create a port with all 31 usable timeslots as | ||
122 | * B-channels. | ||
123 | * If no bits are set on bmask, no B-channel is created for that fragment. | ||
124 | * Example: dmask=0xfffffffe bmask=0,0,0,0.... (31 0-values for bmask) | ||
125 | * This will create 31 ports with one D-channel only. | ||
114 | * If you don't know how to use it, you don't need it! | 126 | * If you don't know how to use it, you don't need it! |
115 | * | 127 | * |
116 | * iomode: | 128 | * iomode: |
@@ -172,6 +184,7 @@ | |||
172 | 184 | ||
173 | #define MAX_CARDS 8 | 185 | #define MAX_CARDS 8 |
174 | #define MAX_PORTS (8 * MAX_CARDS) | 186 | #define MAX_PORTS (8 * MAX_CARDS) |
187 | #define MAX_FRAGS (32 * MAX_CARDS) | ||
175 | 188 | ||
176 | static LIST_HEAD(HFClist); | 189 | static LIST_HEAD(HFClist); |
177 | static spinlock_t HFClock; /* global hfc list lock */ | 190 | static spinlock_t HFClock; /* global hfc list lock */ |
@@ -203,7 +216,8 @@ static int nt_t1_count[] = { 3840, 1920, 960, 480, 240, 120, 60, 30 }; | |||
203 | 216 | ||
204 | static uint type[MAX_CARDS]; | 217 | static uint type[MAX_CARDS]; |
205 | static int pcm[MAX_CARDS]; | 218 | static int pcm[MAX_CARDS]; |
206 | static int dslot[MAX_CARDS]; | 219 | static uint dmask[MAX_CARDS]; |
220 | static uint bmask[MAX_FRAGS]; | ||
207 | static uint iomode[MAX_CARDS]; | 221 | static uint iomode[MAX_CARDS]; |
208 | static uint port[MAX_PORTS]; | 222 | static uint port[MAX_PORTS]; |
209 | static uint debug; | 223 | static uint debug; |
@@ -218,7 +232,7 @@ static uint clockdelay_nt = CLKDEL_NT; | |||
218 | #define HWID_MINIP16 3 | 232 | #define HWID_MINIP16 3 |
219 | static uint hwid = HWID_NONE; | 233 | static uint hwid = HWID_NONE; |
220 | 234 | ||
221 | static int HFC_cnt, Port_cnt, PCM_cnt = 99; | 235 | static int HFC_cnt, E1_cnt, bmask_cnt, Port_cnt, PCM_cnt = 99; |
222 | 236 | ||
223 | MODULE_AUTHOR("Andreas Eversberg"); | 237 | MODULE_AUTHOR("Andreas Eversberg"); |
224 | MODULE_LICENSE("GPL"); | 238 | MODULE_LICENSE("GPL"); |
@@ -231,7 +245,8 @@ module_param(clockdelay_te, uint, S_IRUGO | S_IWUSR); | |||
231 | module_param(clockdelay_nt, uint, S_IRUGO | S_IWUSR); | 245 | module_param(clockdelay_nt, uint, S_IRUGO | S_IWUSR); |
232 | module_param_array(type, uint, NULL, S_IRUGO | S_IWUSR); | 246 | module_param_array(type, uint, NULL, S_IRUGO | S_IWUSR); |
233 | module_param_array(pcm, int, NULL, S_IRUGO | S_IWUSR); | 247 | module_param_array(pcm, int, NULL, S_IRUGO | S_IWUSR); |
234 | module_param_array(dslot, int, NULL, S_IRUGO | S_IWUSR); | 248 | module_param_array(dmask, uint, NULL, S_IRUGO | S_IWUSR); |
249 | module_param_array(bmask, uint, NULL, S_IRUGO | S_IWUSR); | ||
235 | module_param_array(iomode, uint, NULL, S_IRUGO | S_IWUSR); | 250 | module_param_array(iomode, uint, NULL, S_IRUGO | S_IWUSR); |
236 | module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR); | 251 | module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR); |
237 | module_param(hwid, uint, S_IRUGO | S_IWUSR); /* The hardware ID */ | 252 | module_param(hwid, uint, S_IRUGO | S_IWUSR); /* The hardware ID */ |
@@ -1619,9 +1634,9 @@ hfcmulti_leds(struct hfc_multi *hc) | |||
1619 | led[1] = 0; | 1634 | led[1] = 0; |
1620 | led[2] = 0; | 1635 | led[2] = 0; |
1621 | led[3] = 0; | 1636 | led[3] = 0; |
1622 | dch = hc->chan[hc->dslot].dch; | 1637 | dch = hc->chan[hc->dnum[0]].dch; |
1623 | if (dch) { | 1638 | if (dch) { |
1624 | if (hc->chan[hc->dslot].los) | 1639 | if (hc->chan[hc->dnum[0]].los) |
1625 | led[1] = 1; | 1640 | led[1] = 1; |
1626 | if (hc->e1_state != 1) { | 1641 | if (hc->e1_state != 1) { |
1627 | led[0] = 1; | 1642 | led[0] = 1; |
@@ -2453,55 +2468,55 @@ handle_timer_irq(struct hfc_multi *hc) | |||
2453 | } | 2468 | } |
2454 | } | 2469 | } |
2455 | if (hc->ctype == HFC_TYPE_E1 && hc->created[0]) { | 2470 | if (hc->ctype == HFC_TYPE_E1 && hc->created[0]) { |
2456 | dch = hc->chan[hc->dslot].dch; | 2471 | dch = hc->chan[hc->dnum[0]].dch; |
2457 | if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dslot].cfg)) { | 2472 | /* LOS */ |
2458 | /* LOS */ | 2473 | temp = HFC_inb_nodebug(hc, R_SYNC_STA) & V_SIG_LOS; |
2459 | temp = HFC_inb_nodebug(hc, R_SYNC_STA) & V_SIG_LOS; | 2474 | hc->chan[hc->dnum[0]].los = temp; |
2460 | if (!temp && hc->chan[hc->dslot].los) | 2475 | if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dnum[0]].cfg)) { |
2476 | if (!temp && hc->chan[hc->dnum[0]].los) | ||
2461 | signal_state_up(dch, L1_SIGNAL_LOS_ON, | 2477 | signal_state_up(dch, L1_SIGNAL_LOS_ON, |
2462 | "LOS detected"); | 2478 | "LOS detected"); |
2463 | if (temp && !hc->chan[hc->dslot].los) | 2479 | if (temp && !hc->chan[hc->dnum[0]].los) |
2464 | signal_state_up(dch, L1_SIGNAL_LOS_OFF, | 2480 | signal_state_up(dch, L1_SIGNAL_LOS_OFF, |
2465 | "LOS gone"); | 2481 | "LOS gone"); |
2466 | hc->chan[hc->dslot].los = temp; | ||
2467 | } | 2482 | } |
2468 | if (test_bit(HFC_CFG_REPORT_AIS, &hc->chan[hc->dslot].cfg)) { | 2483 | if (test_bit(HFC_CFG_REPORT_AIS, &hc->chan[hc->dnum[0]].cfg)) { |
2469 | /* AIS */ | 2484 | /* AIS */ |
2470 | temp = HFC_inb_nodebug(hc, R_SYNC_STA) & V_AIS; | 2485 | temp = HFC_inb_nodebug(hc, R_SYNC_STA) & V_AIS; |
2471 | if (!temp && hc->chan[hc->dslot].ais) | 2486 | if (!temp && hc->chan[hc->dnum[0]].ais) |
2472 | signal_state_up(dch, L1_SIGNAL_AIS_ON, | 2487 | signal_state_up(dch, L1_SIGNAL_AIS_ON, |
2473 | "AIS detected"); | 2488 | "AIS detected"); |
2474 | if (temp && !hc->chan[hc->dslot].ais) | 2489 | if (temp && !hc->chan[hc->dnum[0]].ais) |
2475 | signal_state_up(dch, L1_SIGNAL_AIS_OFF, | 2490 | signal_state_up(dch, L1_SIGNAL_AIS_OFF, |
2476 | "AIS gone"); | 2491 | "AIS gone"); |
2477 | hc->chan[hc->dslot].ais = temp; | 2492 | hc->chan[hc->dnum[0]].ais = temp; |
2478 | } | 2493 | } |
2479 | if (test_bit(HFC_CFG_REPORT_SLIP, &hc->chan[hc->dslot].cfg)) { | 2494 | if (test_bit(HFC_CFG_REPORT_SLIP, &hc->chan[hc->dnum[0]].cfg)) { |
2480 | /* SLIP */ | 2495 | /* SLIP */ |
2481 | temp = HFC_inb_nodebug(hc, R_SLIP) & V_FOSLIP_RX; | 2496 | temp = HFC_inb_nodebug(hc, R_SLIP) & V_FOSLIP_RX; |
2482 | if (!temp && hc->chan[hc->dslot].slip_rx) | 2497 | if (!temp && hc->chan[hc->dnum[0]].slip_rx) |
2483 | signal_state_up(dch, L1_SIGNAL_SLIP_RX, | 2498 | signal_state_up(dch, L1_SIGNAL_SLIP_RX, |
2484 | " bit SLIP detected RX"); | 2499 | " bit SLIP detected RX"); |
2485 | hc->chan[hc->dslot].slip_rx = temp; | 2500 | hc->chan[hc->dnum[0]].slip_rx = temp; |
2486 | temp = HFC_inb_nodebug(hc, R_SLIP) & V_FOSLIP_TX; | 2501 | temp = HFC_inb_nodebug(hc, R_SLIP) & V_FOSLIP_TX; |
2487 | if (!temp && hc->chan[hc->dslot].slip_tx) | 2502 | if (!temp && hc->chan[hc->dnum[0]].slip_tx) |
2488 | signal_state_up(dch, L1_SIGNAL_SLIP_TX, | 2503 | signal_state_up(dch, L1_SIGNAL_SLIP_TX, |
2489 | " bit SLIP detected TX"); | 2504 | " bit SLIP detected TX"); |
2490 | hc->chan[hc->dslot].slip_tx = temp; | 2505 | hc->chan[hc->dnum[0]].slip_tx = temp; |
2491 | } | 2506 | } |
2492 | if (test_bit(HFC_CFG_REPORT_RDI, &hc->chan[hc->dslot].cfg)) { | 2507 | if (test_bit(HFC_CFG_REPORT_RDI, &hc->chan[hc->dnum[0]].cfg)) { |
2493 | /* RDI */ | 2508 | /* RDI */ |
2494 | temp = HFC_inb_nodebug(hc, R_RX_SL0_0) & V_A; | 2509 | temp = HFC_inb_nodebug(hc, R_RX_SL0_0) & V_A; |
2495 | if (!temp && hc->chan[hc->dslot].rdi) | 2510 | if (!temp && hc->chan[hc->dnum[0]].rdi) |
2496 | signal_state_up(dch, L1_SIGNAL_RDI_ON, | 2511 | signal_state_up(dch, L1_SIGNAL_RDI_ON, |
2497 | "RDI detected"); | 2512 | "RDI detected"); |
2498 | if (temp && !hc->chan[hc->dslot].rdi) | 2513 | if (temp && !hc->chan[hc->dnum[0]].rdi) |
2499 | signal_state_up(dch, L1_SIGNAL_RDI_OFF, | 2514 | signal_state_up(dch, L1_SIGNAL_RDI_OFF, |
2500 | "RDI gone"); | 2515 | "RDI gone"); |
2501 | hc->chan[hc->dslot].rdi = temp; | 2516 | hc->chan[hc->dnum[0]].rdi = temp; |
2502 | } | 2517 | } |
2503 | temp = HFC_inb_nodebug(hc, R_JATT_DIR); | 2518 | temp = HFC_inb_nodebug(hc, R_JATT_DIR); |
2504 | switch (hc->chan[hc->dslot].sync) { | 2519 | switch (hc->chan[hc->dnum[0]].sync) { |
2505 | case 0: | 2520 | case 0: |
2506 | if ((temp & 0x60) == 0x60) { | 2521 | if ((temp & 0x60) == 0x60) { |
2507 | if (debug & DEBUG_HFCMULTI_SYNC) | 2522 | if (debug & DEBUG_HFCMULTI_SYNC) |
@@ -2510,10 +2525,10 @@ handle_timer_irq(struct hfc_multi *hc) | |||
2510 | "in clock sync\n", | 2525 | "in clock sync\n", |
2511 | __func__, hc->id); | 2526 | __func__, hc->id); |
2512 | HFC_outb(hc, R_RX_OFF, | 2527 | HFC_outb(hc, R_RX_OFF, |
2513 | hc->chan[hc->dslot].jitter | V_RX_INIT); | 2528 | hc->chan[hc->dnum[0]].jitter | V_RX_INIT); |
2514 | HFC_outb(hc, R_TX_OFF, | 2529 | HFC_outb(hc, R_TX_OFF, |
2515 | hc->chan[hc->dslot].jitter | V_RX_INIT); | 2530 | hc->chan[hc->dnum[0]].jitter | V_RX_INIT); |
2516 | hc->chan[hc->dslot].sync = 1; | 2531 | hc->chan[hc->dnum[0]].sync = 1; |
2517 | goto check_framesync; | 2532 | goto check_framesync; |
2518 | } | 2533 | } |
2519 | break; | 2534 | break; |
@@ -2524,7 +2539,7 @@ handle_timer_irq(struct hfc_multi *hc) | |||
2524 | "%s: (id=%d) E1 " | 2539 | "%s: (id=%d) E1 " |
2525 | "lost clock sync\n", | 2540 | "lost clock sync\n", |
2526 | __func__, hc->id); | 2541 | __func__, hc->id); |
2527 | hc->chan[hc->dslot].sync = 0; | 2542 | hc->chan[hc->dnum[0]].sync = 0; |
2528 | break; | 2543 | break; |
2529 | } | 2544 | } |
2530 | check_framesync: | 2545 | check_framesync: |
@@ -2535,7 +2550,7 @@ handle_timer_irq(struct hfc_multi *hc) | |||
2535 | "%s: (id=%d) E1 " | 2550 | "%s: (id=%d) E1 " |
2536 | "now in frame sync\n", | 2551 | "now in frame sync\n", |
2537 | __func__, hc->id); | 2552 | __func__, hc->id); |
2538 | hc->chan[hc->dslot].sync = 2; | 2553 | hc->chan[hc->dnum[0]].sync = 2; |
2539 | } | 2554 | } |
2540 | break; | 2555 | break; |
2541 | case 2: | 2556 | case 2: |
@@ -2545,7 +2560,7 @@ handle_timer_irq(struct hfc_multi *hc) | |||
2545 | "%s: (id=%d) E1 lost " | 2560 | "%s: (id=%d) E1 lost " |
2546 | "clock & frame sync\n", | 2561 | "clock & frame sync\n", |
2547 | __func__, hc->id); | 2562 | __func__, hc->id); |
2548 | hc->chan[hc->dslot].sync = 0; | 2563 | hc->chan[hc->dnum[0]].sync = 0; |
2549 | break; | 2564 | break; |
2550 | } | 2565 | } |
2551 | temp = HFC_inb_nodebug(hc, R_SYNC_STA); | 2566 | temp = HFC_inb_nodebug(hc, R_SYNC_STA); |
@@ -2555,7 +2570,7 @@ handle_timer_irq(struct hfc_multi *hc) | |||
2555 | "%s: (id=%d) E1 " | 2570 | "%s: (id=%d) E1 " |
2556 | "lost frame sync\n", | 2571 | "lost frame sync\n", |
2557 | __func__, hc->id); | 2572 | __func__, hc->id); |
2558 | hc->chan[hc->dslot].sync = 1; | 2573 | hc->chan[hc->dnum[0]].sync = 1; |
2559 | } | 2574 | } |
2560 | break; | 2575 | break; |
2561 | } | 2576 | } |
@@ -2696,7 +2711,7 @@ hfcmulti_interrupt(int intno, void *dev_id) | |||
2696 | int i; | 2711 | int i; |
2697 | void __iomem *plx_acc; | 2712 | void __iomem *plx_acc; |
2698 | u_short wval; | 2713 | u_short wval; |
2699 | u_char e1_syncsta, temp; | 2714 | u_char e1_syncsta, temp, temp2; |
2700 | u_long flags; | 2715 | u_long flags; |
2701 | 2716 | ||
2702 | if (!hc) { | 2717 | if (!hc) { |
@@ -2771,7 +2786,7 @@ hfcmulti_interrupt(int intno, void *dev_id) | |||
2771 | if (r_irq_misc & V_STA_IRQ) { | 2786 | if (r_irq_misc & V_STA_IRQ) { |
2772 | if (hc->ctype == HFC_TYPE_E1) { | 2787 | if (hc->ctype == HFC_TYPE_E1) { |
2773 | /* state machine */ | 2788 | /* state machine */ |
2774 | dch = hc->chan[hc->dslot].dch; | 2789 | dch = hc->chan[hc->dnum[0]].dch; |
2775 | e1_syncsta = HFC_inb_nodebug(hc, R_SYNC_STA); | 2790 | e1_syncsta = HFC_inb_nodebug(hc, R_SYNC_STA); |
2776 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip) | 2791 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip) |
2777 | && hc->e1_getclock) { | 2792 | && hc->e1_getclock) { |
@@ -2781,23 +2796,26 @@ hfcmulti_interrupt(int intno, void *dev_id) | |||
2781 | hc->syncronized = 0; | 2796 | hc->syncronized = 0; |
2782 | } | 2797 | } |
2783 | /* undocumented: status changes during read */ | 2798 | /* undocumented: status changes during read */ |
2784 | dch->state = HFC_inb_nodebug(hc, R_E1_RD_STA); | 2799 | temp = HFC_inb_nodebug(hc, R_E1_RD_STA); |
2785 | while (dch->state != (temp = | 2800 | while (temp != (temp2 = |
2786 | HFC_inb_nodebug(hc, R_E1_RD_STA))) { | 2801 | HFC_inb_nodebug(hc, R_E1_RD_STA))) { |
2787 | if (debug & DEBUG_HFCMULTI_STATE) | 2802 | if (debug & DEBUG_HFCMULTI_STATE) |
2788 | printk(KERN_DEBUG "%s: reread " | 2803 | printk(KERN_DEBUG "%s: reread " |
2789 | "STATE because %d!=%d\n", | 2804 | "STATE because %d!=%d\n", |
2790 | __func__, temp, | 2805 | __func__, temp, temp2); |
2791 | dch->state); | 2806 | temp = temp2; /* repeat */ |
2792 | dch->state = temp; /* repeat */ | ||
2793 | } | 2807 | } |
2794 | dch->state = HFC_inb_nodebug(hc, R_E1_RD_STA) | 2808 | /* broadcast state change to all fragments */ |
2795 | & 0x7; | ||
2796 | schedule_event(dch, FLG_PHCHANGE); | ||
2797 | if (debug & DEBUG_HFCMULTI_STATE) | 2809 | if (debug & DEBUG_HFCMULTI_STATE) |
2798 | printk(KERN_DEBUG | 2810 | printk(KERN_DEBUG |
2799 | "%s: E1 (id=%d) newstate %x\n", | 2811 | "%s: E1 (id=%d) newstate %x\n", |
2800 | __func__, hc->id, dch->state); | 2812 | __func__, hc->id, temp & 0x7); |
2813 | for (i = 0; i < hc->ports; i++) { | ||
2814 | dch = hc->chan[hc->dnum[i]].dch; | ||
2815 | dch->state = temp & 0x7; | ||
2816 | schedule_event(dch, FLG_PHCHANGE); | ||
2817 | } | ||
2818 | |||
2801 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) | 2819 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) |
2802 | plxsd_checksync(hc, 0); | 2820 | plxsd_checksync(hc, 0); |
2803 | } | 2821 | } |
@@ -3870,31 +3888,37 @@ hfcmulti_initmode(struct dchannel *dch) | |||
3870 | if (debug & DEBUG_HFCMULTI_INIT) | 3888 | if (debug & DEBUG_HFCMULTI_INIT) |
3871 | printk(KERN_DEBUG "%s: entered\n", __func__); | 3889 | printk(KERN_DEBUG "%s: entered\n", __func__); |
3872 | 3890 | ||
3891 | i = dch->slot; | ||
3892 | pt = hc->chan[i].port; | ||
3873 | if (hc->ctype == HFC_TYPE_E1) { | 3893 | if (hc->ctype == HFC_TYPE_E1) { |
3874 | hc->chan[hc->dslot].slot_tx = -1; | 3894 | /* E1 */ |
3875 | hc->chan[hc->dslot].slot_rx = -1; | 3895 | hc->chan[hc->dnum[pt]].slot_tx = -1; |
3876 | hc->chan[hc->dslot].conf = -1; | 3896 | hc->chan[hc->dnum[pt]].slot_rx = -1; |
3877 | if (hc->dslot) { | 3897 | hc->chan[hc->dnum[pt]].conf = -1; |
3878 | mode_hfcmulti(hc, hc->dslot, dch->dev.D.protocol, | 3898 | if (hc->dnum[pt]) { |
3899 | mode_hfcmulti(hc, dch->slot, dch->dev.D.protocol, | ||
3879 | -1, 0, -1, 0); | 3900 | -1, 0, -1, 0); |
3880 | dch->timer.function = (void *) hfcmulti_dbusy_timer; | 3901 | dch->timer.function = (void *) hfcmulti_dbusy_timer; |
3881 | dch->timer.data = (long) dch; | 3902 | dch->timer.data = (long) dch; |
3882 | init_timer(&dch->timer); | 3903 | init_timer(&dch->timer); |
3883 | } | 3904 | } |
3884 | for (i = 1; i <= 31; i++) { | 3905 | for (i = 1; i <= 31; i++) { |
3885 | if (i == hc->dslot) | 3906 | if (!((1 << i) & hc->bmask[pt])) /* skip unused chan */ |
3886 | continue; | 3907 | continue; |
3887 | hc->chan[i].slot_tx = -1; | 3908 | hc->chan[i].slot_tx = -1; |
3888 | hc->chan[i].slot_rx = -1; | 3909 | hc->chan[i].slot_rx = -1; |
3889 | hc->chan[i].conf = -1; | 3910 | hc->chan[i].conf = -1; |
3890 | mode_hfcmulti(hc, i, ISDN_P_NONE, -1, 0, -1, 0); | 3911 | mode_hfcmulti(hc, i, ISDN_P_NONE, -1, 0, -1, 0); |
3891 | } | 3912 | } |
3892 | /* E1 */ | 3913 | } |
3893 | if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dslot].cfg)) { | 3914 | if (hc->ctype == HFC_TYPE_E1 && pt == 0) { |
3915 | /* E1, port 0 */ | ||
3916 | dch = hc->chan[hc->dnum[0]].dch; | ||
3917 | if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dnum[0]].cfg)) { | ||
3894 | HFC_outb(hc, R_LOS0, 255); /* 2 ms */ | 3918 | HFC_outb(hc, R_LOS0, 255); /* 2 ms */ |
3895 | HFC_outb(hc, R_LOS1, 255); /* 512 ms */ | 3919 | HFC_outb(hc, R_LOS1, 255); /* 512 ms */ |
3896 | } | 3920 | } |
3897 | if (test_bit(HFC_CFG_OPTICAL, &hc->chan[hc->dslot].cfg)) { | 3921 | if (test_bit(HFC_CFG_OPTICAL, &hc->chan[hc->dnum[0]].cfg)) { |
3898 | HFC_outb(hc, R_RX0, 0); | 3922 | HFC_outb(hc, R_RX0, 0); |
3899 | hc->hw.r_tx0 = 0 | V_OUT_EN; | 3923 | hc->hw.r_tx0 = 0 | V_OUT_EN; |
3900 | } else { | 3924 | } else { |
@@ -3907,12 +3931,12 @@ hfcmulti_initmode(struct dchannel *dch) | |||
3907 | HFC_outb(hc, R_TX_FR0, 0x00); | 3931 | HFC_outb(hc, R_TX_FR0, 0x00); |
3908 | HFC_outb(hc, R_TX_FR1, 0xf8); | 3932 | HFC_outb(hc, R_TX_FR1, 0xf8); |
3909 | 3933 | ||
3910 | if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dslot].cfg)) | 3934 | if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dnum[0]].cfg)) |
3911 | HFC_outb(hc, R_TX_FR2, V_TX_MF | V_TX_E | V_NEG_E); | 3935 | HFC_outb(hc, R_TX_FR2, V_TX_MF | V_TX_E | V_NEG_E); |
3912 | 3936 | ||
3913 | HFC_outb(hc, R_RX_FR0, V_AUTO_RESYNC | V_AUTO_RECO | 0); | 3937 | HFC_outb(hc, R_RX_FR0, V_AUTO_RESYNC | V_AUTO_RECO | 0); |
3914 | 3938 | ||
3915 | if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dslot].cfg)) | 3939 | if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dnum[0]].cfg)) |
3916 | HFC_outb(hc, R_RX_FR1, V_RX_MF | V_RX_MF_SYNC); | 3940 | HFC_outb(hc, R_RX_FR1, V_RX_MF | V_RX_MF_SYNC); |
3917 | 3941 | ||
3918 | if (dch->dev.D.protocol == ISDN_P_NT_E1) { | 3942 | if (dch->dev.D.protocol == ISDN_P_NT_E1) { |
@@ -3975,13 +3999,14 @@ hfcmulti_initmode(struct dchannel *dch) | |||
3975 | hc->syncronized = 0; | 3999 | hc->syncronized = 0; |
3976 | plxsd_checksync(hc, 0); | 4000 | plxsd_checksync(hc, 0); |
3977 | } | 4001 | } |
3978 | } else { | 4002 | } |
3979 | i = dch->slot; | 4003 | if (hc->ctype != HFC_TYPE_E1) { |
4004 | /* ST */ | ||
3980 | hc->chan[i].slot_tx = -1; | 4005 | hc->chan[i].slot_tx = -1; |
3981 | hc->chan[i].slot_rx = -1; | 4006 | hc->chan[i].slot_rx = -1; |
3982 | hc->chan[i].conf = -1; | 4007 | hc->chan[i].conf = -1; |
3983 | mode_hfcmulti(hc, i, dch->dev.D.protocol, -1, 0, -1, 0); | 4008 | mode_hfcmulti(hc, i, dch->dev.D.protocol, -1, 0, -1, 0); |
3984 | dch->timer.function = (void *)hfcmulti_dbusy_timer; | 4009 | dch->timer.function = (void *) hfcmulti_dbusy_timer; |
3985 | dch->timer.data = (long) dch; | 4010 | dch->timer.data = (long) dch; |
3986 | init_timer(&dch->timer); | 4011 | init_timer(&dch->timer); |
3987 | hc->chan[i - 2].slot_tx = -1; | 4012 | hc->chan[i - 2].slot_tx = -1; |
@@ -3992,8 +4017,6 @@ hfcmulti_initmode(struct dchannel *dch) | |||
3992 | hc->chan[i - 1].slot_rx = -1; | 4017 | hc->chan[i - 1].slot_rx = -1; |
3993 | hc->chan[i - 1].conf = -1; | 4018 | hc->chan[i - 1].conf = -1; |
3994 | mode_hfcmulti(hc, i - 1, ISDN_P_NONE, -1, 0, -1, 0); | 4019 | mode_hfcmulti(hc, i - 1, ISDN_P_NONE, -1, 0, -1, 0); |
3995 | /* ST */ | ||
3996 | pt = hc->chan[i].port; | ||
3997 | /* select interface */ | 4020 | /* select interface */ |
3998 | HFC_outb(hc, R_ST_SEL, pt); | 4021 | HFC_outb(hc, R_ST_SEL, pt); |
3999 | /* undocumented: delay after R_ST_SEL */ | 4022 | /* undocumented: delay after R_ST_SEL */ |
@@ -4571,6 +4594,8 @@ release_port(struct hfc_multi *hc, struct dchannel *dch) | |||
4571 | } | 4594 | } |
4572 | /* free channels */ | 4595 | /* free channels */ |
4573 | for (i = 0; i <= 31; i++) { | 4596 | for (i = 0; i <= 31; i++) { |
4597 | if (!((1 << i) & hc->bmask[pt])) /* skip unused chan */ | ||
4598 | continue; | ||
4574 | if (hc->chan[i].bch) { | 4599 | if (hc->chan[i].bch) { |
4575 | if (debug & DEBUG_HFCMULTI_INIT) | 4600 | if (debug & DEBUG_HFCMULTI_INIT) |
4576 | printk(KERN_DEBUG | 4601 | printk(KERN_DEBUG |
@@ -4626,7 +4651,8 @@ release_port(struct hfc_multi *hc, struct dchannel *dch) | |||
4626 | spin_unlock_irqrestore(&hc->lock, flags); | 4651 | spin_unlock_irqrestore(&hc->lock, flags); |
4627 | 4652 | ||
4628 | if (debug & DEBUG_HFCMULTI_INIT) | 4653 | if (debug & DEBUG_HFCMULTI_INIT) |
4629 | printk(KERN_DEBUG "%s: free port %d channel D\n", __func__, pt); | 4654 | printk(KERN_DEBUG "%s: free port %d channel D(%d)\n", __func__, |
4655 | pt+1, ci); | ||
4630 | mISDN_freedchannel(dch); | 4656 | mISDN_freedchannel(dch); |
4631 | kfree(dch); | 4657 | kfree(dch); |
4632 | 4658 | ||
@@ -4648,15 +4674,19 @@ release_card(struct hfc_multi *hc) | |||
4648 | if (hc->iclock) | 4674 | if (hc->iclock) |
4649 | mISDN_unregister_clock(hc->iclock); | 4675 | mISDN_unregister_clock(hc->iclock); |
4650 | 4676 | ||
4651 | /* disable irq */ | 4677 | /* disable and free irq */ |
4652 | spin_lock_irqsave(&hc->lock, flags); | 4678 | spin_lock_irqsave(&hc->lock, flags); |
4653 | disable_hwirq(hc); | 4679 | disable_hwirq(hc); |
4654 | spin_unlock_irqrestore(&hc->lock, flags); | 4680 | spin_unlock_irqrestore(&hc->lock, flags); |
4655 | udelay(1000); | 4681 | udelay(1000); |
4682 | if (hc->irq) { | ||
4683 | if (debug & DEBUG_HFCMULTI_INIT) | ||
4684 | printk(KERN_DEBUG "%s: free irq %d (hc=%p)\n", | ||
4685 | __func__, hc->irq, hc); | ||
4686 | free_irq(hc->irq, hc); | ||
4687 | hc->irq = 0; | ||
4656 | 4688 | ||
4657 | /* dimm leds */ | 4689 | } |
4658 | if (hc->leds) | ||
4659 | hfcmulti_leds(hc); | ||
4660 | 4690 | ||
4661 | /* disable D-channels & B-channels */ | 4691 | /* disable D-channels & B-channels */ |
4662 | if (debug & DEBUG_HFCMULTI_INIT) | 4692 | if (debug & DEBUG_HFCMULTI_INIT) |
@@ -4667,15 +4697,11 @@ release_card(struct hfc_multi *hc) | |||
4667 | release_port(hc, hc->chan[ch].dch); | 4697 | release_port(hc, hc->chan[ch].dch); |
4668 | } | 4698 | } |
4669 | 4699 | ||
4670 | /* release hardware & irq */ | 4700 | /* dimm leds */ |
4671 | if (hc->irq) { | 4701 | if (hc->leds) |
4672 | if (debug & DEBUG_HFCMULTI_INIT) | 4702 | hfcmulti_leds(hc); |
4673 | printk(KERN_DEBUG "%s: free irq %d\n", | ||
4674 | __func__, hc->irq); | ||
4675 | free_irq(hc->irq, hc); | ||
4676 | hc->irq = 0; | ||
4677 | 4703 | ||
4678 | } | 4704 | /* release hardware */ |
4679 | release_io_hfcmulti(hc); | 4705 | release_io_hfcmulti(hc); |
4680 | 4706 | ||
4681 | if (debug & DEBUG_HFCMULTI_INIT) | 4707 | if (debug & DEBUG_HFCMULTI_INIT) |
@@ -4693,61 +4719,9 @@ release_card(struct hfc_multi *hc) | |||
4693 | __func__); | 4719 | __func__); |
4694 | } | 4720 | } |
4695 | 4721 | ||
4696 | static int | 4722 | static void |
4697 | init_e1_port(struct hfc_multi *hc, struct hm_map *m) | 4723 | init_e1_port_hw(struct hfc_multi *hc, struct hm_map *m) |
4698 | { | 4724 | { |
4699 | struct dchannel *dch; | ||
4700 | struct bchannel *bch; | ||
4701 | int ch, ret = 0; | ||
4702 | char name[MISDN_MAX_IDLEN]; | ||
4703 | |||
4704 | dch = kzalloc(sizeof(struct dchannel), GFP_KERNEL); | ||
4705 | if (!dch) | ||
4706 | return -ENOMEM; | ||
4707 | dch->debug = debug; | ||
4708 | mISDN_initdchannel(dch, MAX_DFRAME_LEN_L1, ph_state_change); | ||
4709 | dch->hw = hc; | ||
4710 | dch->dev.Dprotocols = (1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1); | ||
4711 | dch->dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) | | ||
4712 | (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)); | ||
4713 | dch->dev.D.send = handle_dmsg; | ||
4714 | dch->dev.D.ctrl = hfcm_dctrl; | ||
4715 | dch->dev.nrbchan = (hc->dslot) ? 30 : 31; | ||
4716 | dch->slot = hc->dslot; | ||
4717 | hc->chan[hc->dslot].dch = dch; | ||
4718 | hc->chan[hc->dslot].port = 0; | ||
4719 | hc->chan[hc->dslot].nt_timer = -1; | ||
4720 | for (ch = 1; ch <= 31; ch++) { | ||
4721 | if (ch == hc->dslot) /* skip dchannel */ | ||
4722 | continue; | ||
4723 | bch = kzalloc(sizeof(struct bchannel), GFP_KERNEL); | ||
4724 | if (!bch) { | ||
4725 | printk(KERN_ERR "%s: no memory for bchannel\n", | ||
4726 | __func__); | ||
4727 | ret = -ENOMEM; | ||
4728 | goto free_chan; | ||
4729 | } | ||
4730 | hc->chan[ch].coeff = kzalloc(512, GFP_KERNEL); | ||
4731 | if (!hc->chan[ch].coeff) { | ||
4732 | printk(KERN_ERR "%s: no memory for coeffs\n", | ||
4733 | __func__); | ||
4734 | ret = -ENOMEM; | ||
4735 | kfree(bch); | ||
4736 | goto free_chan; | ||
4737 | } | ||
4738 | bch->nr = ch; | ||
4739 | bch->slot = ch; | ||
4740 | bch->debug = debug; | ||
4741 | mISDN_initbchannel(bch, MAX_DATA_MEM); | ||
4742 | bch->hw = hc; | ||
4743 | bch->ch.send = handle_bmsg; | ||
4744 | bch->ch.ctrl = hfcm_bctrl; | ||
4745 | bch->ch.nr = ch; | ||
4746 | list_add(&bch->ch.list, &dch->dev.bchannels); | ||
4747 | hc->chan[ch].bch = bch; | ||
4748 | hc->chan[ch].port = 0; | ||
4749 | set_channelmap(bch->nr, dch->dev.channelmap); | ||
4750 | } | ||
4751 | /* set optical line type */ | 4725 | /* set optical line type */ |
4752 | if (port[Port_cnt] & 0x001) { | 4726 | if (port[Port_cnt] & 0x001) { |
4753 | if (!m->opticalsupport) { | 4727 | if (!m->opticalsupport) { |
@@ -4763,7 +4737,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m) | |||
4763 | __func__, | 4737 | __func__, |
4764 | HFC_cnt + 1, 1); | 4738 | HFC_cnt + 1, 1); |
4765 | test_and_set_bit(HFC_CFG_OPTICAL, | 4739 | test_and_set_bit(HFC_CFG_OPTICAL, |
4766 | &hc->chan[hc->dslot].cfg); | 4740 | &hc->chan[hc->dnum[0]].cfg); |
4767 | } | 4741 | } |
4768 | } | 4742 | } |
4769 | /* set LOS report */ | 4743 | /* set LOS report */ |
@@ -4773,7 +4747,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m) | |||
4773 | "LOS report: card(%d) port(%d)\n", | 4747 | "LOS report: card(%d) port(%d)\n", |
4774 | __func__, HFC_cnt + 1, 1); | 4748 | __func__, HFC_cnt + 1, 1); |
4775 | test_and_set_bit(HFC_CFG_REPORT_LOS, | 4749 | test_and_set_bit(HFC_CFG_REPORT_LOS, |
4776 | &hc->chan[hc->dslot].cfg); | 4750 | &hc->chan[hc->dnum[0]].cfg); |
4777 | } | 4751 | } |
4778 | /* set AIS report */ | 4752 | /* set AIS report */ |
4779 | if (port[Port_cnt] & 0x008) { | 4753 | if (port[Port_cnt] & 0x008) { |
@@ -4782,7 +4756,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m) | |||
4782 | "AIS report: card(%d) port(%d)\n", | 4756 | "AIS report: card(%d) port(%d)\n", |
4783 | __func__, HFC_cnt + 1, 1); | 4757 | __func__, HFC_cnt + 1, 1); |
4784 | test_and_set_bit(HFC_CFG_REPORT_AIS, | 4758 | test_and_set_bit(HFC_CFG_REPORT_AIS, |
4785 | &hc->chan[hc->dslot].cfg); | 4759 | &hc->chan[hc->dnum[0]].cfg); |
4786 | } | 4760 | } |
4787 | /* set SLIP report */ | 4761 | /* set SLIP report */ |
4788 | if (port[Port_cnt] & 0x010) { | 4762 | if (port[Port_cnt] & 0x010) { |
@@ -4792,7 +4766,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m) | |||
4792 | "card(%d) port(%d)\n", | 4766 | "card(%d) port(%d)\n", |
4793 | __func__, HFC_cnt + 1, 1); | 4767 | __func__, HFC_cnt + 1, 1); |
4794 | test_and_set_bit(HFC_CFG_REPORT_SLIP, | 4768 | test_and_set_bit(HFC_CFG_REPORT_SLIP, |
4795 | &hc->chan[hc->dslot].cfg); | 4769 | &hc->chan[hc->dnum[0]].cfg); |
4796 | } | 4770 | } |
4797 | /* set RDI report */ | 4771 | /* set RDI report */ |
4798 | if (port[Port_cnt] & 0x020) { | 4772 | if (port[Port_cnt] & 0x020) { |
@@ -4802,7 +4776,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m) | |||
4802 | "card(%d) port(%d)\n", | 4776 | "card(%d) port(%d)\n", |
4803 | __func__, HFC_cnt + 1, 1); | 4777 | __func__, HFC_cnt + 1, 1); |
4804 | test_and_set_bit(HFC_CFG_REPORT_RDI, | 4778 | test_and_set_bit(HFC_CFG_REPORT_RDI, |
4805 | &hc->chan[hc->dslot].cfg); | 4779 | &hc->chan[hc->dnum[0]].cfg); |
4806 | } | 4780 | } |
4807 | /* set CRC-4 Mode */ | 4781 | /* set CRC-4 Mode */ |
4808 | if (!(port[Port_cnt] & 0x100)) { | 4782 | if (!(port[Port_cnt] & 0x100)) { |
@@ -4811,7 +4785,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m) | |||
4811 | " card(%d) port(%d)\n", | 4785 | " card(%d) port(%d)\n", |
4812 | __func__, HFC_cnt + 1, 1); | 4786 | __func__, HFC_cnt + 1, 1); |
4813 | test_and_set_bit(HFC_CFG_CRC4, | 4787 | test_and_set_bit(HFC_CFG_CRC4, |
4814 | &hc->chan[hc->dslot].cfg); | 4788 | &hc->chan[hc->dnum[0]].cfg); |
4815 | } else { | 4789 | } else { |
4816 | if (debug & DEBUG_HFCMULTI_INIT) | 4790 | if (debug & DEBUG_HFCMULTI_INIT) |
4817 | printk(KERN_DEBUG "%s: PORT turn off CRC4" | 4791 | printk(KERN_DEBUG "%s: PORT turn off CRC4" |
@@ -4843,20 +4817,85 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m) | |||
4843 | } | 4817 | } |
4844 | /* set elastic jitter buffer */ | 4818 | /* set elastic jitter buffer */ |
4845 | if (port[Port_cnt] & 0x3000) { | 4819 | if (port[Port_cnt] & 0x3000) { |
4846 | hc->chan[hc->dslot].jitter = (port[Port_cnt]>>12) & 0x3; | 4820 | hc->chan[hc->dnum[0]].jitter = (port[Port_cnt]>>12) & 0x3; |
4847 | if (debug & DEBUG_HFCMULTI_INIT) | 4821 | if (debug & DEBUG_HFCMULTI_INIT) |
4848 | printk(KERN_DEBUG | 4822 | printk(KERN_DEBUG |
4849 | "%s: PORT set elastic " | 4823 | "%s: PORT set elastic " |
4850 | "buffer to %d: card(%d) port(%d)\n", | 4824 | "buffer to %d: card(%d) port(%d)\n", |
4851 | __func__, hc->chan[hc->dslot].jitter, | 4825 | __func__, hc->chan[hc->dnum[0]].jitter, |
4852 | HFC_cnt + 1, 1); | 4826 | HFC_cnt + 1, 1); |
4853 | } else | 4827 | } else |
4854 | hc->chan[hc->dslot].jitter = 2; /* default */ | 4828 | hc->chan[hc->dnum[0]].jitter = 2; /* default */ |
4855 | snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1); | 4829 | } |
4830 | |||
4831 | static int | ||
4832 | init_e1_port(struct hfc_multi *hc, struct hm_map *m, int pt) | ||
4833 | { | ||
4834 | struct dchannel *dch; | ||
4835 | struct bchannel *bch; | ||
4836 | int ch, ret = 0; | ||
4837 | char name[MISDN_MAX_IDLEN]; | ||
4838 | int bcount = 0; | ||
4839 | |||
4840 | dch = kzalloc(sizeof(struct dchannel), GFP_KERNEL); | ||
4841 | if (!dch) | ||
4842 | return -ENOMEM; | ||
4843 | dch->debug = debug; | ||
4844 | mISDN_initdchannel(dch, MAX_DFRAME_LEN_L1, ph_state_change); | ||
4845 | dch->hw = hc; | ||
4846 | dch->dev.Dprotocols = (1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1); | ||
4847 | dch->dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) | | ||
4848 | (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)); | ||
4849 | dch->dev.D.send = handle_dmsg; | ||
4850 | dch->dev.D.ctrl = hfcm_dctrl; | ||
4851 | dch->slot = hc->dnum[pt]; | ||
4852 | hc->chan[hc->dnum[pt]].dch = dch; | ||
4853 | hc->chan[hc->dnum[pt]].port = pt; | ||
4854 | hc->chan[hc->dnum[pt]].nt_timer = -1; | ||
4855 | for (ch = 1; ch <= 31; ch++) { | ||
4856 | if (!((1 << ch) & hc->bmask[pt])) /* skip unused channel */ | ||
4857 | continue; | ||
4858 | bch = kzalloc(sizeof(struct bchannel), GFP_KERNEL); | ||
4859 | if (!bch) { | ||
4860 | printk(KERN_ERR "%s: no memory for bchannel\n", | ||
4861 | __func__); | ||
4862 | ret = -ENOMEM; | ||
4863 | goto free_chan; | ||
4864 | } | ||
4865 | hc->chan[ch].coeff = kzalloc(512, GFP_KERNEL); | ||
4866 | if (!hc->chan[ch].coeff) { | ||
4867 | printk(KERN_ERR "%s: no memory for coeffs\n", | ||
4868 | __func__); | ||
4869 | ret = -ENOMEM; | ||
4870 | kfree(bch); | ||
4871 | goto free_chan; | ||
4872 | } | ||
4873 | bch->nr = ch; | ||
4874 | bch->slot = ch; | ||
4875 | bch->debug = debug; | ||
4876 | mISDN_initbchannel(bch, MAX_DATA_MEM); | ||
4877 | bch->hw = hc; | ||
4878 | bch->ch.send = handle_bmsg; | ||
4879 | bch->ch.ctrl = hfcm_bctrl; | ||
4880 | bch->ch.nr = ch; | ||
4881 | list_add(&bch->ch.list, &dch->dev.bchannels); | ||
4882 | hc->chan[ch].bch = bch; | ||
4883 | hc->chan[ch].port = pt; | ||
4884 | set_channelmap(bch->nr, dch->dev.channelmap); | ||
4885 | bcount++; | ||
4886 | } | ||
4887 | dch->dev.nrbchan = bcount; | ||
4888 | if (pt == 0) | ||
4889 | init_e1_port_hw(hc, m); | ||
4890 | if (hc->ports > 1) | ||
4891 | snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d-%d", | ||
4892 | HFC_cnt + 1, pt+1); | ||
4893 | else | ||
4894 | snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1); | ||
4856 | ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name); | 4895 | ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name); |
4857 | if (ret) | 4896 | if (ret) |
4858 | goto free_chan; | 4897 | goto free_chan; |
4859 | hc->created[0] = 1; | 4898 | hc->created[pt] = 1; |
4860 | return ret; | 4899 | return ret; |
4861 | free_chan: | 4900 | free_chan: |
4862 | release_port(hc, dch); | 4901 | release_port(hc, dch); |
@@ -4989,7 +5028,8 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev, | |||
4989 | struct hfc_multi *hc; | 5028 | struct hfc_multi *hc; |
4990 | u_long flags; | 5029 | u_long flags; |
4991 | u_char dips = 0, pmj = 0; /* dip settings, port mode Jumpers */ | 5030 | u_char dips = 0, pmj = 0; /* dip settings, port mode Jumpers */ |
4992 | int i; | 5031 | int i, ch; |
5032 | u_int maskcheck; | ||
4993 | 5033 | ||
4994 | if (HFC_cnt >= MAX_CARDS) { | 5034 | if (HFC_cnt >= MAX_CARDS) { |
4995 | printk(KERN_ERR "too many cards (max=%d).\n", | 5035 | printk(KERN_ERR "too many cards (max=%d).\n", |
@@ -5023,18 +5063,36 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev, | |||
5023 | hc->id = HFC_cnt; | 5063 | hc->id = HFC_cnt; |
5024 | hc->pcm = pcm[HFC_cnt]; | 5064 | hc->pcm = pcm[HFC_cnt]; |
5025 | hc->io_mode = iomode[HFC_cnt]; | 5065 | hc->io_mode = iomode[HFC_cnt]; |
5026 | if (dslot[HFC_cnt] < 0 && hc->ctype == HFC_TYPE_E1) { | 5066 | if (hc->ctype == HFC_TYPE_E1 && dmask[E1_cnt]) { |
5027 | hc->dslot = 0; | 5067 | /* fragment card */ |
5028 | printk(KERN_INFO "HFC-E1 card has disabled D-channel, but " | 5068 | pt = 0; |
5029 | "31 B-channels\n"); | 5069 | maskcheck = 0; |
5030 | } | 5070 | for (ch = 0; ch <= 31; ch++) { |
5031 | if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32 | 5071 | if (!((1 << ch) & dmask[E1_cnt])) |
5032 | && hc->ctype == HFC_TYPE_E1) { | 5072 | continue; |
5033 | hc->dslot = dslot[HFC_cnt]; | 5073 | hc->dnum[pt] = ch; |
5034 | printk(KERN_INFO "HFC-E1 card has alternating D-channel on " | 5074 | hc->bmask[pt] = bmask[bmask_cnt++]; |
5035 | "time slot %d\n", dslot[HFC_cnt]); | 5075 | if ((maskcheck & hc->bmask[pt]) |
5036 | } else | 5076 | || (dmask[E1_cnt] & hc->bmask[pt])) { |
5037 | hc->dslot = 16; | 5077 | printk(KERN_INFO |
5078 | "HFC-E1 #%d has overlapping B-channels on fragment #%d\n", | ||
5079 | E1_cnt + 1, pt); | ||
5080 | return -EINVAL; | ||
5081 | } | ||
5082 | maskcheck |= hc->bmask[pt]; | ||
5083 | printk(KERN_INFO | ||
5084 | "HFC-E1 #%d uses D-channel on slot %d and a B-channel map of 0x%08x\n", | ||
5085 | E1_cnt + 1, ch, hc->bmask[pt]); | ||
5086 | pt++; | ||
5087 | } | ||
5088 | hc->ports = pt; | ||
5089 | } | ||
5090 | if (hc->ctype == HFC_TYPE_E1 && !dmask[E1_cnt]) { | ||
5091 | /* default card layout */ | ||
5092 | hc->dnum[0] = 16; | ||
5093 | hc->bmask[0] = 0xfffefffe; | ||
5094 | hc->ports = 1; | ||
5095 | } | ||
5038 | 5096 | ||
5039 | /* set chip specific features */ | 5097 | /* set chip specific features */ |
5040 | hc->masterclk = -1; | 5098 | hc->masterclk = -1; |
@@ -5117,23 +5175,33 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev, | |||
5117 | goto free_card; | 5175 | goto free_card; |
5118 | } | 5176 | } |
5119 | if (hc->ctype == HFC_TYPE_E1) | 5177 | if (hc->ctype == HFC_TYPE_E1) |
5120 | ret_err = init_e1_port(hc, m); | 5178 | ret_err = init_e1_port(hc, m, pt); |
5121 | else | 5179 | else |
5122 | ret_err = init_multi_port(hc, pt); | 5180 | ret_err = init_multi_port(hc, pt); |
5123 | if (debug & DEBUG_HFCMULTI_INIT) | 5181 | if (debug & DEBUG_HFCMULTI_INIT) |
5124 | printk(KERN_DEBUG | 5182 | printk(KERN_DEBUG |
5125 | "%s: Registering D-channel, card(%d) port(%d)" | 5183 | "%s: Registering D-channel, card(%d) port(%d) " |
5126 | "result %d\n", | 5184 | "result %d\n", |
5127 | __func__, HFC_cnt + 1, pt, ret_err); | 5185 | __func__, HFC_cnt + 1, pt + 1, ret_err); |
5128 | 5186 | ||
5129 | if (ret_err) { | 5187 | if (ret_err) { |
5130 | while (pt) { /* release already registered ports */ | 5188 | while (pt) { /* release already registered ports */ |
5131 | pt--; | 5189 | pt--; |
5132 | release_port(hc, hc->chan[(pt << 2) + 2].dch); | 5190 | if (hc->ctype == HFC_TYPE_E1) |
5191 | release_port(hc, | ||
5192 | hc->chan[hc->dnum[pt]].dch); | ||
5193 | else | ||
5194 | release_port(hc, | ||
5195 | hc->chan[(pt << 2) + 2].dch); | ||
5133 | } | 5196 | } |
5134 | goto free_card; | 5197 | goto free_card; |
5135 | } | 5198 | } |
5136 | Port_cnt++; | 5199 | if (hc->ctype != HFC_TYPE_E1) |
5200 | Port_cnt++; /* for each S0 port */ | ||
5201 | } | ||
5202 | if (hc->ctype == HFC_TYPE_E1) { | ||
5203 | Port_cnt++; /* for each E1 port */ | ||
5204 | E1_cnt++; | ||
5137 | } | 5205 | } |
5138 | 5206 | ||
5139 | /* disp switches */ | 5207 | /* disp switches */ |