示例#1
0
static void xpp_set_syncer(xbus_t *xbus, bool on)
{
	if(syncer != xbus && on) {
		XBUS_DBG(SYNC, xbus, "New syncer\n");
		syncer = xbus;
	} else if(syncer == xbus && !on) {
		XBUS_DBG(SYNC, xbus, "Lost syncer\n");
		syncer = NULL;
	} else
		XBUS_DBG(SYNC, xbus, "ignore %s (current syncer: %s)\n",
			(on)?"ON":"OFF",
			(syncer) ? syncer->busname : "NO-SYNC");
}
示例#2
0
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);
	}
}
示例#3
0
void xbus_set_command_timer(xbus_t *xbus, bool on)
{
	XBUS_DBG(SYNC, xbus, "%s\n", (on)?"ON":"OFF");
	if(on) {
		if(!timer_pending(&xbus->command_timer)) {
			XBUS_DBG(SYNC, xbus, "add_timer\n");
			xbus->command_timer.function = xbus_command_timer;
			xbus->command_timer.data = (unsigned long)xbus;
			xbus->command_timer.expires = jiffies + 1;
			add_timer(&xbus->command_timer);
		}
	} else if(timer_pending(&xbus->command_timer)) {
		XBUS_DBG(SYNC, xbus, "del_timer\n");
		del_timer(&xbus->command_timer);
	}
}
示例#4
0
static void xpp_dev_release(struct device *dev)
{
	xbus_t	*xbus;

	BUG_ON(!dev);
	xbus = dev_to_xbus(dev);
	XBUS_DBG(GENERAL, xbus, "\n");
}
示例#5
0
static int astribank_probe(struct device *dev)
{
	xbus_t *xbus;

	xbus = dev_to_xbus(dev);
	XBUS_DBG(DEVICES, xbus, "SYSFS\n");
	return 0;
}
示例#6
0
/*
 * 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);
	}
}
示例#7
0
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act)
{
	struct kobject *kobj;

	kobj = &xbus->astribank.kobj;
	XBUS_DBG(DEVICES, xbus, "SYFS bus_id=%s action=%d\n",
		 dev_name(&xbus->astribank), act);
	kobject_uevent(kobj, act);
}
示例#8
0
int xbus_sysfs_create(xbus_t *xbus)
{
	struct device	*astribank;
	int		ret = 0;

	BUG_ON(!xbus);
	astribank = &xbus->astribank;
	BUG_ON(!astribank);
	XBUS_DBG(GENERAL, xbus, "\n");
	device_initialize(astribank);
	astribank->bus = &xpp_bus_type;
	astribank->parent = &xpp_bus;
	snprintf(astribank->bus_id, BUS_ID_SIZE, "xbus-%02d", xbus->num);
	astribank->driver_data = NULL;	/* override below */
	astribank->release = xpp_dev_release;
	ret = device_register(astribank);
	if(ret) {
		XBUS_ERR(xbus, "%s: device_add failed: %d\n", __FUNCTION__, ret);
		goto out;
	}
	ret = device_create_file(astribank, &dev_attr_connector);
	if(ret) {
		XBUS_ERR(xbus, "%s: device_create_file failed: %d\n", __FUNCTION__, ret);
		goto out;
	}
	ret = device_create_file(astribank, &dev_attr_label);
	if(ret) {
		XBUS_ERR(xbus, "%s: device_create_file failed: %d\n", __FUNCTION__, ret);
		goto out;
	}
	ret = device_create_file(astribank, &dev_attr_status);
	if(ret) {
		XBUS_ERR(xbus, "%s: device_create_file failed: %d\n", __FUNCTION__, ret);
		goto out;
	}
	ret = device_create_file(astribank, &dev_attr_timing);
	if(ret) {
		XBUS_ERR(xbus, "%s: device_create_file failed: %d\n", __FUNCTION__, ret);
		goto out;
	}
	ret = device_create_file(astribank, &dev_attr_cls);
	if(ret) {
		XBUS_ERR(xbus, "%s: device_create_file failed: %d\n", __FUNCTION__, ret);
		goto out;
	}
#ifdef	SAMPLE_TICKS
	ret = device_create_file(astribank, &dev_attr_samples);
	if(ret) {
		XBUS_ERR(xbus, "%s: device_create_file failed: %d\n", __FUNCTION__, ret);
		goto out;
	}
#endif 
	astribank->driver_data = xbus;	/* Everything is good */
out:
	return ret;
}
示例#9
0
/*
 * Called when the Astribank replies to a sync change request
 */
void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift)
{
	unsigned long	flags;

	XBUS_DBG(SYNC, xbus, "Mode %s (%d), drift=%d (pcm_rx_counter=%d)\n",
		sync_mode_name(mode), mode, drift, atomic_read(&xbus->pcm_rx_counter));
	spin_lock_irqsave(&xbus->lock, flags);
	xbus->sync_adjustment = (signed char)drift;
	if(xbus->sync_mode == mode) {
		XBUS_DBG(SYNC, xbus, "Already in mode '%s'. Ignored\n", sync_mode_name(mode));
		goto out;
	}
	switch(mode) {
	case SYNC_MODE_AB:
		xbus->sync_mode = mode;
		xbus_set_command_timer(xbus, 0);
		xbus->self_ticking = 1;
		xpp_set_syncer(xbus, 1);
		global_ticker = xbus;
		break;
	case SYNC_MODE_PLL:
		xbus->sync_mode = mode;
		xbus_set_command_timer(xbus, 0);
		xbus->self_ticking = 1;
		xpp_set_syncer(xbus, 0);
		global_ticker = xbus;
		break;
	case SYNC_MODE_NONE:		/* lost sync source */
		xbus->sync_mode = mode;
		xbus_set_command_timer(xbus, 1);
		xbus->self_ticking = 0;
		xpp_set_syncer(xbus, 0);
		break;
	case SYNC_MODE_QUERY:		/* ignore           */
		break;
	default:
		XBUS_ERR(xbus, "%s: unknown mode=0x%X\n", __FUNCTION__, mode);
	}
out:
	spin_unlock_irqrestore(&xbus->lock, flags);
}
示例#10
0
int zaptel_sync_tick(struct zt_span *span, int is_master)
{
	xpd_t		*xpd = span->pvt;
	static int	redundant_ticks;	/* for extra spans */
	struct timeval	now;

	if(!force_zaptel_sync)
		goto noop;
	do_gettimeofday(&now);
	BUG_ON(!xpd);
	/*
	 * Detect if any of our spans is zaptel sync master
	 */
	if(is_master) {
		static int	rate_limit;

		if(xpd->xbus != syncer && ((rate_limit % 1003) == 0)) {
			XPD_ERR(xpd,
				"Zaptel master, but syncer=%s\n",
				xpd->xbus->busname);
		}
		if((rate_limit % 5003) == 0)
			XPD_NOTICE(xpd, "Zaptel master: ignore ZAPTEL sync\n");
		rate_limit++;
		goto noop;
	}
	/* Now we know for sure someone else is zaptel sync master */
	if(syncer) {
		static int	rate_limit;

		if((rate_limit++ % 5003) == 0)
			XBUS_DBG(SYNC, syncer,
				"Already a syncer, ignore ZAPTEL sync\n");
		goto noop;
	}
	/* ignore duplicate calls from all our registered spans */
	if((redundant_ticks++ % total_registered_spans()) != 0) {
#if 0
		static int	rate_limit;

		if((rate_limit++ % 1003) < 16)
			XPD_NOTICE(xpd, "boop (%d)\n", zaptel_tick_count);
#endif
		goto noop;
	}
	xpp_ticker_step(&zaptel_ticker, &now);
	zaptel_tick_count++;
	//flip_parport_bit(1);
	return 0;
noop:
	return 0;	/* No auto sync from zaptel */
}
示例#11
0
static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe)
{
	byte		*xframe_end;
	xpacket_t	*pack;
	byte		*p;
	int		len;
	int		ret;

	if(debug & DBG_COMMANDS)
		dump_xframe("RX-CMD", xbus, xframe, DBG_ANY);
	p = xframe->packets;
	xframe_end = p + XFRAME_LEN(xframe);
	do {
		pack = (xpacket_t *)p;
		len = XPACKET_LEN(pack);
		/* Sanity checks */
		if(unlikely(XPACKET_OP(pack) == XPROTO_NAME(GLOBAL,PCM_READ))) {
			static int	rate_limit;

			if((rate_limit++ % 1003) == 0) {
				XBUS_DBG(GENERAL, xbus, "A PCM packet within a Non-PCM xframe\n");
				dump_xframe("In Non-PCM xframe", xbus, xframe, debug);
			}
			ret = -EPROTO;
			goto out;
		}
		p += len;
		if(p > xframe_end || len < RPACKET_HEADERSIZE) {
			static int	rate_limit;

			if((rate_limit++ % 1003) == 0) {
				XBUS_NOTICE(xbus, "Invalid packet length %d\n", len);
				dump_xframe("BAD LENGTH", xbus, xframe, debug);
			}
			ret = -EPROTO;
			goto out;
		}
		ret = packet_process(xbus, pack);
		if(unlikely(ret < 0))
			break;
	} while(p < xframe_end);
out:
	FREE_RECV_XFRAME(xbus, xframe);
	return ret;
}
示例#12
0
static void send_drift(xbus_t *xbus, int drift)
{
	struct timeval          now;
	const char              *msg;

	BUG_ON(abs(drift) > SYNC_ADJ_MAX);
	do_gettimeofday(&now);
	if(drift > xbus->sync_adjustment)
		msg = "up";
	else
		msg = "down";
	XBUS_DBG(SYNC, xbus, "%sDRIFT adjust %s (%d) (last update %ld seconds ago)\n",
		(disable_pll_sync) ? "Fake " : "",
		msg, drift, now.tv_sec - xbus->pll_updated_at);
	if(!disable_pll_sync)
		CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_PLL, drift);
	xbus->pll_updated_at = now.tv_sec;
}
示例#13
0
static DEVICE_ATTR_WRITER(xbus_state_store, dev, buf, count)
{
	xbus_t *xbus;

	xbus = dev_to_xbus(dev);
	XBUS_DBG(GENERAL, xbus, "%s\n", buf);
	if (strncmp(buf, "stop", 4) == 0)
		xbus_deactivate(xbus);
	else if (XBUS_IS(xbus, IDLE) && strncmp(buf, "start", 5) == 0)
		xbus_activate(xbus);
	else {
		XBUS_NOTICE(xbus,
			    "%s: Illegal action %s in state %s. Ignored.\n",
			    __func__, buf, xbus_statename(XBUS_STATE(xbus)));
		return -EINVAL;
	}
	return count;
}
示例#14
0
int xframe_receive(xbus_t *xbus, xframe_t *xframe)
{
	int		ret = 0;
	struct timeval	now;
	struct timeval	tv_received;
	int		usec;

	if(XFRAME_LEN(xframe) < RPACKET_HEADERSIZE) {
		static int	rate_limit;

		if((rate_limit++ % 1003) == 0) {
			XBUS_NOTICE(xbus, "short xframe\n");
			dump_xframe("short xframe", xbus, xframe, debug);
		}
		FREE_RECV_XFRAME(xbus, xframe);
		return -EPROTO;
	}
	if(!XBUS_FLAGS(xbus, CONNECTED)) {
		XBUS_DBG(GENERAL, xbus, "Dropped xframe. Is shutting down.\n");
		return -ENODEV;
	}
	tv_received = xframe->tv_received;
	/*
	 * We want to check that xframes do not mix PCM and other commands
	 */
	if(XPACKET_IS_PCM((xpacket_t *)xframe->packets)) {
		if(!XBUS_IS(xbus, READY))
			FREE_RECV_XFRAME(xbus, xframe);
		else
			xframe_receive_pcm(xbus, xframe);
	} else {
		XBUS_COUNTER(xbus, RX_CMD)++;
		ret = xframe_receive_cmd(xbus, xframe);
	}
	/* Calculate total processing time */
	do_gettimeofday(&now);
	usec = (now.tv_sec - tv_received.tv_sec) * 1000000 +
		now.tv_usec - tv_received.tv_usec;
	if(usec > xbus->max_rx_process)
		xbus->max_rx_process = usec;
	return ret;
}
示例#15
0
void xbus_sysfs_remove(xbus_t *xbus)
{
	struct device	*astribank;

	BUG_ON(!xbus);
	XBUS_DBG(GENERAL, xbus, "\n");
	astribank = &xbus->astribank;
	BUG_ON(!astribank);
	if(!astribank->driver_data)
		return;
	BUG_ON(astribank->driver_data != xbus);
#ifdef	SAMPLE_TICKS
	device_remove_file(&xbus->astribank, &dev_attr_samples);
#endif 
	device_remove_file(&xbus->astribank, &dev_attr_cls);
	device_remove_file(&xbus->astribank, &dev_attr_timing);
	device_remove_file(&xbus->astribank, &dev_attr_status);
	device_remove_file(&xbus->astribank, &dev_attr_label);
	device_remove_file(&xbus->astribank, &dev_attr_connector);
	device_unregister(&xbus->astribank);
}
示例#16
0
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);
}
示例#17
0
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);
}
示例#18
0
static void xpp_drift_step(xbus_t *xbus, const struct timeval *tv)
{
	struct xpp_drift	*driftinfo = &xbus->drift;
	struct xpp_ticker	*ticker = &xbus->ticker;
	unsigned long		flags;
	bool			cycled;

	spin_lock_irqsave(&driftinfo->lock, flags);
	cycled = xpp_ticker_step(&xbus->ticker, tv);
	if(ref_ticker && syncer && xbus->sync_mode == SYNC_MODE_PLL) {
		int	new_delta_tick = ticker->count - ref_ticker->count;
		int	lost_ticks = new_delta_tick - driftinfo->delta_tick;

		driftinfo->delta_tick = new_delta_tick;
		if(lost_ticks) {
			driftinfo->lost_ticks++;
			driftinfo->lost_tick_count += abs(lost_ticks);
			XBUS_DBG(SYNC, xbus, "Lost %d tick%s\n",
				lost_ticks,
				(abs(lost_ticks) > 1) ? "s": "");
			ticker->cycle = SYNC_ADJ_QUICK;
			if(abs(lost_ticks) > 100)
				ticker->count = ref_ticker->count;
		} else {
			long	usec_delta;
			bool	nofix = 0;

			usec_delta = (long)usec_diff(
					&ticker->last_sample.tv,
					&ref_ticker->last_sample.tv);
			usec_delta -= driftinfo->wanted_offset;
			sample_tick(xbus, usec_delta);
			if(abs(usec_delta) > 300) {
				/*
				 * We are close to the edge, send a brutal
				 * fix, and skip calculation until next time.
				 */
				if(usec_delta > 0 && xbus->sync_adjustment > -SYNC_ADJ_MAX) {
					XBUS_DBG(SYNC, xbus, "Pullback usec_delta=%ld\n", usec_delta);
					send_drift(xbus, -SYNC_ADJ_MAX);	/* emergency push */
				}
				if(usec_delta < 0 && xbus->sync_adjustment < SYNC_ADJ_MAX) {
					XBUS_DBG(SYNC, xbus, "Pushback usec_delta=%ld\n", usec_delta);
					send_drift(xbus, SYNC_ADJ_MAX);		/* emergency push */
				}
				ticker->cycle = SYNC_ADJ_QUICK;
				nofix = 1;
			} else {
				/* good data, use it */
				if(usec_delta > driftinfo->delta_max)
					driftinfo->delta_max = usec_delta;
				if(usec_delta < driftinfo->delta_min)
					driftinfo->delta_min = usec_delta;
			}
			if(!nofix && cycled) {
				int	offset = 0;

				driftinfo->median = (driftinfo->delta_max + driftinfo->delta_min) / 2;
				driftinfo->jitter = driftinfo->delta_max - driftinfo->delta_min;
				if(abs(driftinfo->median) >= 150) {	/* more than 1 usb uframe */
					int	factor = abs(driftinfo->median) / 125;

					factor = 1 + (factor * 8000) / ticker->cycle;
					if(driftinfo->median > 0)
						offset = driftinfo->calc_drift - factor;
					else
						offset = driftinfo->calc_drift + factor;
					/* for large median, push some more */
					if(abs(driftinfo->median) >= 300) {	/* more than 2 usb uframes */
						ticker->cycle = SYNC_ADJ_QUICK;
						XBUS_NOTICE(xbus,
								"Back to quick: median=%d\n",
								driftinfo->median);
					}
				} else {
					ticker->cycle += 500;
					if(ticker->cycle >= SYNC_ADJ_SLOW)
						ticker->cycle = SYNC_ADJ_SLOW;
				}
				driftinfo->calc_drift = offset;
				XBUS_DBG(SYNC, xbus,
						"ADJ: min=%d max=%d jitter=%d median=%d offset=%d\n",
						driftinfo->delta_min,
						driftinfo->delta_max,
						driftinfo->jitter,
						driftinfo->median,
						offset);
				if(offset < -SYNC_ADJ_MAX)
					offset = -SYNC_ADJ_MAX;
				if(offset > SYNC_ADJ_MAX)
					offset = SYNC_ADJ_MAX;
				xbus->sync_adjustment_offset = offset;
				if(xbus != syncer && xbus->sync_adjustment != offset)
					send_drift(xbus, offset);
				driftinfo_recalc(driftinfo);
			}
		}
	}
	spin_unlock_irqrestore(&driftinfo->lock, flags);
}
示例#19
0
void xbus_request_sync(xbus_t *xbus, enum sync_mode mode)
{
	BUG_ON(!xbus);
	XBUS_DBG(SYNC, xbus, "sent request (mode=%d)\n", mode);
	CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, mode, 0);
}