Beispiel #1
0
void
xenconscn_putc(dev_t dev, int c)
{
    int s = spltty();
    XENCONS_RING_IDX cons, prod;

    if (xendomain_is_dom0()) {
        u_char buf[1];

        buf[0] = c;
        (void)HYPERVISOR_console_io(CONSOLEIO_write, 1, buf);
    } else {
        XENPRINTK(("xenconscn_putc(%c)\n", c));

        cons = xencons_interface->out_cons;
        prod = xencons_interface->out_prod;
        xen_rmb();
        while (prod == cons + sizeof(xencons_interface->out)) {
            cons = xencons_interface->out_cons;
            prod = xencons_interface->out_prod;
            xen_rmb();
        }
        xencons_interface->out[MASK_XENCONS_IDX(xencons_interface->out_prod,
                                                xencons_interface->out)] = c;
        xen_rmb();
        xencons_interface->out_prod++;
        xen_rmb();
        hypervisor_notify_via_evtchn(xen_start_info.console.domU.evtchn);
        splx(s);
    }
}
int 
xencons_ring_send(const char *data, unsigned len)
{
	struct xencons_interface *intf; 
	XENCONS_RING_IDX cons, prod;
	int sent;

	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;

	notify_remote_via_evtchn(xen_start_info->console_evtchn);

	return sent;

}	
Beispiel #3
0
int xencons_ring_recv(struct consfront_dev *dev, char *data, unsigned len)
{
	struct xencons_interface *intf;
	XENCONS_RING_IDX cons, prod;
        unsigned filled = 0;

        if (!dev)
            intf = xencons_interface();
        else
            intf = dev->ring;

	cons = intf->in_cons;
	prod = intf->in_prod;
	mb();
	BUG_ON((prod - cons) > sizeof(intf->in));

        while (filled < len && cons + filled != prod) {
                data[filled] = *(intf->in + MASK_XENCONS_IDX(cons + filled, intf->in));
                filled++;
	}

	mb();
        intf->in_cons = cons + filled;

	notify_daemon(dev);

        return filled;
}
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 #5
0
int xencons_ring_send_no_notify(struct consfront_dev *dev, const char *data, unsigned len)
{	
    int sent = 0;
	struct xencons_interface *intf;
	XENCONS_RING_IDX cons, prod;

	if (!dev)
            intf = xencons_interface();
        else
            intf = dev->ring;
        if (!intf)
            return sent;

    while (sent < len) {
	cons = intf->out_cons;
	prod = intf->out_prod;
	mb();
	BUG_ON((prod - cons) > sizeof(intf->out));

	while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
		intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];

	wmb();
	intf->out_prod = prod;

	if (sent < len) {
	    block_domain(MILLISECS(10));
	}
    }
    
    return sent;
}
Beispiel #6
0
void console_handle_input(evtchn_port_t port, struct pt_regs *regs, void *data)
{
	struct consfront_dev *dev = (struct consfront_dev *) data;
#ifdef HAVE_LIBC
        int fd = dev ? dev->fd : -1;

        if (fd != -1)
            files[fd].read = 1;

        wake_up(&console_queue);
#else
	struct xencons_interface *intf = xencons_interface();
	XENCONS_RING_IDX cons, prod;

	cons = intf->in_cons;
	prod = intf->in_prod;
	mb();
	BUG_ON((prod - cons) > sizeof(intf->in));

	while (cons != prod) {
		xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1, regs);
		cons++;
	}

	mb();
	intf->in_cons = cons;

	notify_daemon(dev);

	xencons_tx();
#endif
}
Beispiel #7
0
static void console_int(uint32_t port, void *data)
{
	XENCONS_RING_IDX cons, prod;
	cons = console.intf->in_cons;
	prod = console.intf->in_prod;
	rmb();

	if (prod == cons)
		return;

	uint32_t in_size = prod - cons;
	uint8_t buf[in_size];
	uint8_t *ptr = buf;

	ssa(SYS_STATS_IO_INPUT, in_size);

	while (prod > cons)
	{
		int idx = MASK_XENCONS_IDX(cons++, console.intf->in);
#ifdef DEBUG_CONSOLE
		if (debug_key(console.intf->in[idx]))
		{
			in_size--;
			continue;
		}
#endif
		*ptr++ = console.intf->in[idx];
	}

	console.intf->in_cons = prod;
	wmb();

	if (console.attached)
		outlet_new_data(console.attached, buf, in_size);
}
Beispiel #8
0
void console_write(const char *msg, int len) {
	static int was_cr = 0;

	int sent = 0;
	while (sent < len)
	{
		XENCONS_RING_IDX cons, prod;
		cons = console.intf->out_cons;
		rmb();
		prod = console.intf->out_prod;

//	while ((sent < len) && (prod - cons < sizeof(console.intf->out)))
//		console.intf->out[MASK_XENCONS_IDX(prod++, console.intf->out)] = msg[sent++];
//
// It may be possible to use stty or ESC sequence instead of this nastiness
// 

		while ((sent < len) && (prod - cons < sizeof(console.intf->out))) {
			if (msg[sent] == '\n' && !was_cr)
			{
				int idx = MASK_XENCONS_IDX(prod, console.intf->out);
				console.intf->out[idx] = '\r';
				prod++;
				if (prod - cons >= sizeof(console.intf->out))
					break;
			}
			was_cr = (msg[sent] == '\r');
			int idx = MASK_XENCONS_IDX(prod, console.intf->out);
			console.intf->out[idx] = msg[sent++];
			prod++;
		}

		console.intf->out_prod = prod;
		wmb();

		event_kick(console.chan);
	}
	ssa(SYS_STATS_IO_OUTPUT, len);
}
Beispiel #9
0
int
xenconscn_getc(dev_t dev)
{
    char c;
    int s = spltty();
    XENCONS_RING_IDX cons, prod;

    if (xencons_console_device && xencons_console_device->polling == 0) {
        printf("xenconscn_getc() but not polling\n");
        splx(s);
        return 0;
    }
    if (xendomain_is_dom0()) {
        while (HYPERVISOR_console_io(CONSOLEIO_read, 1, &c) == 0)
            ;
        cn_check_magic(dev, c, xencons_cnm_state);
        splx(s);
        return c;
    }
    if (xencons_console_device == NULL) {
        printf("xenconscn_getc(): not console\n");
        while (1)
            ;  /* loop here instead of in ddb */
        splx(s);
        return 0;
    }

    if (xencons_console_device->polling == 0) {
        printf("xenconscn_getc() but not polling\n");
        splx(s);
        return 0;
    }

    cons = xencons_interface->in_cons;
    prod = xencons_interface->in_prod;
    xen_rmb();
    while (cons == prod) {
        HYPERVISOR_yield();
        prod = xencons_interface->in_prod;
    }
    xen_rmb();
    c = xencons_interface->in[MASK_XENCONS_IDX(xencons_interface->in_cons,
                              xencons_interface->in)];
    xen_rmb();
    xencons_interface->in_cons = cons + 1;
    cn_check_magic(dev, c, xencons_cnm_state);
    splx(s);
    return c;
}
Beispiel #10
0
static void buffer_append(struct XenConsole *con)
{
    struct buffer *buffer = &con->buffer;
    XENCONS_RING_IDX cons, prod, size;
    struct xencons_interface *intf = con->sring;

    cons = intf->out_cons;
    prod = intf->out_prod;
    xen_mb();

    size = prod - cons;
    if ((size == 0) || (size > sizeof(intf->out)))
	return;

    if ((buffer->capacity - buffer->size) < size) {
	buffer->capacity += (size + 1024);
	buffer->data = g_realloc(buffer->data, buffer->capacity);
    }

    while (cons != prod)
	buffer->data[buffer->size++] = intf->out[
	    MASK_XENCONS_IDX(cons++, intf->out)];

    xen_mb();
    intf->out_cons = cons;
    xen_pv_send_notify(&con->xendev);

    if (buffer->max_capacity &&
	buffer->size > buffer->max_capacity) {
	/* Discard the middle of the data. */

	size_t over = buffer->size - buffer->max_capacity;
	uint8_t *maxpos = buffer->data + buffer->max_capacity;

	memmove(maxpos - over, maxpos, over);
	buffer->data = g_realloc(buffer->data, buffer->max_capacity);
	buffer->size = buffer->capacity = buffer->max_capacity;

	if (buffer->consumed > buffer->max_capacity - over)
	    buffer->consumed = buffer->max_capacity - over;
    }
}
Beispiel #11
0
static int domU_read_console(uint32_t vtermno, char *buf, int len)
{
	struct xencons_interface *intf = xencons_interface();
	XENCONS_RING_IDX cons, prod;
	int recv = 0;

	cons = intf->in_cons;
	prod = intf->in_prod;
	mb();			/* get pointers before reading ring */
	BUG_ON((prod - cons) > sizeof(intf->in));

	while (cons != prod && recv < len)
		buf[recv++] = intf->in[MASK_XENCONS_IDX(cons++, intf->in)];

	mb();			/* read ring before consuming */
	intf->in_cons = cons;

	notify_daemon();
	return recv;
}
Beispiel #12
0
static int write_console(uint32_t vtermno, const char *data, int len)
{
	struct xencons_interface *intf = xencons_interface();
	XENCONS_RING_IDX cons, prod;
	int sent = 0;

	cons = intf->out_cons;
	prod = intf->out_prod;
	mb();			/* update queue values before going on */
	BUG_ON((prod - cons) > sizeof(intf->out));

	while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
		intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];

	wmb();			/* write ring before updating pointer */
	intf->out_prod = prod;

	notify_daemon();
	return sent;
}
Beispiel #13
0
static void xencons_receive(void *opaque, const uint8_t *buf, int len)
{
    struct XenConsole *con = opaque;
    struct xencons_interface *intf = con->sring;
    XENCONS_RING_IDX prod;
    int i, max;

    max = ring_free_bytes(con);
    /* The can_receive() func limits this, but check again anyway */
    if (max < len)
	len = max;

    prod = intf->in_prod;
    for (i = 0; i < len; i++) {
	intf->in[MASK_XENCONS_IDX(prod++, intf->in)] =
	    buf[i];
    }
    xen_wmb();
    intf->in_prod = prod;
    xen_pv_send_notify(&con->xendev);
}
Beispiel #14
0
int xencons_ring_send(const char *data, unsigned len)
{
	int sent = 0;
	struct xencons_interface *intf = xencons_interface();
	XENCONS_RING_IDX cons, prod;

	cons = intf->out_cons;
	prod = intf->out_prod;
	mb();
	BUG_ON((prod - cons) > sizeof(intf->out));

	while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
		intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];

	wmb();
	intf->out_prod = prod;

	notify_daemon();

	return sent;
}
/**
  Write data from buffer to serial device.

  Writes NumberOfBytes data bytes from Buffer to the serial device.
  The number of bytes actually written to the serial device is returned.
  If the return value is less than NumberOfBytes, then the write operation failed.
  If Buffer is NULL, then ASSERT().
  If NumberOfBytes is zero, then return 0.

  @param  Buffer           Pointer to the data buffer to be written.
  @param  NumberOfBytes    Number of bytes to written to the serial device.

  @retval 0                NumberOfBytes is 0.
  @retval >0               The number of bytes written to the serial device.
                           If this value is less than NumberOfBytes, then the write operation failed.

**/
UINTN
EFIAPI
SerialPortWrite (
  IN UINT8     *Buffer,
  IN UINTN     NumberOfBytes
  )
{
  XENCONS_RING_IDX  Consumer, Producer;
  UINTN             Sent;

  ASSERT (Buffer != NULL);

  if (NumberOfBytes == 0) {
    return 0;
  }

  if (!mXenConsoleInterface) {
    return 0;
  }

  Sent = 0;
  do {
    Consumer = mXenConsoleInterface->out_cons;
    Producer = mXenConsoleInterface->out_prod;

    MemoryFence ();

    while (Sent < NumberOfBytes && ((Producer - Consumer) < sizeof (mXenConsoleInterface->out)))
      mXenConsoleInterface->out[MASK_XENCONS_IDX(Producer++, mXenConsoleInterface->out)] = Buffer[Sent++];

    MemoryFence ();

    mXenConsoleInterface->out_prod = Producer;

    XenHypercallEventChannelOp (EVTCHNOP_send, &mXenConsoleEventChain);

  } while (Sent < NumberOfBytes);

  return Sent;
}
Beispiel #16
0
void console_handle_input(evtchn_port_t port, struct pt_regs *regs, void *data)
{
	struct consfront_dev *dev = (struct consfront_dev *) data;
	struct xencons_interface *intf = xencons_interface();
	XENCONS_RING_IDX cons, prod;

	cons = intf->in_cons;
	prod = intf->in_prod;
	mb();
	BUG_ON((prod - cons) > sizeof(intf->in));

	while (cons != prod) {
		xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1, regs);
		cons++;
	}

	mb();
	intf->in_cons = cons;

	notify_daemon(dev);

	xencons_tx();
}
Beispiel #17
0
/* Non-privileged console interrupt routine */
static int
xencons_handler(void *arg)
{
    struct xencons_softc *sc = arg;
    XENCONS_RING_IDX cons, prod, len;
    int s = spltty();

    if (sc->polling) {
        splx(s);
        return 1;
    }


#define XNC_IN (xencons_interface->in)

    cons = xencons_interface->in_cons;
    prod = xencons_interface->in_prod;
    xen_rmb();
    while (cons != prod) {
        if (MASK_XENCONS_IDX(cons, XNC_IN) <
                MASK_XENCONS_IDX(prod, XNC_IN))
            len = MASK_XENCONS_IDX(prod, XNC_IN) -
                  MASK_XENCONS_IDX(cons, XNC_IN);
        else
            len = sizeof(XNC_IN) - MASK_XENCONS_IDX(cons, XNC_IN);

        xencons_tty_input(sc, __UNVOLATILE(
                              &XNC_IN[MASK_XENCONS_IDX(cons, XNC_IN)]), len);
        if (__predict_false(xencons_interface->in_cons != cons)) {
            /* catch up with xenconscn_getc() */
            cons = xencons_interface->in_cons;
            prod = xencons_interface->in_prod;
            xen_rmb();
        } else {
            cons += len;
            xen_wmb();
            xencons_interface->in_cons = cons;
            xen_wmb();
        }
    }
    hypervisor_notify_via_evtchn(xen_start_info.console.domU.evtchn);
    splx(s);
    return 1;
#undef XNC_IN
}
/**
  Read data from serial device and save the datas in buffer.

  Reads NumberOfBytes data bytes from a serial device into the buffer
  specified by Buffer. The number of bytes actually read is returned.
  If Buffer is NULL, then ASSERT().
  If NumberOfBytes is zero, then return 0.

  @param  Buffer           Pointer to the data buffer to store the data read from the serial device.
  @param  NumberOfBytes    Number of bytes which will be read.

  @retval 0                Read data failed, no data is to be read.
  @retval >0               Actual number of bytes read from serial device.

**/
UINTN
EFIAPI
SerialPortRead (
  OUT UINT8     *Buffer,
  IN  UINTN     NumberOfBytes
)
{
  XENCONS_RING_IDX  Consumer, Producer;
  UINTN             Received;

  ASSERT (Buffer != NULL);

  if (NumberOfBytes == 0) {
    return 0;
  }

  if (!mXenConsoleInterface) {
    return 0;
  }

  Consumer = mXenConsoleInterface->in_cons;
  Producer = mXenConsoleInterface->in_prod;

  MemoryFence ();

  Received = 0;
  while (Received < NumberOfBytes && Consumer < Producer)
     Buffer[Received++] = mXenConsoleInterface->in[MASK_XENCONS_IDX(Consumer++, mXenConsoleInterface->in)];

  MemoryFence ();

  mXenConsoleInterface->in_cons = Consumer;

  XenHypercallEventChannelOp (EVTCHNOP_send, &mXenConsoleEventChain);

  return Received;
}
Beispiel #19
0
static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs)
{
	struct xencons_interface *intf = xencons_interface();
	XENCONS_RING_IDX cons, prod;

	cons = intf->in_cons;
	prod = intf->in_prod;
	mb();
	BUG_ON((prod - cons) > sizeof(intf->in));

	while (cons != prod) {
		xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1, regs);
		cons++;
	}

	mb();
	intf->in_cons = cons;

	notify_daemon();

	xencons_tx();

	return IRQ_HANDLED;
}
Beispiel #20
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;
}
Beispiel #21
0
void
xencons_start(struct tty *tp)
{
    struct clist *cl;
    int s;

    s = spltty();
    if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
        goto out;
    tp->t_state |= TS_BUSY;
    splx(s);

    /*
     * We need to do this outside spl since it could be fairly
     * expensive and we don't want our serial ports to overflow.
     */
    cl = &tp->t_outq;
    if (xendomain_is_dom0()) {
        int len, r;
        u_char buf[XENCONS_BURST+1];

        len = q_to_b(cl, buf, XENCONS_BURST);
        while (len > 0) {
            r = HYPERVISOR_console_io(CONSOLEIO_write, len, buf);
            if (r <= 0)
                break;
            len -= r;
        }
    } else {
        XENCONS_RING_IDX cons, prod, len;

#define XNC_OUT (xencons_interface->out)
        cons = xencons_interface->out_cons;
        prod = xencons_interface->out_prod;
        xen_rmb();
        while (prod != cons + sizeof(xencons_interface->out)) {
            if (MASK_XENCONS_IDX(prod, XNC_OUT) <
                    MASK_XENCONS_IDX(cons, XNC_OUT)) {
                len = MASK_XENCONS_IDX(cons, XNC_OUT) -
                      MASK_XENCONS_IDX(prod, XNC_OUT);
            } else {
                len = sizeof(XNC_OUT) -
                      MASK_XENCONS_IDX(prod, XNC_OUT);
            }
            len = q_to_b(cl, __UNVOLATILE(
                             &XNC_OUT[MASK_XENCONS_IDX(prod, XNC_OUT)]), len);
            if (len == 0)
                break;
            prod = prod + len;
        }
        xen_wmb();
        xencons_interface->out_prod = prod;
        xen_wmb();
        hypervisor_notify_via_evtchn(xen_start_info.console.domU.evtchn);
#undef XNC_OUT
    }

    s = spltty();
    tp->t_state &= ~TS_BUSY;
    if (ttypull(tp)) {
        tp->t_state |= TS_TIMEOUT;
        callout_schedule(&tp->t_rstrt_ch, 1);
    }
out:
    splx(s);
}