From ba840a7aa6178133f4e7697225f0ace4c353e8a4 Mon Sep 17 00:00:00 2001 From: Noe Rubinstein Date: Fri, 24 Sep 2010 14:15:55 +0200 Subject: clean up + introduce new bugs --- xivovp/base.c | 370 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 217 insertions(+), 153 deletions(-) (limited to 'xivovp/base.c') diff --git a/xivovp/base.c b/xivovp/base.c index 4f0b703..2875d96 100644 --- a/xivovp/base.c +++ b/xivovp/base.c @@ -10,11 +10,11 @@ #include "vp_api.h" #include "EVB_Le71HR8921G_rev_E_2M048.h" -#define TICK_MS 5 /* matches with device profile configuration */ +#define VP_TICK_MS 5 /* matches with device profile configuration */ #include "tolapai_spi.h" -#define DRV_NAME KBUILD_BASENAME +#define DRV_NAME "xivovp" #define TRACES_VANISH_DEFAULT 2000 #define TXQUEUE_LEN 5 @@ -27,8 +27,11 @@ MODULE_PARM_DESC(traces_vanish, "ERROR/WARNING/INFO (default: " __stringify(TRACES_VANISH_DEFAULT) ")"); -#define NB_LINES 1 //XXX -#define TICK_JIFFIES DIV_ROUND_UP(TICK_MS * HZ, 1000) +#define NB_LINES 1 //XXX +#define TICK_JIFFIES(n) DIV_ROUND_UP(n * HZ, 1000) +#define VP_TICK_JIFFIES TICK_JIFFIES(VP_TICK_MS) +#define RXTX_TICK_JIFFIES TICK_JIDDIES(1) + #define DEBUG_SELECT_RUNNING (VP_DBG_ERROR \ | VP_DBG_WARNING \ | VP_DBG_INFO) @@ -63,20 +66,36 @@ static struct xivovp { VpDevCtxType dev_ctx; } xivovp; -static int -xivovp_hooksig_pvt(struct xivovp_line* line, enum dahdi_txsig txsig); +struct timer_list rxtx_timer; + +static void xivovp_rxtx(unsigned long data) +{ + (void) data; + dahdi_receive(&xivovp.span) + dahdi_transmit(&xivovp.span) + dahdi_ec_span(&xivovp.span) + + mod_timer(&xivovp.vp_tick_timer, jiffies + RXTX_TICK_JIFFIES); +} /* Shouldn't there be something better there? TOTHINK */ static struct xivovp_line* xivovp_line_from_ctx(VpLineCtxType* line_ctx) { - Vp890LineObjectType* line_obj = line_ctx->pLineObj; + Vp890LineObjectType* line_obj; int i; + if(!line_ctx) { + printk(KERN_ERR DRV_NAME ": LineCtx == NULL\n"); + return NULL; + } + + line_obj = line_ctx->pLineObj; + for(i = 0; i < ARRAY_SIZE(xivovp.line); i++) if(&xivovp.line[i].line_obj == line_obj) return &xivovp.line[i]; - printk(KERN_ERR DRV_NAME ": a FX line we don't know of? This certainly shouldn't happen.\n"); + printk(KERN_ERR DRV_NAME ": unknown FX line, this shouldn't happen\n"); return NULL; } @@ -87,28 +106,191 @@ static void vp_set_debug_select_running(void) for(i = 0; i < ARRAY_SIZE(xivovp.line); i++) { debug_select = DEBUG_SELECT_RUNNING; - VpSetOption(&xivovp.line[i].vp_ctx, NULL, VP_OPTION_ID_DEBUG_SELECT, - &debug_select); + VpSetOption(&xivovp.line[i].vp_ctx, NULL, + VP_OPTION_ID_DEBUG_SELECT, + &debug_select); } debug_select = DEBUG_SELECT_RUNNING; - VpSetOption(NULL, &xivovp.dev_ctx, VP_OPTION_ID_DEBUG_SELECT, &debug_select); + VpSetOption(NULL, &xivovp.dev_ctx, VP_OPTION_ID_DEBUG_SELECT, + &debug_select); debug_select = DEBUG_SELECT_RUNNING; VpSetOption(NULL, NULL, VP_OPTION_ID_DEBUG_SELECT, &debug_select); } -static void vp_tick(const unsigned long data) +static int xivovp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig) +{ + struct xivovp_line* line = chan->pvt; + + if(line->txsig_queue_len >= ARRAY_SIZE(line->txsig_queue)) { + printk(KERN_WARNING DRV_NAME "(chan %d): txsig overrun", chan->chanpos); + return -1; + } + + line->txsig_queue[line->txsig_queue_len++] = txsig; + return 0; +} + +/* + * hooksig transmits sig from DAHDI to VP. + * sig from VP is handled in vp_tick and transmitted to DAHDI with + * dahdi_hooksig + */ +static void xivovp_hooksig_pvt(struct xivovp_line* line, enum dahdi_txsig txsig) +{ + int chanpos = line->chan.chanpos; + if(line->type == FXO_LINE) { + switch(txsig) { + case DAHDI_TXSIG_START: + case DAHDI_TXSIG_OFFHOOK: + printk(KERN_WARNING DRV_NAME "(chan %d): transmitting %s state on FXO, setting to TALK.\n", chanpos, txsig == DAHDI_TXSIG_START ? "START" : "OFFHOOK"); + VpSetLineState(&line->vp_ctx, VP_LINE_FXO_TALK); + break; + case DAHDI_TXSIG_ONHOOK: + printk(KERN_WARNING DRV_NAME "(chan %d): transmitting ONHOOK on FXO, setting to OHT.\n", chanpos); + VpSetLineState(&line->vp_ctx, VP_LINE_FXO_OHT); + break; + default: + printk(KERN_WARNING DRV_NAME "(chan %d): unsupported tx state for FXO: %d\n", chanpos, txsig); + } + } else /* FXS */ { + switch(txsig) { + case DAHDI_TXSIG_START: + printk(KERN_WARNING DRV_NAME "(chan %d): transmitting START on FXS, setting to RINGING.\n", chanpos); + VpSetLineState(&line->vp_ctx, VP_LINE_RINGING); + break; + case DAHDI_TXSIG_OFFHOOK: + printk(KERN_WARNING DRV_NAME "(chan %d): transmitting OFFHOOK on FXS, setting to TALK.\n", chanpos); + VpSetLineState(&line->vp_ctx, VP_LINE_TALK); + break; + case DAHDI_TXSIG_ONHOOK: + printk(KERN_WARNING DRV_NAME "(chan %d): transmitting ONHOOK on FXS, setting to OHT.\n", chanpos); + VpSetLineState(&line->vp_ctx, VP_LINE_OHT); + break; + case DAHDI_TXSIG_KEWL: + printk(KERN_WARNING DRV_NAME "(chan %d): requested to transmit DAHDI_TXSIG_KEWL but I have no idea what it means.\n", chanpos); + //VpSetLineState(line->vp_ctx, ); + break; + default: + printk(KERN_WARNING DRV_NAME "(chan %d): unsupported tx state for FXS: %d\n", chanpos, txsig); + } + } +} + +static void xivovp_handle_txsig_queue(void) { + static int said; int i, j; + + for(i = 0; i < ARRAY_SIZE(xivovp.line); i++) { + if(xivovp.line[i].ready) { + for(j = 0; j < xivovp.line[i].txsig_queue_len; j++) { + xivovp_hooksig_pvt(&xivovp.line[i], + xivovp.line[i].txsig_queue[j]); + } + xivovp.line[i].txsig_queue_len = 0; + } else if(!said) { + said = 1; + printk(KERN_WARNING DRV_NAME ": txsig pending but calibration not done yet! Waiting...\n"); + } + } +} + +static bool count_and_stop_traces = FALSE; + +static void vp_post_init(VpEventType *event) +{ + VpStatusType vpst; + + VpOptionTimeslotType timeslot = { + .tx = 12, + .rx = 12, + }; + VpOptionEventMaskType event_mask = { + .faults = 0, + .signaling = 0, + .response = 0, + .test = 0, + .process = 0, + .fxo = 0, + }; + + printk(KERN_INFO DRV_NAME ": vp dev init complete\n"); + + vpst = VpSetOption(NULL, event->pDevCtx, + VP_OPTION_ID_EVENT_MASK, &event_mask); + if (vpst != VP_STATUS_SUCCESS) { + printk(KERN_ERR DRV_NAME ": VpSetOption VP_OPTION_ID_EVENT_MASK returned %d\n", + (int)vpst); + return; + } + vpst = VpSetOption(NULL, event->pDevCtx, + VP_OPTION_ID_TIMESLOT, + ×lot); + if (vpst != VP_STATUS_SUCCESS) { + printk(KERN_ERR DRV_NAME ": VpSetOption VP_OPTION_ID_TIMESLOT returned %d\n", + (int)vpst); + return; + } + + vpst = VpSetLineState(&xivovp.line[FXS_LINE].vp_ctx, + VP_LINE_OHT); + if (vpst != VP_STATUS_SUCCESS) { + printk(KERN_ERR DRV_NAME ": VpSetLineState returned %d\n", + (int)vpst); + return; + } + + //TODO: VpSetLineState for FXO_LINE + //TODO: VpCalLine for FXO_LINE + // What happens if lines aren't connected? + + vpst = VpCalLine(&xivovp.line[FXS_LINE].vp_ctx); + if (vpst != VP_STATUS_SUCCESS) { + printk(KERN_ERR DRV_NAME ": VpCalLine returned %d\n", + (int)vpst); + return; + } + + mod_timer(&xivovp.vp_tick_timer, jiffies + RXTX_TICK_JIFFIES); + count_and_stop_traces = TRUE; +} + +static void event_calibration_complete(VpEventType *event) +{ + printk(KERN_INFO DRV_NAME ": calibration succeeded\n"); + xivovp_line_from_ctx(event->pLineCtx)->ready = 1; + vp_set_debug_select_running(); +} + +static void event_calibration_fail(VpEventType *event) +{ + (void) event; + printk(KERN_WARNING DRV_NAME ": calibration failed (returned VP_EVID_CAL_BUSY)\n"); + vp_set_debug_select_running(); +} + +static void event_hook_off(VpEventType *event) +{ + struct xivovp_line *line = xivovp_line_from_ctx(event->pLineCtx); + dahdi_hooksig(&line->chan, DAHDI_RXSIG_OFFHOOK); +} + +static void event_hook_on(VpEventType *event) +{ + struct xivovp_line *line = xivovp_line_from_ctx(event->pLineCtx); + dahdi_hooksig(&line->chan, DAHDI_RXSIG_ONHOOK); +} + +static void vp_tick(const unsigned long data) +{ static VpEventType event; static VpResultsType result; - struct xivovp_line* line; bool ev_pending; VpStatusType vpst; - static bool count_and_stop_traces = FALSE; - (void)data; + (void) data; vpst = VpApiTick(&xivovp.dev_ctx, &ev_pending); if (vpst != VP_STATUS_SUCCESS) { @@ -133,84 +315,27 @@ static void vp_tick(const unsigned long data) switch ((int)event.eventCategory) { case VP_EVCAT_RESPONSE: switch (event.eventId) { - case VP_DEV_EVID_DEV_INIT_CMP: { - VpOptionTimeslotType timeslot = { - .tx = 12, - .rx = 12, - }; - VpOptionEventMaskType event_mask = { - .faults = 0, - .signaling = 0, - .response = 0, - .test = 0, - .process = 0, - .fxo = 0, - }; - printk(KERN_INFO DRV_NAME ": vp dev init complete\n"); - vpst = VpSetOption(NULL, event.pDevCtx, - VP_OPTION_ID_EVENT_MASK, &event_mask); - if (vpst != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpSetOption VP_OPTION_ID_EVENT_MASK returned %d\n", - (int)vpst); - return; - } - vpst = VpSetOption(NULL, event.pDevCtx, - VP_OPTION_ID_TIMESLOT, - ×lot); - if (vpst != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpSetOption VP_OPTION_ID_TIMESLOT returned %d\n", - (int)vpst); - return; - } - - vpst = VpSetLineState(&xivovp.line[FXS_LINE].vp_ctx, - VP_LINE_OHT); - if (vpst != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpSetLineState returned %d\n", - (int)vpst); - return; - } - - //TODO: VpSetLineState for FXO_LINE - //TODO: VpCalLine for FXO_LINE - // What happens if lines aren't connected? - - vpst = VpCalLine(&xivovp.line[FXS_LINE].vp_ctx); - if (vpst != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpCalLine returned %d\n", - (int)vpst); - return; - } - count_and_stop_traces = TRUE; + case VP_DEV_EVID_DEV_INIT_CMP: + vp_post_init(&event); break; - } - case VP_EVID_CAL_CMP: - printk(KERN_INFO DRV_NAME ": calibration succeeded\n"); - xivovp_line_from_ctx(event.pLineCtx)->ready = 1; - vp_set_debug_select_running(); + event_calibration_complete(&event); break; case VP_EVID_CAL_BUSY: - printk(KERN_WARNING DRV_NAME ": calibration failed (returned VP_EVID_CAL_BUSY)\n"); - vp_set_debug_select_running(); + event_calibration_fail(&event); break; } break; case VP_EVCAT_FAULT: break; case VP_EVCAT_SIGNALING: - if(!(line = xivovp_line_from_ctx(event.pLineCtx))) - break; - switch (event.eventId) { case VP_LINE_EVID_HOOK_OFF: - dahdi_hooksig(&line->chan, - DAHDI_RXSIG_OFFHOOK); + event_hook_off(&event); break; case VP_LINE_EVID_HOOK_ON: - dahdi_hooksig(&line->chan, - DAHDI_RXSIG_ONHOOK); + event_hook_on(&event); break; } break; @@ -233,88 +358,16 @@ static void vp_tick(const unsigned long data) } } - - for(i = 0; i < ARRAY_SIZE(xivovp.line); i++) { - if(xivovp.line[i].ready) { - for(j = 0; j < xivovp.line[i].txsig_queue_len; j++) { - xivovp_hooksig_pvt(&xivovp.line[i], - xivovp.line[i].txsig_queue[j]); - } - xivovp.line[i].txsig_queue_len = 0; - } - } + xivovp_handle_txsig_queue(); if (count_and_stop_traces) { if (traces_vanish >= 0 && --traces_vanish < 0) vp_set_debug_select_running(); } - mod_timer(&xivovp.vp_tick_timer, jiffies + TICK_JIFFIES); + mod_timer(&xivovp.vp_tick_timer, jiffies + VP_TICK_JIFFIES); } -static int -xivovp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig) -{ - struct xivovp_line* line = chan->pvt; - - if(line->txsig_queue_len >= ARRAY_SIZE(line->txsig_queue)) { - printk(KERN_WARNING DRV_NAME "(chan %d): txsig overrun", chan->chanpos); - return -1; - } - - line->txsig_queue[line->txsig_queue_len++] = txsig; - return 0; -} - -/* - * hooksig transmits sig from DAHDI to VP. - * sig from VP is handled in vp_tick and transmitted to DAHDI with - * dahdi_hooksig - */ -static int -xivovp_hooksig_pvt(struct xivovp_line* line, enum dahdi_txsig txsig) -{ - int chanpos = line->chan.chanpos; - if(line->type == FXO_LINE) { - switch(txsig) { - case DAHDI_TXSIG_START: - case DAHDI_TXSIG_OFFHOOK: - printk(KERN_WARNING DRV_NAME "(chan %d): transmitting %s state on FXO, setting to TALK.\n", chanpos, txsig == DAHDI_TXSIG_START ? "START" : "OFFHOOK"); - VpSetLineState(&line->vp_ctx, VP_LINE_FXO_TALK); - break; - case DAHDI_TXSIG_ONHOOK: - printk(KERN_WARNING DRV_NAME "(chan %d): transmitting ONHOOK on FXO, setting to OHT.\n", chanpos); - VpSetLineState(&line->vp_ctx, VP_LINE_FXO_OHT); - break; - default: - printk(KERN_WARNING DRV_NAME "(chan %d): unsupported tx state for FXO: %d\n", chanpos, txsig); - } - } else /* FXS */ { - switch(txsig) { - case DAHDI_TXSIG_START: - printk(KERN_WARNING DRV_NAME "(chan %d): transmitting START on FXS, setting to RINGING.\n", chanpos); - VpSetLineState(&line->vp_ctx, VP_LINE_RINGING); - break; - case DAHDI_TXSIG_OFFHOOK: - printk(KERN_WARNING DRV_NAME "(chan %d): transmitting OFFHOOK on FXS, setting to TALK.\n", chanpos); - VpSetLineState(&line->vp_ctx, VP_LINE_TALK); - break; - case DAHDI_TXSIG_ONHOOK: - printk(KERN_WARNING DRV_NAME "(chan %d): transmitting ONHOOK on FXS, setting to OHT.\n", chanpos); - VpSetLineState(&line->vp_ctx, VP_LINE_OHT); - break; - case DAHDI_TXSIG_KEWL: - printk(KERN_WARNING DRV_NAME "(chan %d): requested to transmit DAHDI_TXSIG_KEWL but I have no idea what it means.\n", chanpos); - //VpSetLineState(line->vp_ctx, ); - return -1; - default: - printk(KERN_WARNING DRV_NAME "(chan %d): unsupported tx state for FXS: %d\n", chanpos, txsig); - return -1; - } - } - - return 0; -} static const struct dahdi_span_ops xivovp_span_ops = { .owner = THIS_MODULE, @@ -336,6 +389,11 @@ span_init(void) init_waitqueue_head(&xivovp.span.maintq); /* still dunno what this is */ + if(dahdi_register(&xivovp.span, /*prefmaster*/ 0)) { + printk(KERN_WARNING DRV_NAME ": couldn't register span.\n"); + return -EINVAL; + } + return 0; } @@ -349,6 +407,10 @@ xivovp_init(void) xivovp.vp_tick_timer.function = vp_tick; xivovp.vp_tick_timer.data = 42; + init_timer(&rxtx_timer); + rxtx_timer.function = xivovp_rxtx(); + rxtx_timer.data = 1337; + xivovp.line[FXS_LINE].type = FXS_LINE; xivovp.line[FXO_LINE].type = FXO_LINE; @@ -456,7 +518,7 @@ test_evb_ve890_init(void) goto err_dahdi_init; } - mod_timer(&xivovp.vp_tick_timer, jiffies + TICK_JIFFIES); + mod_timer(&xivovp.vp_tick_timer, jiffies + VP_TICK_JIFFIES); return 0; @@ -475,6 +537,8 @@ test_evb_ve890_exit(void) { printk(KERN_INFO DRV_NAME ": %s\n", __func__); + dahdi_unregister(&xivovp.span); + del_timer_sync(&xivovp.vp_tick_timer); /* XXX : TODO update upstream Linux doc of del_timer_sync */ tlp_spidev_exit(); -- cgit v1.2.3