diff options
Diffstat (limited to 'xpp/card_bri.c')
-rw-r--r-- | xpp/card_bri.c | 359 |
1 files changed, 257 insertions, 102 deletions
diff --git a/xpp/card_bri.c b/xpp/card_bri.c index ad10aed..9919036 100644 --- a/xpp/card_bri.c +++ b/xpp/card_bri.c @@ -105,7 +105,7 @@ static const char *xhfc_state_name(xpd_type_t xpd_type, enum xhfc_states state) #define HFC_L1_ACTIVATING 1 #define HFC_L1_ACTIVATED 2 -#define NT_T1_COUNT 25 /* number of 4ms interrupts for G2 timeout */ +#define TIMER_T1_MAX 2500 #define HFC_TIMER_T3 8000 /* 8s activation timer T3 */ #define HFC_TIMER_T4 500 /* 500ms deactivation timer T4 */ #define HFC_TIMER_OFF -1 /* timer disabled */ @@ -130,6 +130,7 @@ typedef union { } su_rd_sta_t; #define REG30_LOST 3 /* in polls */ +#define DCHAN_LOST 15000 /* in ticks */ #define BRI_DCHAN_SIGCAP ( \ ZT_SIG_EM | \ @@ -163,18 +164,13 @@ static int proc_xpd_register_write(struct file *file, const char __user *buffer, enum led_state { BRI_LED_OFF = 0x0, BRI_LED_ON = 0x1, - BRI_LED_BLINK_SLOW = 0x2, /* 1/2 a second blink cycle */ - BRI_LED_BLINK_FAST = 0x3 /* 1/4 a second blink cycle */ -}; - -#define LED_STATE_NAME(x) [ BRI_ ## x ] = #x -static const char *led_state_names[] = { - LED_STATE_NAME(LED_OFF), - LED_STATE_NAME(LED_ON), - LED_STATE_NAME(LED_BLINK_SLOW), - LED_STATE_NAME(LED_BLINK_FAST), + /* + * We blink by software from driver, so that + * if the driver malfunction that blink would stop. + */ + // BRI_LED_BLINK_SLOW = 0x2, /* 1/2 a second blink cycle */ + // BRI_LED_BLINK_FAST = 0x3 /* 1/4 a second blink cycle */ }; -#undef LED_STATE_NAME enum bri_led_names { GREEN_LED = 0, @@ -184,6 +180,7 @@ enum bri_led_names { #define NUM_LEDS 2 #define LED_TICKS 100 + struct bri_leds { byte state:2; byte led_sel:1; /* 0 - GREEN, 1 - RED */ @@ -201,11 +198,13 @@ struct BRI_priv_data { struct proc_dir_entry *bri_info; su_rd_sta_t state_register; bool initialized; + int t1; /* timer 1 for NT deactivation */ int t3; /* timer 3 for activation */ int t4; /* timer 4 for deactivation */ ulong l1_flags; bool reg30_good; uint reg30_ticks; + bool layer1_up; /* * D-Chan: buffers + extra state info. @@ -219,9 +218,14 @@ struct BRI_priv_data { reg_cmd_t last_reply; uint tick_counter; uint poll_counter; - uint drop_counter; + uint dchan_tx_counter; + uint dchan_rx_counter; + uint dchan_rx_drops; + bool dchan_alive; + uint dchan_alive_ticks; + uint dchan_notx_ticks; + uint dchan_norx_ticks; enum led_state ledstate[NUM_LEDS]; - enum led_state ledcontrol[NUM_LEDS]; }; xproto_table_t PROTO_TABLE(BRI_NT); @@ -240,19 +244,14 @@ static void dump_hex_buf(xpd_t *xpd, char *msg, byte *buf, size_t len) { char debug_buf[DEBUG_BUF_SIZE + 1]; int i; - char *p; + int n = 0; xbus_t *xbus = xpd->xbus; - if (len >= DEBUG_BUF_SIZE) { - ERR("%s: dumped buffer too long. Length: %d, Maximum allowed: %d.\n", - __FUNCTION__, len, DEBUG_BUF_SIZE); - return; - } - p = debug_buf; - *p = '\0'; - for(i=0; i<len; i++) - p += snprintf(p, DEBUG_BUF_SIZE - (p - debug_buf), "%02X ", buf[i]); - printk(KERN_DEBUG "%s/%s: %s[0..%d]: %s\n", xbus->busname, xpd->xpdname, msg, len-1, debug_buf); + debug_buf[0] = '\0'; + for(i = 0; i < len && n < DEBUG_BUF_SIZE; i++) + n += snprintf(&debug_buf[n], DEBUG_BUF_SIZE - n, "%02X ", buf[i]); + DBG("%s/%s: %s[0..%d]: %s%s\n", xbus->busname, xpd->xpdname, msg, + len-1, debug_buf, (n >= DEBUG_BUF_SIZE)?"...":""); } static void dump_dchan_packet(xpd_t *xpd, bool transmit, byte *buf, int len) @@ -289,6 +288,83 @@ static void dump_dchan_packet(xpd_t *xpd, bool transmit, byte *buf, int len) dump_hex_buf(xpd, msgbuf, buf, len); } +static void layer1_state(xpd_t *xpd, bool up) +{ + struct BRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(priv->layer1_up == up) + return; + priv->layer1_up = up; + DBG("%s/%s: STATE CHANGE: Layer1 %s\n", xpd->xbus->busname, xpd->xpdname, + (up)?"UP":"DOWN"); +} + +static void dchan_state(xpd_t *xpd, bool up) +{ + struct BRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(priv->dchan_alive == up) + return; + if(up) { + DBG("%s/%s: STATE CHANGE: D-Channel RUNNING\n", + xpd->xbus->busname, xpd->xpdname); + priv->dchan_alive = 1; + } else { + DBG("%s/%s: STATE CHANGE: D-Channel STOPPED\n", + xpd->xbus->busname, xpd->xpdname); + priv->dchan_rx_counter = priv->dchan_tx_counter = priv->dchan_rx_drops = 0; + priv->dchan_alive = 0; + priv->dchan_alive_ticks = 0; + } +} + +static void xpd_activation(xpd_t *xpd, bool on) +{ + struct BRI_priv_data *priv; + xbus_t *xbus; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + xbus = xpd->xbus; + DBG("%s/%s: %s\n", xbus->busname, xpd->xpdname, (on)?"ON":"OFF"); + switch(xpd->type) { + case XPD_TYPE_BRI_TE: + if(on) { + DBG("%s/%s: HFC_L1_ACTIVATE_TE\n", xbus->busname, xpd->xpdname); + set_bit(HFC_L1_ACTIVATING, &priv->l1_flags); + write_state_register(xpd, STA_ACTIVATE); + priv->t3 = HFC_TIMER_T3; + } else { + DBG("%s/%s: HFC_L1_FORCE_DEACTIVATE_TE\n", xbus->busname, xpd->xpdname); + write_state_register(xpd, STA_DEACTIVATE); + } + break; + case XPD_TYPE_BRI_NT: + if(on) { + DBG("%s/%s: HFC_L1_ACTIVATE_NT\n", xbus->busname, xpd->xpdname); + priv->t1 = TIMER_T1_MAX; + set_bit(HFC_L1_ACTIVATING, &priv->l1_flags); + write_state_register(xpd, STA_ACTIVATE | V_SU_SET_G2_G3); + } else { + DBG("%s/%s: HFC_L1_DEACTIVATE_NT\n", xbus->busname, xpd->xpdname); + write_state_register(xpd, STA_DEACTIVATE); + } + break; + default: + ERR("%s: %s/%s: Bad xpd type %d\n", __FUNCTION__, + xbus->busname, xpd->xpdname, xpd->type); + BUG(); + } +} + + /* * D-Chan receive */ @@ -371,6 +447,8 @@ static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd) */ dchan->bytes2receive = idx - 1; dchan->eofrx = 1; + priv->dchan_rx_counter++; + priv->dchan_norx_ticks = 0; drop: priv->dchan_r_idx = 0; out: @@ -441,7 +519,7 @@ static int tx_dchan(xpd_t *xpd) DBG("%s/%s: T3 expired\n", xpd->xbus->busname, xpd->xpdname); priv->t3 = HFC_TIMER_OFF; clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); - CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 0); /* Deactivate TE */ + xpd_activation(xpd, 0); /* Deactivate TE */ } } if (priv->t4 > HFC_TIMER_OFF) { @@ -470,7 +548,8 @@ static int tx_dchan(xpd_t *xpd) return -EINVAL; } if(!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags) && !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) { - CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 1); /* Kick transmitter */ + DBG("%s/%s: Kick D-Channel transmiter\n", xpd->xbus->busname, xpd->xpdname); + xpd_activation(xpd, 1); return 0; } if(print_dbg) @@ -483,6 +562,8 @@ static int tx_dchan(xpd_t *xpd) if(ret < 0) NOTICE("%s/%s: %s: failed sending xframe\n", __FUNCTION__, xpd->xbus->busname, xpd->xpdname); + priv->dchan_tx_counter++; + priv->dchan_notx_ticks = 0; return ret; } @@ -552,6 +633,7 @@ static int BRI_card_init(xbus_t *xbus, xpd_t *xpd) priv->regfile->read_proc = proc_xpd_register_read; priv->regfile->data = xpd; #endif + priv->t1 = HFC_TIMER_OFF; ret = run_initialize_registers(xpd); if(ret < 0) goto err; @@ -562,9 +644,6 @@ static int BRI_card_init(xbus_t *xbus, xpd_t *xpd) CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_HOST, 0); DBG("done: %s/%s\n", xbus->busname, xpd->xpdname); priv->initialized = 1; - CALL_PROTO(BRI, SET_LED, xbus, xpd, GREEN_LED, BRI_LED_ON); - CALL_PROTO(BRI, SET_LED, xbus, xpd, RED_LED, BRI_LED_ON); - msleep(10); return 0; err: clean_proc(xbus, xpd); @@ -644,9 +723,6 @@ static int BRI_card_zaptel_postregistration(xpd_t *xpd, bool on) priv = xpd->priv; BUG_ON(!xbus); DBG("%s/%s: %s\n", xbus->busname, xpd->xpdname, (on)?"on":"off"); - msleep(10); - CALL_PROTO(BRI, SET_LED, xbus, xpd, GREEN_LED, BRI_LED_OFF); - CALL_PROTO(BRI, SET_LED, xbus, xpd, RED_LED, BRI_LED_OFF); return(0); } @@ -656,6 +732,79 @@ int BRI_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig) return 0; } +/* + * LED managment is done by the driver now: + * - Turn constant ON RED/GREEN led to indicate NT/TE port + * - Very fast "Double Blink" to indicate Layer1 alive (without D-Channel) + * - Constant blink (1/2 sec cycle) to indicate D-Channel alive. + */ +static void handle_leds(xbus_t *xbus, xpd_t *xpd) +{ + struct BRI_priv_data *priv; + unsigned int timer_count; + int which_led; + int other_led; + enum led_state ledstate; + int mod; + + BUG_ON(!xpd); + if(xpd->type == XPD_TYPE_BRI_TE) { + which_led = GREEN_LED; + other_led = RED_LED; + } else { + which_led = RED_LED; + other_led = GREEN_LED; + } + priv = xpd->priv; + BUG_ON(!priv); + ledstate = priv->ledstate[which_led]; + timer_count = xpd->timer_count; + if((timer_count % DEFAULT_LED_PERIOD) == 0) { + if(xpd->blink_mode) { + // led state is toggled + if(ledstate == BRI_LED_OFF) { + CALL_PROTO(BRI, SET_LED, xbus, xpd, which_led, BRI_LED_ON); + CALL_PROTO(BRI, SET_LED, xbus, xpd, other_led, BRI_LED_ON); + } else { + CALL_PROTO(BRI, SET_LED, xbus, xpd, which_led, BRI_LED_OFF); + CALL_PROTO(BRI, SET_LED, xbus, xpd, other_led, BRI_LED_OFF); + } + return; + } else if(priv->ledstate[other_led] == BRI_LED_ON) /* cleanup after blink */ + CALL_PROTO(BRI, SET_LED, xbus, xpd, other_led, BRI_LED_OFF); + } + if(priv->dchan_alive) { + mod = timer_count % 1000; + switch(mod) { + case 0: + if(ledstate == BRI_LED_OFF) + CALL_PROTO(BRI, SET_LED, xbus, xpd, which_led, BRI_LED_ON); + break; + case 500: + if(ledstate == BRI_LED_ON) + CALL_PROTO(BRI, SET_LED, xbus, xpd, which_led, BRI_LED_OFF); + break; + } + } else if(priv->layer1_up) { + mod = timer_count % 1000; + switch(mod) { + case 0: + case 100: + if(ledstate == BRI_LED_OFF) + CALL_PROTO(BRI, SET_LED, xbus, xpd, which_led, BRI_LED_ON); + break; + case 50: + case 150: + if(ledstate == BRI_LED_ON) + CALL_PROTO(BRI, SET_LED, xbus, xpd, which_led, BRI_LED_OFF); + break; + } + } else { + if(priv->ledstate[which_led] != BRI_LED_ON) + CALL_PROTO(BRI, SET_LED, xbus, xpd, which_led, BRI_LED_ON); + } +} + /* Poll the register ST/Up-State-machine Register, to see if the cable * if a cable is connected to the port. */ @@ -673,29 +822,49 @@ static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd) priv->poll_counter++; CALL_PROTO(BRI, REGISTER_REQUEST, xbus, xpd, 0, 0, 0, A_SU_RD_STA, 0, 0, 0); } - if((priv->tick_counter % LED_TICKS) == 0) { - int i; - - if(priv->reg30_good && priv->reg30_ticks > poll_interval * REG30_LOST) { - /* No reply for 1/2 a second */ - ERR("%s/%s: Lost state tracking for %d ticks\n", - xbus->busname, xpd->xpdname, priv->reg30_ticks); - priv->reg30_good = 0; - } - if(!priv->reg30_good) { - priv->ledcontrol[RED_LED] = BRI_LED_OFF; - priv->ledcontrol[GREEN_LED] = BRI_LED_OFF; - } - for(i = 0; i < NUM_LEDS; i++) { - if(xpd->blink_mode) { - CALL_PROTO(BRI, SET_LED, xbus, xpd, i, BRI_LED_BLINK_FAST); - } else if(priv->ledstate[i] != priv->ledcontrol[i]) { - CALL_PROTO(BRI, SET_LED, xbus, xpd, i, - priv->ledcontrol[i]); + /* Detect D-Channel disconnect heuristic */ + priv->dchan_notx_ticks++; + priv->dchan_norx_ticks++; + priv->dchan_alive_ticks++; + if(priv->dchan_alive && (priv->dchan_notx_ticks > DCHAN_LOST || priv->dchan_norx_ticks > DCHAN_LOST)) { + /* + * No tx_dchan() or rx_dchan() for many ticks + * This D-Channel is probabelly dead. + */ + dchan_state(xpd, 0); + } else if(priv->dchan_rx_counter > 1 && priv->dchan_tx_counter > 1) { + if(!priv->dchan_alive) + dchan_state(xpd, 1); + } + /* Detect Layer1 disconnect */ + if(priv->reg30_good && priv->reg30_ticks > poll_interval * REG30_LOST) { + /* No reply for 1/2 a second */ + ERR("%s/%s: Lost state tracking for %d ticks\n", + xbus->busname, xpd->xpdname, priv->reg30_ticks); + priv->reg30_good = 0; + layer1_state(xpd, 0); + dchan_state(xpd, 0); + } + handle_leds(xbus, xpd); + tx_dchan(xpd); +#if 0 + /* + Currently not used -- do we want to shut down NT if it wasn't + responding? For how long? + */ + + /* Detect T1 timer expiry on NT */ + if(xpd->type == XPD_TYPE_BRI_NT) { + if (priv->t1 > HFC_TIMER_OFF) { + if (--priv->t1 == 0) { + DBG("%s/%s: T1 Expired. Kick NT\n", xbus->busname, xpd->xpdname); + priv->t1 = HFC_TIMER_OFF; + clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); + write_state_register(xpd, STA_DEACTIVATE); } } } - tx_dchan(xpd); +#endif priv->tick_counter++; priv->reg30_ticks++; return 0; @@ -723,7 +892,7 @@ static int BRI_span_startup(xpd_t *xpd) BUG_ON(!priv); DBG("%s/%s: STARTUP\n", xpd->xbus->busname, xpd->xpdname); write_state_register(xpd, 0); /* Enable L1 state machine */ - CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 1); + xpd_activation(xpd, 1); if(SPAN_REGISTERED(xpd)) { dchan = &xpd->span.chans[2]; xpd->span.flags |= ZT_FLAG_RUNNING; @@ -748,7 +917,7 @@ static int BRI_span_shutdown(xpd_t *xpd) BUG_ON(!priv); DBG("%s/%s: SHUTDOWN\n", xpd->xbus->busname, xpd->xpdname); if(xpd->type == XPD_TYPE_BRI_NT) - CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 0); + xpd_activation(xpd, 0); return 0; } @@ -788,39 +957,9 @@ static int BRI_span_shutdown(xpd_t *xpd) /* 0x0F */ HOSTCMD(BRI, XPD_STATE, bool on) { - struct BRI_priv_data *priv; - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); DBG("%s/%s: %s\n", xbus->busname, xpd->xpdname, (on)?"ON":"OFF"); - switch(xpd->type) { - case XPD_TYPE_BRI_TE: - if(on) { - DBG("%s/%s: HFC_L1_ACTIVATE_TE\n", xbus->busname, xpd->xpdname); - set_bit(HFC_L1_ACTIVATING, &priv->l1_flags); - write_state_register(xpd, STA_ACTIVATE); - priv->t3 = HFC_TIMER_T3; - } else { - DBG("%s/%s: HFC_L1_FORCE_DEACTIVATE_TE\n", xbus->busname, xpd->xpdname); - write_state_register(xpd, STA_DEACTIVATE); - } - break; - case XPD_TYPE_BRI_NT: - if(on) { - DBG("%s/%s: HFC_L1_ACTIVATE_NT\n", xbus->busname, xpd->xpdname); - set_bit(HFC_L1_ACTIVATING, &priv->l1_flags); - write_state_register(xpd, STA_ACTIVATE | V_SU_SET_G2_G3); - } else { - DBG("%s/%s: HFC_L1_DEACTIVATE_NT\n", xbus->busname, xpd->xpdname); - write_state_register(xpd, STA_DEACTIVATE); - } - break; - default: - ERR("%s: %s/%s: Bad xpd type %d\n", __FUNCTION__, - xbus->busname, xpd->xpdname, xpd->type); - return -EINVAL; - } + xpd_activation(xpd, on); return 0; } @@ -849,11 +988,6 @@ static int BRI_span_shutdown(xpd_t *xpd) priv = xpd->priv; BUG_ON(!priv); XFRAME_NEW(xframe, pack, xbus, BRI, SET_LED, xpd->id); -#if 1 - DBG("%s/%s: %s %s (%d)\n", xbus->busname, xpd->xpdname, - (red_led)?"RED":"GREEN", - led_state_names[to_led_state], to_led_state); -#endif bri_leds = &RPACKET_FIELD(pack, BRI, SET_LED, bri_leds); bri_leds->state = to_led_state; bri_leds->led_sel = which_led; @@ -880,28 +1014,39 @@ static int write_state_register(xpd_t *xpd, byte value) return ret; } - /*---------------- BRI: Astribank Reply Handlers --------------------------*/ static void su_new_state(xpd_t *xpd, byte reg_x30) { xbus_t *xbus; struct BRI_priv_data *priv; su_rd_sta_t new_state; - int which_led = (xpd->type == XPD_TYPE_BRI_TE) ? GREEN_LED : RED_LED; BUG_ON(!xpd); priv = xpd->priv; BUG_ON(!priv); xbus = xpd->xbus; + if(!priv->initialized) { + ERR("%s/%s: %s called on uninitialized AB\n", + xbus->busname, xpd->xpdname, __FUNCTION__); + return; + } new_state.reg = reg_x30; priv->reg30_ticks = 0; priv->reg30_good = 1; if((xpd->type == XPD_TYPE_BRI_TE && new_state.bits.v_su_sta == ST_TE_ACTIVATED) || (xpd->type == XPD_TYPE_BRI_NT && new_state.bits.v_su_sta == ST_NT_ACTIVATED)) { - priv->ledcontrol[which_led] = (new_state.bits.v_su_fr_sync) ? BRI_LED_BLINK_SLOW : BRI_LED_BLINK_FAST; - update_xpd_status(xpd, ZT_ALARM_NONE); + if(!priv->layer1_up) { + layer1_state(xpd, 1); + update_xpd_status(xpd, ZT_ALARM_NONE); + } } else { - priv->ledcontrol[which_led] = BRI_LED_OFF; + /* + * Layer 1 disconnected + */ + if(priv->layer1_up) { + layer1_state(xpd, 0); + dchan_state(xpd, 0); + } /* * Do NOT notify Zaptel about the disconnection. * If we do, Asterisk stops transmitting on the D-channel and @@ -917,7 +1062,7 @@ static void su_new_state(xpd_t *xpd, byte reg_x30) if (priv->state_register.bits.v_su_sta == new_state.bits.v_su_sta) return; /* same same */ DBG("%02X ---> %02X\n", priv->state_register.reg, reg_x30); - DBG("%s/%s: %s%i\n", xpd->xbus->busname, xpd->xpdname, + DBG("%s/%s: %s%i\n", xbus->busname, xpd->xpdname, (xpd->type == XPD_TYPE_BRI_NT)?"G":"F", new_state.bits.v_su_sta); @@ -965,18 +1110,21 @@ static void su_new_state(xpd_t *xpd, byte reg_x30) case ST_NT_DEACTIVATED: /* G1 */ DBG("%s/%s: State ST_NT_DEACTIVATED (G1)\n", xbus->busname, xpd->xpdname); clear_bit(HFC_L1_ACTIVATED, &priv->l1_flags); + priv->t1 = HFC_TIMER_OFF; break; case ST_NT_ACTIVATING: /* G2 */ DBG("%s/%s: State ST_NT_ACTIVATING (G2)\n", xbus->busname, xpd->xpdname); - write_state_register(xpd, V_SU_SET_G2_G3); /* Enable transition to G3 */ + xpd_activation(xpd, 1); break; case ST_NT_ACTIVATED: /* G3 */ DBG("%s/%s: State ST_NT_ACTIVATED (G3)\n", xbus->busname, xpd->xpdname); clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); set_bit(HFC_L1_ACTIVATED, &priv->l1_flags); + priv->t1 = HFC_TIMER_OFF; break; case ST_NT_DEACTIVTING: /* G4 */ DBG("%s/%s: State ST_NT_DEACTIVTING (G4)\n", xbus->busname, xpd->xpdname); + priv->t1 = HFC_TIMER_OFF; break; default: NOTICE("%s/%s: Bad NT state: %d\n", xbus->busname, xpd->xpdname, new_state.bits.v_su_sta); @@ -1021,7 +1169,7 @@ HANDLER_DEF(BRI, REGISTER_REPLY) #endif ret = rx_dchan(xpd, info); if (ret < 0) { - priv->drop_counter++; + priv->dchan_rx_drops++; if(atomic_read(&xpd->open_counter) > 0) NOTICE("%s/%s: Multibyte Drop: errno=%d\n", xbus->busname, xpd->xpdname, ret); } @@ -1129,8 +1277,9 @@ static int proc_bri_info_read(char *page, char **start, off_t off, int count, in spin_lock_irqsave(&xpd->lock, flags); priv = xpd->priv; BUG_ON(!priv); - len += sprintf(page + len, "%05d Layer 1 State: ", priv->poll_counter); + len += sprintf(page + len, "%05d Layer 1: ", priv->poll_counter); if(priv->reg30_good) { + len += sprintf(page + len, "%-5s ", (priv->layer1_up) ? "UP" : "DOWN"); len += sprintf(page + len, "%c%d %-15s -- fr_sync=%d t2_exp=%d info0=%d g2_g3=%d\n", (xpd->type == XPD_TYPE_BRI_NT)?'G':'F', priv->state_register.bits.v_su_sta, @@ -1141,14 +1290,20 @@ static int proc_bri_info_read(char *page, char **start, off_t off, int count, in priv->state_register.bits.v_g2_g3); } else len += sprintf(page + len, "Unkown\n"); + if(xpd->type == XPD_TYPE_BRI_NT) + len += sprintf(page + len, "T1 Timer: %d\n", priv->t1); len += sprintf(page + len, "Tick Counter: %d\n", priv->tick_counter); len += sprintf(page + len, "Last Poll Reply: %d ticks ago\n", priv->reg30_ticks); len += sprintf(page + len, "reg30_good=%d\n", priv->reg30_good); - len += sprintf(page + len, "Drop Counter: %d\n", priv->drop_counter); + len += sprintf(page + len, "D-Channel: TX=[%5d] RX=[%5d] BAD=[%5d] (%s)\n\n", + priv->dchan_tx_counter, priv->dchan_rx_counter, priv->dchan_rx_drops, + (priv->dchan_alive) ? "alive" : "dead"); + len += sprintf(page + len, "dchan_alive_ticks: %d\n", priv->dchan_alive_ticks); + len += sprintf(page + len, "dchan_notx_ticks: %d\n", priv->dchan_notx_ticks); + len += sprintf(page + len, "dchan_norx_ticks: %d\n", priv->dchan_norx_ticks); for(led = 0; led < NUM_LEDS; led++) { len += sprintf(page + len, "LED #%d\n", led); len += sprintf(page + len, "\tledstate : %d\n", priv->ledstate[led]); - len += sprintf(page + len, "\tledcontrol: %d\n", priv->ledcontrol[led]); } len += sprintf(page + len, "\nDCHAN:\n"); len += sprintf(page + len, "\n"); |