diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-03-01 13:59:19 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-04-08 18:13:12 +0200 |
commit | 49ab747f668f421138d5b40d83fa279c4c5e278d (patch) | |
tree | 943225a04eac885aed038731adf058f2250a2f40 /hw/xen_console.c | |
parent | ce3b494cb504f96992f2d37ebc8f56deed202b06 (diff) |
hw: move target-independent files to subdirectories
This patch tackles all files that are compiled once, moving
them to subdirectories of hw/.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/xen_console.c')
-rw-r--r-- | hw/xen_console.c | 305 |
1 files changed, 0 insertions, 305 deletions
diff --git a/hw/xen_console.c b/hw/xen_console.c deleted file mode 100644 index efc32320fa..0000000000 --- a/hw/xen_console.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (C) International Business Machines Corp., 2005 - * Author(s): Anthony Liguori <aliguori@us.ibm.com> - * - * Copyright (C) Red Hat 2007 - * - * Xen Console - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; under version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#include <sys/select.h> -#include <fcntl.h> -#include <unistd.h> -#include <termios.h> -#include <stdarg.h> -#include <sys/mman.h> - -#include "hw/hw.h" -#include "char/char.h" -#include "hw/xen/xen_backend.h" - -#include <xen/io/console.h> - -struct buffer { - uint8_t *data; - size_t consumed; - size_t size; - size_t capacity; - size_t max_capacity; -}; - -struct XenConsole { - struct XenDevice xendev; /* must be first */ - struct buffer buffer; - char console[XEN_BUFSIZE]; - int ring_ref; - void *sring; - CharDriverState *chr; - int backlog; -}; - -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_be_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; - } -} - -static void buffer_advance(struct buffer *buffer, size_t len) -{ - buffer->consumed += len; - if (buffer->consumed == buffer->size) { - buffer->consumed = 0; - buffer->size = 0; - } -} - -static int ring_free_bytes(struct XenConsole *con) -{ - struct xencons_interface *intf = con->sring; - XENCONS_RING_IDX cons, prod, space; - - cons = intf->in_cons; - prod = intf->in_prod; - xen_mb(); - - space = prod - cons; - if (space > sizeof(intf->in)) - return 0; /* ring is screwed: ignore it */ - - return (sizeof(intf->in) - space); -} - -static int xencons_can_receive(void *opaque) -{ - struct XenConsole *con = opaque; - return ring_free_bytes(con); -} - -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_be_send_notify(&con->xendev); -} - -static void xencons_send(struct XenConsole *con) -{ - ssize_t len, size; - - size = con->buffer.size - con->buffer.consumed; - if (con->chr) - len = qemu_chr_fe_write(con->chr, con->buffer.data + con->buffer.consumed, - size); - else - len = size; - if (len < 1) { - if (!con->backlog) { - con->backlog = 1; - xen_be_printf(&con->xendev, 1, "backlog piling up, nobody listening?\n"); - } - } else { - buffer_advance(&con->buffer, len); - if (con->backlog && len == size) { - con->backlog = 0; - xen_be_printf(&con->xendev, 1, "backlog is gone\n"); - } - } -} - -/* -------------------------------------------------------------------- */ - -static int con_init(struct XenDevice *xendev) -{ - struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); - char *type, *dom, label[32]; - int ret = 0; - const char *output; - - /* setup */ - dom = xs_get_domain_path(xenstore, con->xendev.dom); - if (!xendev->dev) { - snprintf(con->console, sizeof(con->console), "%s/console", dom); - } else { - snprintf(con->console, sizeof(con->console), "%s/device/console/%d", dom, xendev->dev); - } - free(dom); - - type = xenstore_read_str(con->console, "type"); - if (!type || strcmp(type, "ioemu") != 0) { - xen_be_printf(xendev, 1, "not for me (type=%s)\n", type); - ret = -1; - goto out; - } - - output = xenstore_read_str(con->console, "output"); - - /* no Xen override, use qemu output device */ - if (output == NULL) { - con->chr = serial_hds[con->xendev.dev]; - } else { - snprintf(label, sizeof(label), "xencons%d", con->xendev.dev); - con->chr = qemu_chr_new(label, output, NULL); - } - - xenstore_store_pv_console_info(con->xendev.dev, con->chr); - -out: - g_free(type); - return ret; -} - -static int con_initialise(struct XenDevice *xendev) -{ - struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); - int limit; - - if (xenstore_read_int(con->console, "ring-ref", &con->ring_ref) == -1) - return -1; - if (xenstore_read_int(con->console, "port", &con->xendev.remote_port) == -1) - return -1; - if (xenstore_read_int(con->console, "limit", &limit) == 0) - con->buffer.max_capacity = limit; - - if (!xendev->dev) { - con->sring = xc_map_foreign_range(xen_xc, con->xendev.dom, - XC_PAGE_SIZE, - PROT_READ|PROT_WRITE, - con->ring_ref); - } else { - con->sring = xc_gnttab_map_grant_ref(xendev->gnttabdev, con->xendev.dom, - con->ring_ref, - PROT_READ|PROT_WRITE); - } - if (!con->sring) - return -1; - - xen_be_bind_evtchn(&con->xendev); - if (con->chr) { - if (qemu_chr_fe_claim(con->chr) == 0) { - qemu_chr_add_handlers(con->chr, xencons_can_receive, - xencons_receive, NULL, con); - } else { - xen_be_printf(xendev, 0, - "xen_console_init error chardev %s already used\n", - con->chr->label); - con->chr = NULL; - } - } - - xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n", - con->ring_ref, - con->xendev.remote_port, - con->xendev.local_port, - con->buffer.max_capacity); - return 0; -} - -static void con_disconnect(struct XenDevice *xendev) -{ - struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); - - if (!xendev->dev) { - return; - } - if (con->chr) { - qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL); - qemu_chr_fe_release(con->chr); - } - xen_be_unbind_evtchn(&con->xendev); - - if (con->sring) { - if (!xendev->gnttabdev) { - munmap(con->sring, XC_PAGE_SIZE); - } else { - xc_gnttab_munmap(xendev->gnttabdev, con->sring, 1); - } - con->sring = NULL; - } -} - -static void con_event(struct XenDevice *xendev) -{ - struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); - - buffer_append(con); - if (con->buffer.size - con->buffer.consumed) - xencons_send(con); -} - -/* -------------------------------------------------------------------- */ - -struct XenDevOps xen_console_ops = { - .size = sizeof(struct XenConsole), - .flags = DEVOPS_FLAG_IGNORE_STATE|DEVOPS_FLAG_NEED_GNTDEV, - .init = con_init, - .initialise = con_initialise, - .event = con_event, - .disconnect = con_disconnect, -}; |