diff options
Diffstat (limited to 'kernel/xpp/card_bri.c')
-rw-r--r-- | kernel/xpp/card_bri.c | 824 |
1 files changed, 300 insertions, 524 deletions
diff --git a/kernel/xpp/card_bri.c b/kernel/xpp/card_bri.c index c2be201..086dbea 100644 --- a/kernel/xpp/card_bri.c +++ b/kernel/xpp/card_bri.c @@ -31,7 +31,6 @@ #include "xpp_zap.h" #include "card_bri.h" #include "zap_debug.h" -#include "xpd.h" #include "xbus-core.h" static const char rcsid[] = "$Id$"; @@ -40,9 +39,9 @@ static const char rcsid[] = "$Id$"; #error CONFIG_ZAPATA_BRI_DCHANS is not defined #endif -DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); /* must be before zap_debug.h */ -DEF_PARM(uint, poll_interval, 500, 0644, "Poll channel state interval in milliseconds (0 - disable)"); -DEF_PARM_BOOL(nt_keepalive, 1, 0644, "Force BRI_NT to keep trying connection"); +static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); /* must be before zap_debug.h */ +static DEF_PARM(uint, poll_interval, 500, 0644, "Poll channel state interval in milliseconds (0 - disable)"); +static DEF_PARM_BOOL(nt_keepalive, 1, 0644, "Force BRI_NT to keep trying connection"); enum xhfc_states { ST_RESET = 0, /* G/F0 */ @@ -61,7 +60,7 @@ enum xhfc_states { ST_NT_DEACTIVTING = 4, /* G4 */ }; -static const char *xhfc_state_name(xpd_type_t xpd_type, enum xhfc_states state) +static const char *xhfc_state_name(bool is_nt, enum xhfc_states state) { const char *p; @@ -84,16 +83,16 @@ static const char *xhfc_state_name(xpd_type_t xpd_type, enum xhfc_states state) _E(NT_DEACTIVTING), }; #undef _E - if(xpd_type == XPD_TYPE_BRI_TE) { - if ((state < ST_RESET) || (state > ST_TE_LOST_FRAMING)) - p = "TE ???"; - else - p = te_names[state]; - } else { + if(is_nt) { if ((state < ST_RESET) || (state > ST_NT_DEACTIVTING)) p = "NT ???"; else p = nt_names[state]; + } else { + if ((state < ST_RESET) || (state > ST_TE_LOST_FRAMING)) + p = "TE ???"; + else + p = te_names[state]; } return p; } @@ -106,9 +105,8 @@ 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 TIMER_T1_MAX 2500 +#define HFC_TIMER_T1 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 */ #define A_SU_WR_STA 0x30 /* ST/Up state machine register */ @@ -145,9 +143,10 @@ typedef union { ZT_SIG_CAS | \ ZT_SIG_SF \ ) -#define BRI_BCHAN_SIGCAP ZT_SIG_CLEAR +#define BRI_BCHAN_SIGCAP (ZT_SIG_CLEAR | ZT_SIG_DACS) -#define IS_NT(xpd) ((xpd)->type == XPD_TYPE_BRI_NT) +#define IS_NT(xpd) ((xpd)->direction == TO_PHONE) +#define BRI_PORT(xpd) ((xpd)->addr.subunit) /* shift in PCM highway */ #define SUBUNIT_PCM_SHIFT 4 @@ -159,8 +158,6 @@ static int write_state_register(xpd_t *xpd, byte value); static bool bri_packet_is_valid(xpacket_t *pack); static void bri_packet_dump(const char *msg, xpacket_t *pack); static int proc_bri_info_read(char *page, char **start, off_t off, int count, int *eof, void *data); -static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data); -static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data); static int bri_spanconfig(struct zt_span *span, struct zt_lineconfig *lc); static int bri_chanconfig(struct zt_chan *chan, int sigtype); static int bri_startup(struct zt_span *span); @@ -169,8 +166,6 @@ static int bri_shutdown(struct zt_span *span); #define PROC_REGISTER_FNAME "slics" #define PROC_BRI_INFO_FNAME "bri_info" -#define VALID_CHIPSEL(x) ((x) == 0) - enum led_state { BRI_LED_OFF = 0x0, BRI_LED_ON = 0x1, @@ -204,13 +199,11 @@ struct bri_leds { #define DCHAN_BUFSIZE MAX_DFRAME_LEN_L1 struct BRI_priv_data { - struct proc_dir_entry *regfile; 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 */ + int t1; /* timer 1 for NT deactivation */ + int t3; /* timer 3 for TE activation */ ulong l1_flags; bool reg30_good; uint reg30_ticks; @@ -225,8 +218,6 @@ struct BRI_priv_data { byte dchan_tbuf[DCHAN_BUFSIZE]; bool txframe_begin; - reg_cmd_t requested_reply; - reg_cmd_t last_reply; uint tick_counter; uint poll_counter; uint dchan_tx_counter; @@ -239,8 +230,7 @@ struct BRI_priv_data { enum led_state ledstate[NUM_LEDS]; }; -static xproto_table_t PROTO_TABLE(BRI_NT); -static xproto_table_t PROTO_TABLE(BRI_TE); +static xproto_table_t PROTO_TABLE(BRI); DEF_RPACKET_DATA(BRI, SET_LED, /* Set one of the LED's */ @@ -300,17 +290,13 @@ 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) +static void set_bri_timer(xpd_t *xpd, const char *name, int *bri_timer, int value) { - struct BRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - if(priv->layer1_up == up) - return; - priv->layer1_up = up; - XPD_DBG(SIGNAL, xpd, "STATE CHANGE: Layer1 %s\n", (up)?"UP":"DOWN"); + if(value == HFC_TIMER_OFF) + XPD_DBG(SIGNAL, xpd, "Timer %s DISABLE\n", name); + else + XPD_DBG(SIGNAL, xpd, "Timer %s: set to %d\n", name, value); + *bri_timer = value; } static void dchan_state(xpd_t *xpd, bool up) @@ -333,42 +319,113 @@ static void dchan_state(xpd_t *xpd, bool up) } } -static void xpd_activation(xpd_t *xpd, bool on) +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; + XPD_DBG(SIGNAL, xpd, "STATE CHANGE: Layer1 %s\n", (up)?"UP":"DOWN"); + if(!up) + dchan_state(xpd, 0); +} + +static void te_activation(xpd_t *xpd, bool on) { struct BRI_priv_data *priv; xbus_t *xbus; + byte curr_state; BUG_ON(!xpd); priv = xpd->priv; BUG_ON(!priv); + curr_state = priv->state_register.bits.v_su_sta; xbus = xpd->xbus; XPD_DBG(SIGNAL, xpd, "%s\n", (on)?"ON":"OFF"); - switch(xpd->type) { - case XPD_TYPE_BRI_TE: - if(on) { - XPD_DBG(SIGNAL, xpd, "HFC_L1_ACTIVATE_TE\n"); - set_bit(HFC_L1_ACTIVATING, &priv->l1_flags); - write_state_register(xpd, STA_ACTIVATE); - priv->t3 = HFC_TIMER_T3; - } else { + if(on) { + if(curr_state == ST_TE_DEACTIVATED) { + XPD_DBG(SIGNAL, xpd, "HFC_L1_ACTIVATE_TE\n"); + set_bit(HFC_L1_ACTIVATING, &priv->l1_flags); + write_state_register(xpd, STA_ACTIVATE); + set_bri_timer(xpd, "T3", &priv->t3, HFC_TIMER_T3); + } else { + XPD_DBG(SIGNAL, xpd, + "HFC_L1_ACTIVATE_TE (state %d, ignored)\n", + curr_state); + } + } else { /* happen only because of T3 expiry */ + switch (curr_state) { + case ST_TE_DEACTIVATED: /* F3 */ + case ST_TE_SYNCED: /* F6 */ + case ST_TE_ACTIVATED: /* F7 */ + XPD_DBG(SIGNAL, xpd, + "HFC_L1_FORCE_DEACTIVATE_TE (state %d, ignored)\n", + curr_state); + break; + case ST_TE_SIGWAIT: /* F4 */ + case ST_TE_IDENT: /* F5 */ + case ST_TE_LOST_FRAMING: /* F8 */ XPD_DBG(SIGNAL, xpd, "HFC_L1_FORCE_DEACTIVATE_TE\n"); write_state_register(xpd, STA_DEACTIVATE); - } - break; - case XPD_TYPE_BRI_NT: - if(on) { + break; + default: + XPD_NOTICE(xpd, "Bad TE state: %d\n", curr_state); + break; + } + } +} + +static void nt_activation(xpd_t *xpd, bool on) +{ + struct BRI_priv_data *priv; + xbus_t *xbus; + byte curr_state; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + curr_state = priv->state_register.bits.v_su_sta; + xbus = xpd->xbus; + XPD_DBG(SIGNAL, xpd, "%s\n", (on)?"ON":"OFF"); + if(on) { + switch(curr_state) { + case ST_RESET: /* F/G 0 */ + case ST_NT_DEACTIVATED: /* G1 */ + case ST_NT_DEACTIVTING: /* G4 */ XPD_DBG(SIGNAL, xpd, "HFC_L1_ACTIVATE_NT\n"); - priv->t1 = TIMER_T1_MAX; + set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_T1); set_bit(HFC_L1_ACTIVATING, &priv->l1_flags); - write_state_register(xpd, STA_ACTIVATE | V_SU_SET_G2_G3); - } else { + write_state_register(xpd, STA_ACTIVATE); + break; + case ST_NT_ACTIVATING: /* G2 */ + case ST_NT_ACTIVATED: /* G3 */ + XPD_DBG(SIGNAL, xpd, + "HFC_L1_ACTIVATE_NT (in state %d, ignored)\n", + curr_state); + break; + } + } else { + switch(curr_state) { + case ST_RESET: /* F/G 0 */ + case ST_NT_DEACTIVATED: /* G1 */ + case ST_NT_DEACTIVTING: /* G4 */ + XPD_DBG(SIGNAL, xpd, + "HFC_L1_DEACTIVATE_NT (in state %d, ignored)\n", + curr_state); + break; + case ST_NT_ACTIVATING: /* G2 */ + case ST_NT_ACTIVATED: /* G3 */ XPD_DBG(SIGNAL, xpd, "HFC_L1_DEACTIVATE_NT\n"); write_state_register(xpd, STA_DEACTIVATE); - } - break; - default: - XPD_ERR(xpd, "%s: Bad xpd type %d\n", __FUNCTION__, xpd->type); - BUG(); + break; + default: + XPD_NOTICE(xpd, "Bad NT state: %d\n", curr_state); + break; + } } } @@ -445,7 +502,7 @@ static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd) ret = -EPROTO; goto drop; } - if(print_dbg) + if(debug) dump_dchan_packet(xpd, 0, dchan_buf, idx /* - 3 */); /* Print checksum? */ /* * Tell Zaptel that we received idx-1 bytes. They include the data and a 2-byte checksum. @@ -462,47 +519,6 @@ out: return ret; } -static int send_bri_multibyte(xpd_t *xpd, byte *buf, int len, bool eoftx) -{ - xbus_t *xbus = xpd->xbus; - xframe_t *xframe; - xpacket_t *pack; - reg_cmd_t *reg_cmd; - int ret; - - BUG_ON(len < 0); - /* - * Zero length multibyte is legal and has special meaning for the - * firmware: - * eoftx==1: Start sending us D-channel packets. - * eoftx==0: Stop sending us D-channel packets. - */ - if(len > MULTIBYTE_MAX_LEN) { - XPD_ERR(xpd, "%s: len=%d is too long. dropping.\n", __FUNCTION__, len); - return -EINVAL; - } - XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx); - reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd); - reg_cmd->bytes = len; - reg_cmd->eoframe = eoftx; - reg_cmd->multibyte = 1; - if(len > 0) { - memcpy(REG_XDATA(reg_cmd), (byte *)buf, len); - } else { - XPD_DBG(REGS, xpd, "Magic Packet (eoftx=%d)\n", eoftx); - } -#ifdef XPP_DEBUGFS - xbus_log(xbus, xpd, 1, reg_cmd, sizeof(reg_cmd_t)); /* 1 = TX */ -#else - if(print_dbg) - dump_xframe("SEND_BRI_MULTI", xbus, xframe, print_dbg); -#endif - ret = send_cmd_frame(xbus, xframe); - if(ret < 0) - XPD_NOTICE(xpd, "%s: failed sending xframe\n", __FUNCTION__); - return ret; -} - /* * D-Chan transmit */ @@ -516,29 +532,6 @@ static int tx_dchan(xpd_t *xpd) priv = xpd->priv; BUG_ON(!priv); - if(!IS_NT(xpd)) { - static int rate_limit; - - if (priv->t3 > HFC_TIMER_OFF) { - /* timer expired ? */ - if (--priv->t3 == 0) { - if ((rate_limit % 1003) >= 5) - XPD_DBG(SIGNAL, xpd, "T3 expired\n"); - priv->t3 = HFC_TIMER_OFF; - clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); - xpd_activation(xpd, 0); /* Deactivate TE */ - } - } - if (priv->t4 > HFC_TIMER_OFF) { - /* timer expired ? */ - if (--priv->t4 == 0) { - if ((rate_limit % 1003) >= 5) - XPD_DBG(SIGNAL, xpd, "T4 expired\n"); - priv->t4 = HFC_TIMER_OFF; - } - } - rate_limit++; - } if(!SPAN_REGISTERED(xpd) || !(xpd->span.flags & ZT_FLAG_RUNNING)) return 0; dchan = &xpd->chans[2]; @@ -556,16 +549,20 @@ static int tx_dchan(xpd_t *xpd) } if(!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags) && !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) { XPD_DBG(SIGNAL, xpd, "Want to transmit: Kick D-Channel transmiter\n"); - xpd_activation(xpd, 1); + if(xpd->direction == TO_PSTN) + te_activation(xpd, 1); + else + nt_activation(xpd, 1); return 0; } - if(print_dbg) + if(debug) dump_dchan_packet(xpd, 1, priv->dchan_tbuf, len); if(eoframe) priv->txframe_begin = 1; else priv->txframe_begin = 0; - ret = send_bri_multibyte(xpd, priv->dchan_tbuf, len, eoframe); + ret = send_multibyte_request(xpd->xbus, xpd->addr.unit, xpd->addr.subunit, + eoframe, priv->dchan_tbuf, len); if(ret < 0) XPD_NOTICE(xpd, "%s: failed sending xframe\n", __FUNCTION__); if(eoframe) @@ -576,22 +573,7 @@ static int tx_dchan(xpd_t *xpd) /*---------------- BRI: Methods -------------------------------------------*/ -static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, byte revision) -{ - xpd_t *xpd = NULL; - int channels = min(3, CHANNELS_PERXPD); - - XBUS_DBG(GENERAL, xbus, "\n"); - xpd = xpd_alloc(sizeof(struct BRI_priv_data), proto_table, channels); - if(!xpd) - return NULL; - xpd->direction = (proto_table == &PROTO_TABLE(BRI_NT)) ? TO_PHONE : TO_PSTN; - xpd->revision = revision; - xpd->type_name = proto_table->name; - return xpd; -} - -static void clean_proc(xbus_t *xbus, xpd_t *xpd) +static void bri_proc_remove(xbus_t *xbus, xpd_t *xpd) { struct BRI_priv_data *priv; @@ -599,57 +581,67 @@ static void clean_proc(xbus_t *xbus, xpd_t *xpd) priv = xpd->priv; XPD_DBG(PROC, xpd, "\n"); #ifdef CONFIG_PROC_FS - if(priv->regfile) { - XPD_DBG(PROC, xpd, "Removing registers file\n"); - priv->regfile->data = NULL; - remove_proc_entry(PROC_REGISTER_FNAME, xpd->proc_xpd_dir); - } if(priv->bri_info) { - XPD_DBG(PROC, xpd, "Removing xpd BRI_INFO file\n"); + XPD_DBG(PROC, xpd, "Removing '%s'\n", PROC_BRI_INFO_FNAME); remove_proc_entry(PROC_BRI_INFO_FNAME, xpd->proc_xpd_dir); } #endif } -static int BRI_card_init(xbus_t *xbus, xpd_t *xpd) +static int bri_proc_create(xbus_t *xbus, xpd_t *xpd) { struct BRI_priv_data *priv; - int ret = 0; BUG_ON(!xpd); - XPD_DBG(GENERAL, xpd, "\n"); priv = xpd->priv; + XPD_DBG(PROC, xpd, "\n"); #ifdef CONFIG_PROC_FS - XPD_DBG(PROC, xpd, "Creating BRI_INFO file\n"); + XPD_DBG(PROC, xpd, "Creating '%s'\n", PROC_BRI_INFO_FNAME); priv->bri_info = create_proc_read_entry(PROC_BRI_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_bri_info_read, xpd); if(!priv->bri_info) { XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_BRI_INFO_FNAME); - ret = -ENOENT; goto err; } priv->bri_info->owner = THIS_MODULE; - XPD_DBG(PROC, xpd, "Creating registers file\n"); - priv->regfile = create_proc_entry(PROC_REGISTER_FNAME, 0644, xpd->proc_xpd_dir); - if(!priv->regfile) { - XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_REGISTER_FNAME); - goto err; - } - priv->regfile->owner = THIS_MODULE; - priv->regfile->write_proc = proc_xpd_register_write; - 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) + return 0; +err: + bri_proc_remove(xbus, xpd); + return -EINVAL; +} + +static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, int subunits, bool to_phone) +{ + xpd_t *xpd = NULL; + int channels = min(3, CHANNELS_PERXPD); + + XBUS_DBG(GENERAL, xbus, "\n"); + xpd = xpd_alloc(sizeof(struct BRI_priv_data), proto_table, channels); + if(!xpd) + return NULL; + xpd->direction = (to_phone) ? TO_PHONE : TO_PSTN; + xpd->type_name = (to_phone) ? "BRI_NT" : "BRI_TE"; + if(xpd_common_init(xbus, xpd, unit, subunit, subtype, subunits) < 0) goto err; - XPD_DBG(PROC, xpd, "done\n"); + if(bri_proc_create(xbus, xpd) < 0) + goto err; + return xpd; +err: + xpd_free(xpd); + return NULL; +} + +static int BRI_card_init(xbus_t *xbus, xpd_t *xpd) +{ + struct BRI_priv_data *priv; + + BUG_ON(!xpd); + XPD_DBG(GENERAL, xpd, "\n"); + priv = xpd->priv; + set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF); + write_state_register(xpd, 0); /* Enable L1 state machine */ priv->initialized = 1; return 0; -err: - clean_proc(xbus, xpd); - XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret); - return ret; } static int BRI_card_remove(xbus_t *xbus, xpd_t *xpd) @@ -659,7 +651,7 @@ static int BRI_card_remove(xbus_t *xbus, xpd_t *xpd) BUG_ON(!xpd); priv = xpd->priv; XPD_DBG(GENERAL, xpd, "\n"); - clean_proc(xbus, xpd); + bri_proc_remove(xbus, xpd); return 0; } @@ -692,7 +684,7 @@ static int BRI_card_zaptel_preregistration(xpd_t *xpd, bool on) XPD_DBG(GENERAL, xpd, "setting BRI channel %d\n", i); snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%02d/%1d%1d/%d", - xpd->xproto->name, xbus->num, + xpd->type_name, xbus->num, xpd->addr.unit, xpd->addr.subunit, i); cur_chan->chanpos = i + 1; cur_chan->pvt = xpd; @@ -832,6 +824,42 @@ static void handle_leds(xbus_t *xbus, xpd_t *xpd) } } +static void handle_bri_timers(xpd_t *xpd) +{ + struct BRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(IS_NT(xpd)) { + if (priv->t1 > HFC_TIMER_OFF) { + if (--priv->t1 == 0) { + set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF); + if(!nt_keepalive) { + if(priv->state_register.bits.v_su_sta == ST_NT_ACTIVATING) { /* G2 */ + XPD_DBG(SIGNAL, xpd, "T1 Expired. Deactivate NT\n"); + clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); + nt_activation(xpd, 0); /* Deactivate NT */ + } else + XPD_DBG(SIGNAL, xpd, + "T1 Expired. (state %d, ignored)\n", + priv->state_register.bits.v_su_sta); + } + } + } + } else { + if (priv->t3 > HFC_TIMER_OFF) { + /* timer expired ? */ + if (--priv->t3 == 0) { + XPD_DBG(SIGNAL, xpd, "T3 expired. Deactivate TE\n"); + set_bri_timer(xpd, "T3", &priv->t3, HFC_TIMER_OFF); + clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); + te_activation(xpd, 0); /* Deactivate TE */ + } + } + } +} + /* Poll the register ST/Up-State-machine Register, to see if the cable * if a cable is connected to the port. */ @@ -847,13 +875,23 @@ static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd) if(poll_interval != 0 && (priv->tick_counter % poll_interval) == 0) { // XPD_DBG(GENERAL, xpd, "%d\n", priv->tick_counter); priv->poll_counter++; - xpp_register_request(xbus, xpd, 0, 0, 0, A_SU_RD_STA, 0, 0, 0); + xpp_register_request(xbus, xpd, + BRI_PORT(xpd), /* portno */ + 0, /* writing */ + A_SU_RD_STA, /* regnum */ + 0, /* do_subreg */ + 0, /* subreg */ + 0, /* data_low */ + 0, /* do_datah */ + 0, /* data_high */ + 0 /* should_reply */ + ); if(IS_NT(xpd) && nt_keepalive && !test_bit(HFC_L1_ACTIVATED, &priv->l1_flags) && !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) { XPD_DBG(SIGNAL, xpd, "Kick NT D-Channel\n"); - xpd_activation(xpd, 1); + nt_activation(xpd, 1); } } /* Detect D-Channel disconnect heuristic */ @@ -876,21 +914,10 @@ static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd) XPD_ERR(xpd, "Lost state tracking for %d ticks\n", priv->reg30_ticks); priv->reg30_good = 0; layer1_state(xpd, 0); - dchan_state(xpd, 0); } handle_leds(xbus, xpd); + handle_bri_timers(xpd); tx_dchan(xpd); - /* Detect T1 timer expiry on NT */ - if(IS_NT(xpd) && !nt_keepalive) { - if (priv->t1 > HFC_TIMER_OFF) { - if (--priv->t1 == 0) { - XPD_DBG(SIGNAL, xpd, "T1 Expired. Deactivate NT\n"); - priv->t1 = HFC_TIMER_OFF; - clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); - write_state_register(xpd, STA_DEACTIVATE); - } - } - } priv->tick_counter++; priv->reg30_ticks++; return 0; @@ -1003,8 +1030,6 @@ static int bri_startup(struct zt_span *span) XPD_DBG(GENERAL, xpd, "STARTUP\n"); // Turn on all channels CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 1); - write_state_register(xpd, 0); /* Enable L1 state machine */ - xpd_activation(xpd, 1); if(SPAN_REGISTERED(xpd)) { dchan = &span->chans[2]; span->flags |= ZT_FLAG_RUNNING; @@ -1038,8 +1063,6 @@ static int bri_shutdown(struct zt_span *span) XPD_DBG(GENERAL, xpd, "SHUTDOWN\n"); // Turn off all channels CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 0); - if(IS_NT(xpd)) - xpd_activation(xpd, 0); return 0; } @@ -1134,24 +1157,23 @@ static void BRI_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack) static /* 0x0F */ HOSTCMD(BRI, XPD_STATE, bool on) { + struct BRI_priv_data *priv; + BUG_ON(!xpd); + priv = xpd->priv; XPD_DBG(GENERAL, xpd, "%s\n", (on)?"ON":"OFF"); - xpd_activation(xpd, on); + if(on) { + if(!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)) { + if(xpd->direction == TO_PSTN) + te_activation(xpd, 1); + else + nt_activation(xpd, 1); + } + } else if(IS_NT(xpd)) + nt_activation(xpd, 0); return 0; } -static /* 0x0F */ HOSTCMD(BRI, RING, lineno_t chan, bool on) -{ - XPD_ERR(xpd, "%s: Unsupported\n", __FUNCTION__); - return -ENOSYS; -} - -static /* 0x0F */ HOSTCMD(BRI, RELAY_OUT, byte which, bool on) -{ - XPD_ERR(xpd, "%s: Unsupported\n", __FUNCTION__); - return -ENOSYS; -} - static /* 0x33 */ HOSTCMD(BRI, SET_LED, enum bri_led_names which_led, enum led_state to_led_state) { int ret = 0; @@ -1182,13 +1204,15 @@ static int write_state_register(xpd_t *xpd, byte value) XPD_DBG(REGS, xpd, "value = 0x%02X\n", value); ret = xpp_register_request(xpd->xbus, xpd, - 0, /* chipsel */ + BRI_PORT(xpd), /* portno */ 1, /* writing */ - 0, /* do_subreg */ A_SU_WR_STA, /* regnum */ + 0, /* do_subreg */ 0, /* subreg */ value, /* data_low */ - 0 /* data_high */ + 0, /* do_datah */ + 0, /* data_high */ + 0 /* should_reply */ ); return ret; } @@ -1209,105 +1233,87 @@ static void su_new_state(xpd_t *xpd, byte reg_x30) return; } new_state.reg = reg_x30; + if(new_state.bits.v_su_t2_exp) { + XPD_NOTICE(xpd, "T2 Expired\n"); + } priv->reg30_ticks = 0; priv->reg30_good = 1; - if((!IS_NT(xpd) && new_state.bits.v_su_sta == ST_TE_ACTIVATED) || - (IS_NT(xpd) && new_state.bits.v_su_sta == ST_NT_ACTIVATED)) { - if(!priv->layer1_up) { - layer1_state(xpd, 1); - update_xpd_status(xpd, ZT_ALARM_NONE); - } - } else { - /* - * 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 - * we can't reactivate layer-1. - * Without the notification, Asterisk thinks that we are active - * (although the PSTN stopped layer-1) and on call setup, sends - * us D-channel data, which triggers the layer-1 activation. - */ -#if 0 - update_xpd_status(xpd, ZT_ALARM_RED); -#endif - } if (priv->state_register.bits.v_su_sta == new_state.bits.v_su_sta) return; /* same same */ - DBG(SIGNAL, "%02X ---> %02X\n", priv->state_register.reg, reg_x30); - XPD_DBG(SIGNAL, xpd, "%s%i\n", IS_NT(xpd)?"G":"F", new_state.bits.v_su_sta); - + XPD_DBG(SIGNAL, xpd, "%02X ---> %02X (info0=%d) (%s%i)\n", + priv->state_register.reg, + reg_x30, + new_state.bits.v_su_info0, + IS_NT(xpd)?"G":"F", + new_state.bits.v_su_sta); if(!IS_NT(xpd)) { - /* disable T3 ? */ - if ((new_state.bits.v_su_sta <= ST_TE_DEACTIVATED) || (new_state.bits.v_su_sta >= ST_TE_ACTIVATED)) { - XPD_DBG(SIGNAL, xpd, "Disable T3 ?\n"); - priv->t3 = HFC_TIMER_OFF; - } switch (new_state.bits.v_su_sta) { case ST_TE_DEACTIVATED: /* F3 */ XPD_DBG(SIGNAL, xpd, "State ST_TE_DEACTIVATED (F3)\n"); - if (test_and_clear_bit(HFC_L1_ACTIVATED, &priv->l1_flags)) - priv->t4 = HFC_TIMER_T4; + clear_bit(HFC_L1_ACTIVATED, &priv->l1_flags); + layer1_state(xpd, 0); break; case ST_TE_SIGWAIT: /* F4 */ XPD_DBG(SIGNAL, xpd, "State ST_TE_SIGWAIT (F4)\n"); + layer1_state(xpd, 0); break; case ST_TE_IDENT: /* F5 */ XPD_DBG(SIGNAL, xpd, "State ST_TE_IDENT (F5)\n"); + layer1_state(xpd, 0); break; case ST_TE_SYNCED: /* F6 */ XPD_DBG(SIGNAL, xpd, "State ST_TE_SYNCED (F6)\n"); + layer1_state(xpd, 0); break; case ST_TE_ACTIVATED: /* F7 */ XPD_DBG(SIGNAL, xpd, "State ST_TE_ACTIVATED (F7)\n"); - if (priv->t4 > HFC_TIMER_OFF) - priv->t4 = HFC_TIMER_OFF; + set_bri_timer(xpd, "T3", &priv->t3, HFC_TIMER_OFF); clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); set_bit(HFC_L1_ACTIVATED, &priv->l1_flags); + layer1_state(xpd, 1); update_xpd_status(xpd, ZT_ALARM_NONE); break; - case ST_TE_LOST_FRAMING: /* F8 */ XPD_DBG(SIGNAL, xpd, "State ST_TE_LOST_FRAMING (F8)\n"); - priv->t4 = HFC_TIMER_OFF; + layer1_state(xpd, 0); break; default: XPD_NOTICE(xpd, "Bad TE state: %d\n", new_state.bits.v_su_sta); break; } - } else if(IS_NT(xpd)) { + } else { switch (new_state.bits.v_su_sta) { case ST_NT_DEACTIVATED: /* G1 */ XPD_DBG(SIGNAL, xpd, "State ST_NT_DEACTIVATED (G1)\n"); clear_bit(HFC_L1_ACTIVATED, &priv->l1_flags); - priv->t1 = HFC_TIMER_OFF; + set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF); + layer1_state(xpd, 0); break; case ST_NT_ACTIVATING: /* G2 */ XPD_DBG(SIGNAL, xpd, "State ST_NT_ACTIVATING (G2)\n"); - xpd_activation(xpd, 1); + layer1_state(xpd, 0); + if(!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)) + nt_activation(xpd, 1); break; case ST_NT_ACTIVATED: /* G3 */ XPD_DBG(SIGNAL, xpd, "State ST_NT_ACTIVATED (G3)\n"); clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); set_bit(HFC_L1_ACTIVATED, &priv->l1_flags); - priv->t1 = HFC_TIMER_OFF; + set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF); + layer1_state(xpd, 1); + update_xpd_status(xpd, ZT_ALARM_NONE); break; case ST_NT_DEACTIVTING: /* G4 */ XPD_DBG(SIGNAL, xpd, "State ST_NT_DEACTIVTING (G4)\n"); - priv->t1 = HFC_TIMER_OFF; + set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF); + layer1_state(xpd, 0); break; default: XPD_NOTICE(xpd, "Bad NT state: %d\n", new_state.bits.v_su_sta); break; } - } else - XPD_ERR(xpd, "%s: Unknown xpd type %d\n", __FUNCTION__, xpd->type); + } priv->state_register.reg = new_state.reg; } @@ -1315,20 +1321,37 @@ static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) { unsigned long flags; struct BRI_priv_data *priv; + struct xpd_addr addr; + xpd_t *orig_xpd; int ret; + /* Map UNIT + PORTNUM to XPD */ + orig_xpd = xpd; + addr.unit = orig_xpd->addr.unit; + addr.subunit = info->portnum; + xpd = xpd_byaddr(xbus, addr.unit, addr.subunit); + if(!xpd) { + static int rate_limit; + + if((rate_limit++ % 1003) < 5) + notify_bad_xpd(__FUNCTION__, xbus, addr , orig_xpd->xpdname); + return -EPROTO; + } spin_lock_irqsave(&xpd->lock, flags); priv = xpd->priv; BUG_ON(!priv); if(REG_FIELD(info, do_subreg)) { - XPD_DBG(REGS, xpd, "RS %02X %02X %02X\n", + XPD_DBG(REGS, xpd, "RI %02X %02X %02X\n", REG_FIELD(info, regnum), REG_FIELD(info, subreg), REG_FIELD(info, data_low)); } else { if (REG_FIELD(info, regnum) != A_SU_RD_STA) XPD_DBG(REGS, xpd, "RD %02X %02X\n", REG_FIELD(info, regnum), REG_FIELD(info, data_low)); + else + XPD_DBG(REGS, xpd, "Got SU_RD_STA=%02X\n", + REG_FIELD(info, data_low)); } - if(info->multibyte) { + if(info->is_multibyte) { XPD_DBG(REGS, xpd, "Got Multibyte: %d bytes, eoframe: %d\n", info->bytes, info->eoframe); ret = rx_dchan(xpd, info); @@ -1345,10 +1368,10 @@ static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) /* Update /proc info only if reply relate to the last slic read request */ if( - REG_FIELD(&priv->requested_reply, regnum) == REG_FIELD(info, regnum) && - REG_FIELD(&priv->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) && - REG_FIELD(&priv->requested_reply, subreg) == REG_FIELD(info, subreg)) { - priv->last_reply = *info; + REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum) && + REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) && + REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info, subreg)) { + xpd->last_reply = *info; } end: @@ -1356,13 +1379,14 @@ end: return 0; } -static xproto_table_t PROTO_TABLE(BRI_NT) = { +static xproto_table_t PROTO_TABLE(BRI) = { .owner = THIS_MODULE, .entries = { /* Table Card Opcode */ }, - .name = "BRI_NT", - .type = XPD_TYPE_BRI_NT, + .name = "BRI", /* protocol name */ + .ports_per_subunit = 1, + .type = XPD_TYPE_BRI, .xops = { .card_new = BRI_card_new, .card_init = BRI_card_init, @@ -1377,37 +1401,6 @@ static xproto_table_t PROTO_TABLE(BRI_NT) = { .card_close = BRI_card_close, .card_register_reply = BRI_card_register_reply, - .RING = XPROTO_CALLER(BRI, RING), - .RELAY_OUT = XPROTO_CALLER(BRI, RELAY_OUT), - .XPD_STATE = XPROTO_CALLER(BRI, XPD_STATE), - }, - .packet_is_valid = bri_packet_is_valid, - .packet_dump = bri_packet_dump, -}; - -static xproto_table_t PROTO_TABLE(BRI_TE) = { - .owner = THIS_MODULE, - .entries = { - /* Table Card Opcode */ - }, - .name = "BRI_TE", - .type = XPD_TYPE_BRI_TE, - .xops = { - .card_new = BRI_card_new, - .card_init = BRI_card_init, - .card_remove = BRI_card_remove, - .card_zaptel_preregistration = BRI_card_zaptel_preregistration, - .card_zaptel_postregistration = BRI_card_zaptel_postregistration, - .card_hooksig = BRI_card_hooksig, - .card_tick = BRI_card_tick, - .card_pcm_fromspan = BRI_card_pcm_fromspan, - .card_pcm_tospan = BRI_card_pcm_tospan, - .card_ioctl = BRI_card_ioctl, - .card_close = BRI_card_close, - .card_register_reply = BRI_card_register_reply, - - .RING = XPROTO_CALLER(BRI, RING), - .RELAY_OUT = XPROTO_CALLER(BRI, RELAY_OUT), .XPD_STATE = XPROTO_CALLER(BRI, XPD_STATE), }, .packet_is_valid = bri_packet_is_valid, @@ -1416,12 +1409,10 @@ static xproto_table_t PROTO_TABLE(BRI_TE) = { static bool bri_packet_is_valid(xpacket_t *pack) { - const xproto_entry_t *xe_nt = NULL; - const xproto_entry_t *xe_te = NULL; + const xproto_entry_t *xe = NULL; // DBG(GENERAL, "\n"); - xe_nt = xproto_card_entry(&PROTO_TABLE(BRI_NT), XPACKET_OP(pack)); - xe_te = xproto_card_entry(&PROTO_TABLE(BRI_TE), XPACKET_OP(pack)); - return xe_nt != NULL || xe_te != NULL; + xe = xproto_card_entry(&PROTO_TABLE(BRI), XPACKET_OP(pack)); + return xe != NULL; } static void bri_packet_dump(const char *msg, xpacket_t *pack) @@ -1449,15 +1440,18 @@ static int proc_bri_info_read(char *page, char **start, off_t off, int count, in len += sprintf(page + len, "%c%d %-15s -- fr_sync=%d t2_exp=%d info0=%d g2_g3=%d\n", IS_NT(xpd)?'G':'F', priv->state_register.bits.v_su_sta, - xhfc_state_name(xpd->type, priv->state_register.bits.v_su_sta), + xhfc_state_name(IS_NT(xpd), priv->state_register.bits.v_su_sta), priv->state_register.bits.v_su_fr_sync, priv->state_register.bits.v_su_t2_exp, priv->state_register.bits.v_su_info0, priv->state_register.bits.v_g2_g3); } else len += sprintf(page + len, "Unkown\n"); - if(IS_NT(xpd)) + if(IS_NT(xpd)) { len += sprintf(page + len, "T1 Timer: %d\n", priv->t1); + } else { + len += sprintf(page + len, "T3 Timer: %d\n", priv->t3); + } 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); @@ -1487,244 +1481,26 @@ static int proc_bri_info_read(char *page, char **start, off_t off, int count, in return len; } -/* - * - * Direct/Indirect - * | - * | Reg# - * | | - * | | Data (only in Write) - * | | | - * | | +-+-+ - * v v v v - * FF WD 06 01 05 - * ^ ^ - * | | - * | Write/Read - * | - * Chan# - * - */ -static int handle_register_command(xpd_t *xpd, char *cmdline) -{ - unsigned chipsel; - unsigned data = 0; - unsigned xdata1 = 0; - unsigned xdata2 = 0; - char op; /* [W]rite, [R]ead */ - char reg_type; /* [D]irect, [S]ubregister */ - int reg_num; - int subreg; - int elements; - bool writing; - char *p; - reg_cmd_t regcmd; - xbus_t *xbus; - int ret = -EINVAL; - struct BRI_priv_data *priv; - byte buf[MAX_PROC_WRITE]; - - BUG_ON(!xpd); - xbus = xpd->xbus; - BUG_ON(!xbus); - priv = xpd->priv; - BUG_ON(!priv); - if((p = strchr(cmdline, '#')) != NULL) /* Truncate comments */ - *p = '\0'; - if((p = strchr(cmdline, ';')) != NULL) /* Truncate comments */ - *p = '\0'; - for(p = cmdline; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */ - ; - if(*p == '\0') - return 0; - - if(!XBUS_GET(xbus)) { - XBUS_DBG(GENERAL, xbus, "Dropped packet. Is shutting down.\n"); - return -EBUSY; - } - memset(buf, 0, MAX_PROC_WRITE); - elements = sscanf(cmdline, "%d %c%c %x %x %x %x %x", - &chipsel, - &op, ®_type, ®_num, - &subreg, - &data, &xdata1, &xdata2); - XPD_DBG(PROC, xpd, "'%s': %d %c%c %02X %02X %02X\n", cmdline, chipsel, op, reg_type, reg_num, subreg, data); - if(elements < 3) { // At least: chipsel, op, reg_type, reg_num - ERR("Not enough arguments: (%d args) '%s'\n", elements, cmdline); - goto out; - } - if(!VALID_CHIPSEL(chipsel)) { - ERR("Bad chip select number: %d\n", chipsel); - goto out; - } - REG_FIELD(®cmd, chipsel) = chipsel; - switch(op) { - case 'W': - writing = 1; - break; - case 'R': - writing = 0; - break; - default: - ERR("Unkown operation type '%c'\n", op); - goto out; - } - if( - (op == 'W' && reg_type == 'D' && elements != 5) || - (op == 'W' && reg_type == 'S' && elements != 6) || - (op == 'R' && reg_type == 'D' && elements != 4) || - (op == 'R' && reg_type == 'S' && elements != 4) - ) { - ERR("Bad number of elements: '%s' (%d elements): %d %c%c %02X %02X %02X\n", - cmdline, elements, - chipsel, op, reg_type, reg_num, subreg, data); - goto out; - } - switch(reg_type) { - case 'S': - REG_FIELD(®cmd, do_subreg) = 1; - REG_FIELD(®cmd, regnum) = reg_num; - REG_FIELD(®cmd, subreg) = subreg; - REG_FIELD(®cmd, data_low) = data; - break; - case 'D': - REG_FIELD(®cmd, do_subreg) = 0; - REG_FIELD(®cmd, regnum) = reg_num; - REG_FIELD(®cmd, subreg) = 0; - REG_FIELD(®cmd, data_low) = subreg; - break; - case 'M': /* Multi without eoftx */ - case 'm': /* Multi with eoftx */ - if(!writing) { - ERR("Read multibyte is not implemented\n"); - goto out; - } - elements -= 3; - REG_XDATA(®cmd)[0] = reg_num; - REG_XDATA(®cmd)[1] = subreg; - REG_XDATA(®cmd)[2] = data; - REG_XDATA(®cmd)[3] = xdata1; - REG_XDATA(®cmd)[4] = xdata2; - ret = send_bri_multibyte(xpd, REG_XDATA(®cmd), elements, (reg_type == 'm')); - goto out; - default: - ERR("Unkown register type '%c'\n", reg_type); - goto out; - } - regcmd.bytes = sizeof(regcmd) - 1; - REG_FIELD(®cmd, read_request) = writing; - REG_FIELD(®cmd, data_high) = 0; - priv->requested_reply = regcmd; - if(print_dbg) - dump_reg_cmd("BRI", ®cmd, 1); - ret = xpp_register_request(xpd->xbus, xpd, - REG_FIELD(®cmd, chipsel), - writing, - REG_FIELD(®cmd, do_subreg), - REG_FIELD(®cmd, regnum), - REG_FIELD(®cmd, subreg), - REG_FIELD(®cmd, data_low), - REG_FIELD(®cmd, data_high)); -out: - XBUS_PUT(xbus); - return ret; -} - -static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ - xpd_t *xpd = data; - char buf[MAX_PROC_WRITE]; - char *p; - int i; - int ret; - - if(!xpd) - return -ENODEV; - for(i = 0; i < count; /* noop */) { - for(p = buf; p < buf + MAX_PROC_WRITE; p++) { /* read a line */ - if(i >= count) - break; - if(get_user(*p, buffer + i)) - return -EFAULT; - i++; - if(*p == '\n' || *p == '\r') /* whatever */ - break; - } - if(p >= buf + MAX_PROC_WRITE) - return -E2BIG; - *p = '\0'; - ret = handle_register_command(xpd, buf); - if(ret < 0) - return ret; - msleep(1); - } - return count; -} - - -static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - xpd_t *xpd = data; - reg_cmd_t *info; - struct BRI_priv_data *priv; - - if(!xpd) - return -ENODEV; - priv = xpd->priv; - BUG_ON(!priv); - spin_lock_irqsave(&xpd->lock, flags); - info = &priv->last_reply; - len += sprintf(page + len, "# Writing bad data into this file may damage your hardware!\n"); - len += sprintf(page + len, "# Consult firmware docs first\n"); - len += sprintf(page + len, "#\n"); - if(REG_FIELD(info, do_subreg)) { - len += sprintf(page + len, "#CH\tOP\tReg.\tSub\tDL\n"); - len += sprintf(page + len, "%2d\tRS\t%02X\t%02X\t%02X\n", - REG_FIELD(info, chipsel), - REG_FIELD(info, regnum), REG_FIELD(info, subreg), REG_FIELD(info, data_low)); - } else { - len += sprintf(page + len, "#CH\tOP\tReg.\tDL\n"); - len += sprintf(page + len, "%2d\tRD\t%02X\t%02X\n", - REG_FIELD(info, chipsel), - REG_FIELD(info, regnum), REG_FIELD(info, data_low)); - } - spin_unlock_irqrestore(&xpd->lock, flags); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -int __init card_bri_startup(void) +static int __init card_bri_startup(void) { DBG(GENERAL, "\n"); INFO("revision %s\n", XPP_VERSION); - xproto_register(&PROTO_TABLE(BRI_NT)); - xproto_register(&PROTO_TABLE(BRI_TE)); + xproto_register(&PROTO_TABLE(BRI)); return 0; } -void __exit card_bri_cleanup(void) +static void __exit card_bri_cleanup(void) { DBG(GENERAL, "\n"); - xproto_unregister(&PROTO_TABLE(BRI_NT)); - xproto_unregister(&PROTO_TABLE(BRI_TE)); + xproto_unregister(&PROTO_TABLE(BRI)); } MODULE_DESCRIPTION("XPP BRI Card Driver"); MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>"); MODULE_LICENSE("GPL"); MODULE_VERSION(XPP_VERSION); -MODULE_ALIAS_XPD(XPD_TYPE_BRI_NT); -MODULE_ALIAS_XPD(XPD_TYPE_BRI_TE); +MODULE_ALIAS_XPD(XPD_TYPE_BRI); module_init(card_bri_startup); module_exit(card_bri_cleanup); |