void 
xencons_handle_input(void *unused)
{
	struct xencons_interface *intf;
	XENCONS_RING_IDX cons, prod;

	CN_LOCK(cn_mtx);
	intf = xencons_interface();

	cons = intf->in_cons;
	prod = intf->in_prod;
	CN_UNLOCK(cn_mtx);
	
	/* XXX needs locking */
	while (cons != prod) {
		xencons_rx(intf->in + MASK_XENCONS_IDX(cons, intf->in), 1);
		cons++;
	}

	mb();
	intf->in_cons = cons;

	CN_LOCK(cn_mtx);
	notify_remote_via_evtchn(xen_start_info->console_evtchn);

	xencons_tx();
	CN_UNLOCK(cn_mtx);
}
Beispiel #2
0
void 
xencons_rx(char *buf, unsigned len)
{
	int           i;
	struct tty *tp = xccons;

	if (xen_console_up
#ifdef DDB
	    && !kdb_active
#endif
		) {
		tty_lock(tp);
		for (i = 0; i < len; i++) {
#ifdef KDB
			kdb_alt_break(buf[i], &xc_altbrk);
#endif
			ttydisc_rint(tp, buf[i], 0);
		}
		ttydisc_rint_done(tp);
		tty_unlock(tp);
	} else {
		CN_LOCK(cn_mtx);
		for (i = 0; i < len; i++)
			rbuf[RBUF_MASK(rp++)] = buf[i];
		CN_UNLOCK(cn_mtx);
	}
}
Beispiel #3
0
static int
xc_cngetc(struct consdev *dev)
{
	int ret;

	if (xencons_has_input())
		xencons_handle_input(NULL);
	
	CN_LOCK(cn_mtx);
	if ((rp - rc) && !xc_mute) {
		/* we need to return only one char */
		ret = (int)rbuf[RBUF_MASK(rc)];
		rc++;
	} else
		ret = -1;
	CN_UNLOCK(cn_mtx);
	return(ret);
}
Beispiel #4
0
static void 
__xencons_tx_flush(void)
{
	int        sz;

	CN_LOCK(cn_mtx);
	while (wc != wp) {
		int sent;
		sz = wp - wc;
		if (sz > (WBUF_SIZE - WBUF_MASK(wc)))
			sz = WBUF_SIZE - WBUF_MASK(wc);
		if (xen_initial_domain()) {
			HYPERVISOR_console_io(CONSOLEIO_write, sz, &wbuf[WBUF_MASK(wc)]);
			wc += sz;
		} else {
			sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
			if (sent == 0) 
				break;
			wc += sent;
		}
	}
	CN_UNLOCK(cn_mtx);
}
Beispiel #5
0
int 
xencons_ring_send(const char *data, unsigned len)
{
	struct xencons_interface *intf; 
	XENCONS_RING_IDX cons, prod;
	int sent;
	struct evtchn_send send = {
		.port = HYPERVISOR_start_info->console_evtchn
	};

	intf = xencons_interface();
	cons = intf->out_cons;
	prod = intf->out_prod;
	sent = 0;

	mb();
	KASSERT((prod - cons) <= sizeof(intf->out),
		("console send ring inconsistent"));
	
	while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
		intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];

	wmb();
	intf->out_prod = prod;

	if (cnsl_evt_reg)
		xen_intr_signal(console_handle);
	else
		HYPERVISOR_event_channel_op(EVTCHNOP_send, &send);

	return sent;

}	


static xencons_receiver_func *xencons_receiver;

void 
xencons_handle_input(void *unused)
{
	struct xencons_interface *intf;
	XENCONS_RING_IDX cons, prod;

	CN_LOCK(cn_mtx);

	if (xen_initial_domain()) {
		static char rbuf[DOM0_BUFFER_SIZE];
		int         l;

		while ((l = HYPERVISOR_console_io(CONSOLEIO_read,
		    DOM0_BUFFER_SIZE, rbuf)) > 0)
			xencons_rx(rbuf, l);

		CN_UNLOCK(cn_mtx);
		return;
	}

	intf = xencons_interface();

	cons = intf->in_cons;
	prod = intf->in_prod;
	CN_UNLOCK(cn_mtx);
	
	/* XXX needs locking */
	while (cons != prod) {
		xencons_rx(intf->in + MASK_XENCONS_IDX(cons, intf->in), 1);
		cons++;
	}

	mb();
	intf->in_cons = cons;

	CN_LOCK(cn_mtx);
	xen_intr_signal(console_handle);

	xencons_tx();
	CN_UNLOCK(cn_mtx);
}

void 
xencons_ring_register_receiver(xencons_receiver_func *f)
{
	xencons_receiver = f;
}

int
xencons_ring_init(void)
{
	int err;

	if (HYPERVISOR_start_info->console_evtchn == 0)
		return 0;

	err = xen_intr_bind_local_port(xencons_dev,
	    HYPERVISOR_start_info->console_evtchn, NULL, xencons_handle_input, NULL,
	    INTR_TYPE_MISC | INTR_MPSAFE, &console_handle);
	if (err) {
		return err;
	}

	return 0;
}