static void reset_sync_counters(void) { int i; //DBG(SYNC, "%d\n", atomic_read(&xpp_tick_counter)); for(i = 0; i < MAX_BUSES; i++) { xbus_t *xbus = get_xbus(i); if(!xbus) continue; /* * Don't send to non self_ticking Astribanks: * - Maybe they didn't finish initialization * - Or maybe they didn't answer us in the first place (e.g: wrong firmware version, etc). */ if (TRANSPORT_RUNNING(xbus) && xbus->self_ticking) { if(XBUS_GET(xbus)) { /* Reset sync LEDs once in a while */ CALL_PROTO(GLOBAL, RESET_SYNC_COUNTERS, xbus, NULL); XBUS_PUT(xbus); } else { static int rate_limit; if((rate_limit++ % 1003) == 0) XBUS_DBG(GENERAL, xbus, "Dropped packet. Is shutting down. (%d)\n", rate_limit); } } put_xbus(xbus); } }
static DEVICE_ATTR_READER(status_show, dev, buf) { xbus_t *xbus; int ret; xbus = dev_to_xbus(dev); ret = snprintf(buf, PAGE_SIZE, "%s\n", (TRANSPORT_RUNNING(xbus))?"connected":"missing"); return ret; }
/* * called from elect_syncer() * if new_syncer is NULL, than we move all to SYNC_MODE_PLL * for ZAPTEL sync. */ static void update_sync_master(xbus_t *new_syncer) { const char *msg = (force_zaptel_sync) ? "ZAPTEL" : "NO-SYNC"; int i; unsigned long flags; DBG(SYNC, "%s => %s\n", (syncer) ? syncer->busname : msg, (new_syncer) ? new_syncer->busname : msg); /* * This global locking protects: * - The ref_ticker so it won't be used while we change it. * - The xbus_drift_clear() from corrupting driftinfo data. */ spin_lock_irqsave(&ref_ticker_lock, flags); if(syncer) xbus_drift_clear(syncer); /* Clean old data */ if(new_syncer) { XBUS_DBG(SYNC, new_syncer, "pcm_rx_counter=%d\n", atomic_read(&new_syncer->pcm_rx_counter)); force_zaptel_sync = 0; ref_ticker = &new_syncer->ticker; xbus_drift_clear(new_syncer); /* Clean new data */ xbus_request_sync(new_syncer, SYNC_MODE_AB); } else if(force_zaptel_sync) { ref_ticker = &zaptel_ticker; } else { ref_ticker = NULL; } spin_unlock_irqrestore(&ref_ticker_lock, flags); DBG(SYNC, "stop unwanted syncers\n"); /* Shut all down except the wanted sync master */ for(i = 0; i < MAX_BUSES; i++) { xbus_t *xbus = get_xbus(i); if(!xbus) continue; if(TRANSPORT_RUNNING(xbus) && xbus != new_syncer) { if(xbus->self_ticking) xbus_request_sync(xbus, SYNC_MODE_PLL); else XBUS_DBG(SYNC, xbus, "Not self_ticking yet. Ignore\n"); } put_xbus(xbus); } }
static inline void pcm_frame_out(xbus_t *xbus, xframe_t *xframe) { unsigned long flags; struct timeval now; unsigned long usec; spin_lock_irqsave(&xbus->lock, flags); do_gettimeofday(&now); if(unlikely(disable_pcm || !TRANSPORT_RUNNING(xbus))) goto dropit; if(XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) { usec = usec_diff(&now, &xbus->last_tx_sync); xbus->last_tx_sync = now; /* ignore startup statistics */ if(likely(atomic_read(&xbus->pcm_rx_counter) > BIG_TICK_INTERVAL)) { if(abs(usec - 1000) > TICK_TOLERANCE) { static int rate_limit; if((rate_limit++ % 5003) == 0) XBUS_DBG(SYNC, xbus, "Bad PCM TX timing(%d): usec=%ld.\n", rate_limit, usec); } if(usec > xbus->max_tx_sync) xbus->max_tx_sync = usec; if(usec < xbus->min_tx_sync) xbus->min_tx_sync = usec; } } spin_unlock_irqrestore(&xbus->lock, flags); /* OK, really send it */ if(debug & DBG_PCM ) dump_xframe("TX_XFRAME_PCM", xbus, xframe, debug); send_pcm_frame(xbus, xframe); XBUS_COUNTER(xbus, TX_XFRAME_PCM)++; return; dropit: spin_unlock_irqrestore(&xbus->lock, flags); FREE_SEND_XFRAME(xbus, xframe); }
void elect_syncer(const char *msg) { int i; int j; uint timing_priority = 0; xpd_t *best_xpd = NULL; xbus_t *the_xbus = NULL; for(i = 0; i < MAX_BUSES; i++) { xbus_t *xbus = get_xbus(i); if(!xbus) continue; if(!the_xbus) the_xbus = xbus; if (TRANSPORT_RUNNING(xbus)) { for(j = 0; j < MAX_XPDS; j++) { xpd_t *xpd = xpd_of(xbus, j); if(!xpd || !xpd->card_present) continue; if(xpd->timing_priority > timing_priority) { timing_priority = xpd->timing_priority; best_xpd = xpd; } } } put_xbus(xbus); } if(best_xpd) { the_xbus = best_xpd->xbus; XPD_DBG(SYNC, best_xpd, "%s: elected with priority %d\n", msg, timing_priority); } else if(the_xbus) { XBUS_DBG(SYNC, the_xbus, "%s: elected\n", msg); } else DBG(SYNC, "%s: No more syncers\n", msg); if(the_xbus != syncer) update_sync_master(the_xbus); }