qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Alexander Graf <agraf@suse.de>
To: Jens Freimann <jfrei@de.ibm.com>
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>,
	Jens Freimann <jfrei@linux.vnet.ibm.com>,
	Heinz Graalfs <graalfs@linux.vnet.ibm.com>,
	qemu-devel <qemu-devel@nongnu.org>
Subject: Re: [Qemu-devel] [PATCH 7/8] s390: Add SCLP vt220 console support
Date: Tue, 12 Jun 2012 13:52:21 +0200	[thread overview]
Message-ID: <4FD72D75.4050907@suse.de> (raw)
In-Reply-To: <1338984323-21914-8-git-send-email-jfrei@de.ibm.com>

On 06/06/2012 02:05 PM, Jens Freimann wrote:
> From: Heinz Graalfs<graalfs@linux.vnet.ibm.com>
>
> Adds console support (in vt220 mode).
> In order to run qemu exploiting the SCLP's console functionality in vt220 mode
> the user has to specify the following console related parameters:
>
>   -chardev stdio,id=charconsole0 -device sclpconsole,chardev=charconsole0,id=console0
>
> Signed-off-by: Heinz Graalfs<graalfs@linux.vnet.ibm.com>
> Signed-off-by: Jens Freimann<jfrei@linux.vnet.ibm.com>
> ---
>   hw/s390-event-facility.c |  209 ++++++++++++++++++++++++++++++++++++++++++++++
>   hw/s390-event-facility.h |    8 ++
>   hw/s390-sclp.c           |  177 ++++++++++++++++++++++++++++++++++++++-
>   hw/s390-sclp.h           |   22 ++++-
>   sysemu.h                 |    1 +
>   target-s390x/op_helper.c |    6 ++
>   vl.c                     |   41 +++++++++
>   7 files changed, 460 insertions(+), 4 deletions(-)
>
> diff --git a/hw/s390-event-facility.c b/hw/s390-event-facility.c
> index b8106a6..cfa5dd4 100644
> --- a/hw/s390-event-facility.c
> +++ b/hw/s390-event-facility.c
> @@ -16,6 +16,11 @@
>   #include "s390-sclp.h"
>   #include "s390-event-facility.h"
>
> +qemu_irq sclp_read_vt220;
> +
> +static int size_buffer = 4096;
> +static char *sclp_console_data_vt220;

Globals?

> +
>   struct SCLPDevice {
>       const char *name;
>       bool vm_running;
> @@ -224,9 +229,213 @@ static TypeInfo sclp_quiesce_info = {
>       .class_init    = sclpef_quiesce_class_init,
>   };
>
> +/* ----------- SCLP VT220 console ------------ */
> +
> +static void s390_signal_read_vt220(void *opaque, int n, int level)
> +{
> +    sclp_enable_signal_read_vt220();
> +    sclp_service_interrupt(opaque, 0);
> +}
> +
> +static void sclpef_set_console(SCLPEvent *event)
> +{
> +    if (event->id == ID_VT220) {
> +        sclp_read_vt220 = *qemu_allocate_irqs(s390_signal_read_vt220,
> +            event->evt_fac->opaque, 1);
> +    }
> +}
> +
> +void sclpef_write_console_vt220(SCLPDevice *sdev, char *buf)
> +{
> +    DeviceState *dev;
> +    SCLPEventFacility *event_facility;
> +    static SCLPEvent *event;
> +    static SCLPEventClass *cons;
> +
> +    event_facility = DO_UPCAST(SCLPEventFacility, sdev, sdev);
> +
> +    if (!cons) {
> +        QTAILQ_FOREACH(dev,&event_facility->sbus.qbus.children, sibling) {
> +            event = (SCLPEvent *) dev;
> +            if (event->id == ID_VT220) {
> +                cons = SCLP_EVENT_GET_CLASS(event);
> +                assert(cons->have_data);
> +                break;
> +            }
> +        }
> +    }

I don't understand the above code. Why do you have to search for 
anything when you're in a call to process a write?

> +    if (cons) {
> +        cons->have_data(event, (const uint8_t *)buf, strlen(buf));
> +    }
> +}
> +
> +char *sclpef_get_console_data_vt220(SCLPDevice *sdev)
> +{
> +    DeviceState *dev;
> +    SCLPEventFacility *event_facility;
> +    SCLPEvent *event = NULL;
> +    static SCLPEventClass *cons;
> +
> +    event_facility = DO_UPCAST(SCLPEventFacility, sdev, sdev);
> +
> +    if (!cons) {
> +        QTAILQ_FOREACH(dev,&event_facility->sbus.qbus.children, sibling) {
> +            event = (SCLPEvent *) dev;
> +            if (event->id == ID_VT220) {
> +                cons = SCLP_EVENT_GET_CLASS(event);
> +                assert(cons->get_data);
> +                break;
> +            }
> +        }
> +    }

See above.

> +    if (cons) {
> +        return cons->get_data();
> +    }
> +    return NULL;
> +}
> +
> +static char *console_data_vt220(void)
> +{
> +    return sclp_console_data_vt220;
> +}
> +
> +static ssize_t flush_buf(SCLPEvent *event, const uint8_t *buf, size_t len)
> +{
> +    SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
> +    ssize_t ret;
> +
> +    if (!scon->chr) {
> +        /* If there's no backend, we can just say we consumed all data. */
> +        return len;
> +    }
> +
> +    ret = qemu_chr_fe_write(scon->chr, buf, len);
> +
> +    if (ret<  0) {
> +        /* see virtio-console comments */
> +        ret = 0;
> +    }
> +
> +    return ret;
> +}
> +
> +static void guest_open(SCLPEvent *event)
> +{
> +    SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
> +
> +    if (!scon->chr) {
> +        return;
> +    }
> +    qemu_chr_fe_open(scon->chr);
> +}
> +
> +static void guest_close(SCLPEvent *event)
> +{
> +    SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
> +
> +    if (!scon->chr) {
> +        return;
> +    }
> +    qemu_chr_fe_close(scon->chr);
> +}
> +
> +static int chr_can_read(void *opaque)
> +{
> +    return 1;
> +}
> +
> +static void chr_read_vt220(void *opaque, const uint8_t *buf, int size)
> +{
> +    char *offset;
> +
> +    if (!sclp_console_data_vt220) {
> +        size_buffer = 2 * size;

Why 2*?

> +        sclp_console_data_vt220 = malloc(size_buffer);

%s/malloc/g_malloc0/g

> +    }
> +    if (size_buffer<  size + 1) {

This could use a comment.

> +        free(sclp_console_data_vt220);
> +        size_buffer = 2 * size;
> +        sclp_console_data_vt220 = malloc(size_buffer);
> +    }
> +    offset = sclp_console_data_vt220;
> +    if (offset) {
> +        memcpy(offset, buf, size);
> +        offset += size;
> +        *offset = '\0';

How do you know you're not out of bounds?

> +        qemu_irq_raise(sclp_read_vt220);
> +    } else {
> +        size_buffer = 0;
> +    }
> +}
> +
> +static void chr_event(void *opaque, int event)
> +{
> +    switch (event) {
> +    case CHR_EVENT_OPENED:
> +        if (!sclp_console_data_vt220) {
> +            sclp_console_data_vt220 = malloc(size_buffer);
> +        }
> +        break;
> +    case CHR_EVENT_CLOSED:
> +        break;
> +    }
> +}
> +
> +static unsigned int send_mask_vt220(void)
> +{
> +    return SCLP_EVENT_MASK_MSG_ASCII;
> +}
> +
> +static unsigned int receive_mask_vt220(void)
> +{
> +    return SCLP_EVENT_MASK_MSG_ASCII;
> +}
> +
> +static int sclpconsole_initfn_vt220(SCLPEvent *event)
> +{
> +    SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
> +
> +    event->id = ID_VT220;
> +    sclpef_set_console(event);
> +    if (scon->chr) {
> +        qemu_chr_add_handlers(scon->chr, chr_can_read,
> +                chr_read_vt220, chr_event, scon);
> +    }
> +
> +    return 0;
> +}
> +
> +static Property sclpconsole_properties[] = {
> +    DEFINE_PROP_CHR("chardev", SCLPConsole, chr),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void sclpconsole_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    SCLPEventClass *k = SCLP_EVENT_CLASS(klass);
> +
> +    k->init = sclpconsole_initfn_vt220;
> +    k->have_data = flush_buf;
> +    k->guest_open = guest_open;
> +    k->guest_close = guest_close;
> +    k->get_send_mask = send_mask_vt220;
> +    k->get_receive_mask = receive_mask_vt220;
> +    k->get_data = console_data_vt220;
> +    dc->props = sclpconsole_properties;
> +}
> +
> +static TypeInfo sclpconsole_info = {
> +    .name          = "sclpconsole",
> +    .parent        = TYPE_SCLP_EVENT,
> +    .instance_size = sizeof(SCLPConsole),
> +    .class_init    = sclpconsole_class_init,
> +};
> +
>   static void sclpef_register_types(void)
>   {
>       type_register_static(&sclp_event_facility_type_info);
>       type_register_static(&sclp_quiesce_info);
> +    type_register_static(&sclpconsole_info);
>   }
>   type_init(sclpef_register_types)
> diff --git a/hw/s390-event-facility.h b/hw/s390-event-facility.h
> index 40d4049..d6bde7d 100644
> --- a/hw/s390-event-facility.h
> +++ b/hw/s390-event-facility.h
> @@ -14,6 +14,7 @@
>   #include "qemu-common.h"
>
>   #define ID_QUIESCE SCLP_EVENT_SIGNAL_QUIESCE
> +#define ID_VT220   SCLP_EVENT_ASCII_CONSOLE_DATA
>
>   #define TYPE_SCLP_EVENT "s390-sclp-event-type"
>   #define SCLP_EVENT(obj) \
> @@ -34,6 +35,11 @@ typedef struct SCLPEventClass {
>       int (*exit)(SCLPEvent *event);
>       unsigned int (*get_send_mask)(void);
>       unsigned int (*get_receive_mask)(void);
> +    void (*guest_open)(SCLPEvent *event);
> +    void (*guest_close)(SCLPEvent *event);
> +    void (*guest_ready)(SCLPEvent *event);
> +    ssize_t (*have_data)(SCLPEvent *event, const uint8_t *buf, size_t len);
> +    char *(*get_data)(void);
>   } SCLPEventClass;
>
>   struct SCLPEvent {
> @@ -50,5 +56,7 @@ void sclpef_enable_irqs(SCLPDevice *sdev, void *opaque);
>   void sclpef_set_masks(void);
>   unsigned int sclpef_send_mask(SCLPDevice *sdev);
>   unsigned int sclpef_receive_mask(SCLPDevice *sdev);
> +void sclpef_write_console_vt220(SCLPDevice *sdev, char *buf);
> +char *sclpef_get_console_data_vt220(SCLPDevice *sdev);
>
>   #endif
> diff --git a/hw/s390-sclp.c b/hw/s390-sclp.c
> index 683a709..8f45773 100644
> --- a/hw/s390-sclp.c
> +++ b/hw/s390-sclp.c
> @@ -11,6 +11,11 @@
>   #include "hw/s390-sclp.h"
>   #include "hw/s390-event-facility.h"
>
> +/* input buffer handling */
> +#define INP_BUFFER_SIZE 4096
> +static int sclp_curr_buf_size;
> +static char *sclp_input_vt220;
> +
>   /* Host capabilites */
>   static unsigned int sclp_send_mask;
>   static unsigned int sclp_receive_mask;
> @@ -21,6 +26,7 @@ static unsigned int sclp_cp_receive_mask;
>
>   static int quiesce;
>   static int event_pending;
> +static int vt220;

If anything, this is a machine variable, no? What is this supposed to 
express?

>
>   int sclp_read_info(CPUS390XState *env, struct sccb *sccb)
>   {
> @@ -66,6 +72,7 @@ void sclp_enable_signal_quiesce(void)
>   {
>       quiesce = 1;
>       event_pending = 1;
> +    vt220 = 0;
>   }
>
>   static void sclp_set_masks(void)
> @@ -81,7 +88,112 @@ static void sclp_set_masks(void)
>
>       sclp_send_mask = sclpef_send_mask(evt_fac->sdev);
>       sclp_receive_mask = sclpef_receive_mask(evt_fac->sdev);
> - }
> +}
> +
> +static int signal_vt220_event(struct sccb *sccb, int *slen)
> +{
> +    char *p;
> +
> +    if (!sclp_input_vt220 || !vt220) {
> +        return 0;
> +    }
> +
> +    int l = strlen(sclp_input_vt220);
> +
> +    if (*slen<  sizeof(struct ascii_cons_data_command) + l + 1) {
> +        event_pending = 1;
> +        return 0;
> +    }
> +    p = (char *)&sccb->c.read.acd_cmd.data;
> +    /* first byte is hex 0 saying an ascii string follows */
> +    *p++ = '\0';
> +    memmove(p, sclp_input_vt220, l);
> +    *sclp_input_vt220 = '\0';
> +
> +    sccb->c.read.acd_cmd.h.length =
> +            cpu_to_be16(sizeof(struct ascii_cons_data_command) + l + 1);
> +    sccb->c.read.acd_cmd.h.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
> +
> +    vt220 = 0;
> +    *slen -= sizeof(struct ascii_cons_data_command) + l + 1;
> +    return 1;
> +}
> +
> +static char *grow_buffer(int size)
> +{
> +    char *p = (char *) malloc(size);
> +
> +    if (!p) {
> +        sclp_curr_buf_size = 0;
> +        return NULL;
> +    }
> +    memset(p, '\0', size);
> +    sclp_curr_buf_size = size;
> +    return p;
> +}
> +
> +static int sclp_write_vt220(struct event_buffer_header *event)
> +{
> +    int l;
> +    char *msg;
> +    SCLPS390EventFacility *evt_fac;
> +    struct ascii_cons_data_command *ad =
> +            (struct ascii_cons_data_command *) event;
> +
> +    assert(sclp_bus);
> +
> +    l = event->length - sizeof(struct event_buffer_header);
> +    msg = (char *) malloc(l + 1);
> +    assert(msg);
> +    memset(msg, '\0', l + 1);
> +    memmove(msg, ad->data, l);

Why the copy? Also, for such short lived data, you're probably better 
off using alloca.

> +
> +    evt_fac = sclp_bus->event_facility;
> +    sclpef_write_console_vt220(evt_fac->sdev, msg);
> +
> +    free(msg);
> +
> +    return SCLP_RC_NORMAL_COMPLETION;
> +}
> +
> +void sclp_enable_signal_read_vt220(void)
> +{
> +    int len;
> +    char *input;
> +    SCLPS390EventFacility *evt_fac;
> +
> +    if (!sclp_bus) {
> +        return;
> +    }
> +    evt_fac = sclp_bus->event_facility;
> +
> +    assert(evt_fac);
> +
> +    input = sclpef_get_console_data_vt220(evt_fac->sdev);
> +
> +    if (!input) {
> +        return;
> +    }
> +
> +    vt220 = 1;
> +    quiesce = 0;
> +    event_pending = 1;
> +    len = strlen((char *) input);
> +    if (sclp_input_vt220 == NULL) {
> +        /* get new buffer */
> +        sclp_input_vt220 = grow_buffer(2 * len + 1);
> +    } else {
> +        if (len>= sclp_curr_buf_size) {
> +            /* get larger buffer */
> +            char *p = grow_buffer(2 * len + 1);
> +            free(sclp_input_vt220);
> +            sclp_input_vt220 = p;
> +        }
> +    }
> +    if (sclp_input_vt220) {
> +        strcat(sclp_input_vt220, (char *)input);
> +    }
> +}
>
>   int sclp_read_event_data(CPUS390XState *env, struct sccb *sccb)
>   {
> @@ -99,7 +211,8 @@ int sclp_read_event_data(CPUS390XState *env, struct sccb *sccb)
>           break;
>       case SCLP_SELECTIVE_READ:
>           if (!(sclp_cp_receive_mask&  be32_to_cpu(sccb->c.read.mask))) {
> -            sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SELECTION_MASK);
> +            sccb->h.response_code =
> +                    cpu_to_be16(SCLP_RC_INVALID_SELECTION_MASK);
>               goto out;
>           }
>           sclp_active_selection_mask = be32_to_cpu(sccb->c.read.mask);
> @@ -117,7 +230,12 @@ int sclp_read_event_data(CPUS390XState *env, struct sccb *sccb)
>               sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_COMPLETION);
>           }
>       }
> -
> +    if (sclp_active_selection_mask&  SCLP_EVENT_MASK_MSG_ASCII) {
> +        if (signal_vt220_event(sccb,&slen)) {
> +            sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_COMPLETION);
> +            sccb->h.length = cpu_to_be16(SCCB_SIZE - slen);
> +        }
> +    }
>       if (sccb->h.control_mask[2]&  SCLP_VARIABLE_LENGTH_RESPONSE) {
>           sccb->h.control_mask[2]&= ~SCLP_VARIABLE_LENGTH_RESPONSE;
>           sccb->h.length = cpu_to_be16(SCCB_SIZE - slen);
> @@ -127,6 +245,59 @@ out:
>       return 0;
>   }
>
> +int sclp_write_event_data(CPUS390XState *env, struct sccb *sccb)
> +{
> +    struct event_buffer_header *event;
> +    int slen;
> +    unsigned elen = 0;
> +
> +    if (sccb->h.function_code != SCLP_FC_NORMAL_WRITE) {
> +        sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_FUNCTION);
> +        goto out;
> +    }
> +    if (be16_to_cpu(sccb->h.length)<  8) {
> +        sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
> +        goto out;
> +    }
> +
> +    /* first check the sum of all events */
> +    event =&sccb->c.event;
> +    for (slen = be16_to_cpu(sccb->h.length) - sizeof(sccb->h);
> +         slen>  0; slen -= elen) {
> +        elen = be16_to_cpu(event->length);
> +        if (elen<  sizeof(*event) || elen>  slen) {
> +            sccb->h.response_code =
> +                    cpu_to_be16(SCLP_RC_EVENT_BUFFER_SYNTAX_ERROR);
> +            goto out;
> +        }
> +        event = (void *) event + elen;
> +    }
> +    if (slen) {
> +        sccb->h.response_code = cpu_to_be16(SCLP_RC_INCONSISTENT_LENGTHS);
> +        goto out;
> +    }
> +
> +    /* the execute */
> +    event =&sccb->c.event;
> +    for (slen = be16_to_cpu(sccb->h.length) - sizeof(sccb->h);
> +         slen>  0; slen -= elen) {
> +        elen = be16_to_cpu(event->length);
> +        switch (event->type) {
> +        case SCLP_EVENT_ASCII_CONSOLE_DATA:
> +            sccb->h.response_code = cpu_to_be16(sclp_write_vt220(event));
> +            break;

This also screams for a generic dispatcher.

> +        default:
> +            sccb->h.response_code = SCLP_RC_INVALID_FUNCTION;
> +            break;
> +        }
> +        event = (void *) event + elen;
> +    }
> +    sccb->h.response_code = SCLP_RC_NORMAL_COMPLETION;
> +
> +out:
> +    return 0;
> +}
> +
>   int sclp_write_event_mask(CPUS390XState *env, struct sccb *sccb)
>   {
>       /* Attention: We assume that Linux uses 4-byte masks, what it actually
> diff --git a/hw/s390-sclp.h b/hw/s390-sclp.h
> index f61421b..c86bca8 100644
> --- a/hw/s390-sclp.h
> +++ b/hw/s390-sclp.h
> @@ -7,6 +7,8 @@
>   /* SCLP command codes */
>   #define SCLP_CMDW_READ_SCP_INFO                 0x00020001
>   #define SCLP_CMDW_READ_SCP_INFO_FORCED          0x00120001
> +#define SCLP_CMD_READ_EVENT_DATA                0x00770005
> +#define SCLP_CMD_WRITE_EVENT_DATA               0x00760005
>   #define SCLP_CMD_WRITE_EVENT_MASK               0x00780005
>
>   /* SCLP response codes */
> @@ -20,11 +22,12 @@
>   #define SCLP_RC_INVALID_MASK_LENGTH             0x74f0
>
>   /* SCLP event types */
> +#define SCLP_EVENT_ASCII_CONSOLE_DATA           0x1a
>   #define SCLP_EVENT_SIGNAL_QUIESCE               0x1d
>
>   /* SCLP event masks */
>   #define SCLP_EVENT_MASK_SIGNAL_QUIESCE          0x00000008
> -#define SCLP_EVENT_MASK_MSG                     0x40000000
> +#define SCLP_EVENT_MASK_MSG_ASCII               0x00000040
>
>   #define SCLP_UNCONDITIONAL_READ                 0x00
>   #define SCLP_SELECTIVE_READ                     0x01
> @@ -44,6 +47,13 @@ struct write_event_mask {
>       uint32_t receive_mask;
>   } __attribute__((packed));
>
> +struct mdb_header {
> +    uint16_t length;
> +    uint16_t type;
> +    uint32_t tag;
> +    uint32_t revision_code;
> +} __attribute__((packed));
> +
>   struct event_buffer_header {
>       uint16_t length;
>       uint8_t  type;
> @@ -58,9 +68,15 @@ struct signal_quiesce {
>       uint8_t unit;
>   } __attribute__((packed));
>
> +struct ascii_cons_data_command {
> +    struct event_buffer_header h;
> +    char data[0];
> +} __attribute__((packed));
> +
>   struct read_event_data {
>       union {
>           struct signal_quiesce quiesce;
> +        struct ascii_cons_data_command acd_cmd;
>           uint32_t mask;
>       };
>   } __attribute__((packed));
> @@ -84,15 +100,19 @@ struct sccb {
>       struct sccb_header h;
>       union {
>           struct read_info_sccb read_info;
> +        struct event_buffer_header event;
>           struct read_event_data read;
> +        struct ascii_cons_data_command acd_cmd;
>           struct write_event_mask we_mask;
>           char data[SCCB_DATA_LEN];
>       } c;
>    } __attribute__((packed));
>
>   void sclp_enable_signal_quiesce(void);
> +void sclp_enable_signal_read_vt220(void);
>   int sclp_read_info(CPUS390XState *env, struct sccb *sccb);
>   int sclp_read_event_data(CPUS390XState *env, struct sccb *sccb);
> +int sclp_write_event_data(CPUS390XState *env, struct sccb *sccb);
>   int sclp_write_event_mask(CPUS390XState *env, struct sccb *sccb);
>   void sclp_service_interrupt(CPUS390XState *env, uint32_t sccb);
>
> diff --git a/sysemu.h b/sysemu.h
> index bc2c788..b4d399c 100644
> --- a/sysemu.h
> +++ b/sysemu.h
> @@ -62,6 +62,7 @@ int qemu_powerdown_requested(void);
>   void qemu_system_killed(int signal, pid_t pid);
>   void qemu_kill_report(void);
>   extern qemu_irq qemu_system_powerdown;
> +extern qemu_irq sclp_read_vt220;
>   void qemu_system_reset(bool report);
>
>   void qemu_add_exit_notifier(Notifier *notify);
> diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
> index 3e5eff4..4d49472 100644
> --- a/target-s390x/op_helper.c
> +++ b/target-s390x/op_helper.c
> @@ -2391,6 +2391,12 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
>           case SCLP_CMDW_READ_SCP_INFO_FORCED:
>               r = sclp_read_info(env,&work_sccb);
>               break;
> +        case SCLP_CMD_READ_EVENT_DATA:
> +            r = sclp_read_event_data(env,&work_sccb);
> +            break;
> +        case SCLP_CMD_WRITE_EVENT_DATA:
> +            r = sclp_write_event_data(env,&work_sccb);
> +            break;
>           case SCLP_CMD_WRITE_EVENT_MASK:
>               r = sclp_write_event_mask(env,&work_sccb);
>               break;
> diff --git a/vl.c b/vl.c
> index 23ab3a3..aba7ab0 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -174,6 +174,7 @@ int main(int argc, char **argv)
>   #define DEFAULT_RAM_SIZE 128
>
>   #define MAX_VIRTIO_CONSOLES 1
> +#define MAX_SCLP_CONSOLES   1
>
>   static const char *data_dir;
>   const char *bios_name = NULL;
> @@ -201,6 +202,7 @@ int no_quit = 0;
>   CharDriverState *serial_hds[MAX_SERIAL_PORTS];
>   CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
>   CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
> +CharDriverState *sclpcon_hds[MAX_SCLP_CONSOLES];
>   int win2k_install_hack = 0;
>   int usb_enabled = 0;
>   int singlestep = 0;
> @@ -274,6 +276,8 @@ static int default_floppy = 1;
>   static int default_cdrom = 1;
>   static int default_sdcard = 1;
>   static int default_vga = 1;
> +static int default_sclpcon = 1;
> +static int default_loader = 1;
>
>   static struct {
>       const char *driver;
> @@ -295,6 +299,8 @@ static struct {
>       { .driver = "isa-cirrus-vga",       .flag =&default_vga       },
>       { .driver = "vmware-svga",          .flag =&default_vga       },
>       { .driver = "qxl-vga",              .flag =&default_vga       },
> +    { .driver = "s390-sclp",            .flag =&default_sclpcon   },
> +    { .driver = "s390-ipl",             .flag =&default_loader    },
>   };
>
>   static void res_free(void)
> @@ -1942,6 +1948,7 @@ struct device_config {
>           DEV_VIRTCON,   /* -virtioconsole */
>           DEV_DEBUGCON,  /* -debugcon */
>           DEV_GDB,       /* -gdb, -s */
> +        DEV_SCLPCON,   /* sclp console */
>       } type;
>       const char *cmdline;
>       Location loc;
> @@ -2058,6 +2065,36 @@ static int virtcon_parse(const char *devname)
>       return 0;
>   }
>
> +static int sclpcon_parse(const char *devname)
> +{
> +    QemuOptsList *device = qemu_find_opts("device");
> +    static int index;
> +    char label[32];
> +    QemuOpts *dev_opts;
> +
> +    if (strcmp(devname, "none") == 0)
> +        return 0;

Apart from that part not passing checkpatch, why do we have to 
reimplement this for every char device?


Alex

> +    if (index == MAX_SCLP_CONSOLES) {
> +        fprintf(stderr, "qemu: too many sclp consoles\n");
> +        exit(1);
> +    }
> +
> +    dev_opts = qemu_opts_create(device, NULL, 0);
> +    qemu_opt_set(dev_opts, "driver", "sclpconsole");
> +
> +    snprintf(label, sizeof(label), "sclpcon%d", index);
> +    sclpcon_hds[index] = qemu_chr_new(label, devname, NULL);
> +    if (!sclpcon_hds[index]) {
> +        fprintf(stderr, "qemu: could not open sclp console '%s': %s\n",
> +                devname, strerror(errno));
> +        return -1;
> +    }
> +    qemu_opt_set(dev_opts, "chardev", label);
> +
> +    index++;
> +    return 0;
> +}
> +
>   static int debugcon_parse(const char *devname)
>   {
>       QemuOpts *opts;
> @@ -3304,6 +3341,8 @@ int main(int argc, char **argv, char **envp)
>               add_device_config(DEV_SERIAL, "mon:stdio");
>           } else if (default_virtcon&&  default_monitor) {
>               add_device_config(DEV_VIRTCON, "mon:stdio");
> +        } else if (default_sclpcon&&  default_monitor) {
> +            add_device_config(DEV_SCLPCON, "mon:stdio");
>           } else {
>               if (default_serial)
>                   add_device_config(DEV_SERIAL, "stdio");
> @@ -3491,6 +3530,8 @@ int main(int argc, char **argv, char **envp)
>           exit(1);
>       if (foreach_device_config(DEV_VIRTCON, virtcon_parse)<  0)
>           exit(1);
> +    if (foreach_device_config(DEV_SCLPCON, sclpcon_parse)<  0)
> +        exit(1);
>       if (foreach_device_config(DEV_DEBUGCON, debugcon_parse)<  0)
>           exit(1);
>

  reply	other threads:[~2012-06-12 11:52 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-06-06 12:05 [Qemu-devel] [PATCH 0/8] s390: SCLP console and misc Jens Freimann
2012-06-06 12:05 ` [Qemu-devel] [PATCH 1/8] s390: add new define for KVM_CAP_S390_COW Jens Freimann
2012-06-06 12:05 ` [Qemu-devel] [PATCH 2/8] s390: autodetect map private Jens Freimann
2012-06-12  9:32   ` Alexander Graf
2012-06-12 11:20     ` Christian Borntraeger
2012-06-12 11:57       ` Alexander Graf
2012-06-12 12:02         ` Christian Borntraeger
2012-06-12 12:12           ` Alexander Graf
2012-06-13 10:30             ` Jan Kiszka
2012-06-13 10:54               ` Alexander Graf
2012-06-13 10:58                 ` Jan Kiszka
2012-06-13 11:27                   ` Christian Borntraeger
2012-06-13 11:41                     ` Jan Kiszka
2012-06-13 12:33                       ` Alexander Graf
2012-06-13 12:35                         ` Jan Kiszka
2012-06-15 14:01                           ` [Qemu-devel] Next version of memory allocation fixup Christian Borntraeger
2012-06-15 14:01                             ` [Qemu-devel] [PatchV2] s390: autodetect map private Christian Borntraeger
2012-06-15 15:10                             ` [Qemu-devel] One more fix Christian Borntraeger
2012-06-15 15:10                               ` [Qemu-devel] [PATCH v3] s390: autodetect map private Christian Borntraeger
2012-06-15 17:01                                 ` Jan Kiszka
2012-06-18 13:44                                 ` Alexander Graf
2012-06-06 12:05 ` [Qemu-devel] [PATCH 3/8] s390: make kvm_stat work on s390 Jens Freimann
2012-06-06 12:05 ` [Qemu-devel] [PATCH 4/8] s390: stop target cpu on sigp initial reset Jens Freimann
2012-06-12  9:42   ` Alexander Graf
2012-06-12 10:15     ` Christian Borntraeger
2012-06-06 12:05 ` [Qemu-devel] [PATCH 5/8] s390: Cleanup sclp functions Jens Freimann
2012-06-12  9:58   ` Alexander Graf
2012-06-12 10:07     ` Christian Borntraeger
2012-06-12 10:09       ` Alexander Graf
2012-06-12 10:10       ` Alexander Graf
2012-06-12 12:24     ` Christian Borntraeger
2012-06-12 12:32       ` Alexander Graf
2012-06-12 22:41         ` Anthony Liguori
2012-06-12 22:38   ` Anthony Liguori
2012-06-06 12:05 ` [Qemu-devel] [PATCH 6/8] s390: sclp event facility and signal quiesce support via system_powerdown Jens Freimann
2012-06-12 11:38   ` Alexander Graf
2012-06-13  7:00     ` Heinz Graalfs
2012-06-13 13:12       ` Andreas Färber
2012-06-06 12:05 ` [Qemu-devel] [PATCH 7/8] s390: Add SCLP vt220 console support Jens Freimann
2012-06-12 11:52   ` Alexander Graf [this message]
2012-06-13  7:27     ` Heinz Graalfs
2012-06-13  7:53       ` Alexander Graf
2012-06-06 12:05 ` [Qemu-devel] [PATCH 8/8] s390: Fix the storage increment size calculation Jens Freimann
2012-06-12 11:53   ` Alexander Graf
2012-06-12 14:57     ` Jeng-fang Wang
2012-06-18 13:46       ` Alexander Graf
2012-06-18 19:30         ` Christian Borntraeger
2012-06-18 12:35 ` [Qemu-devel] [PATCH 0/8] s390: SCLP console and misc Christian Borntraeger
2012-06-18 13:33   ` Alexander Graf
2012-06-18 13:41     ` Christian Borntraeger
2012-06-18 13:51       ` Alexander Graf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4FD72D75.4050907@suse.de \
    --to=agraf@suse.de \
    --cc=cornelia.huck@de.ibm.com \
    --cc=graalfs@linux.vnet.ibm.com \
    --cc=jfrei@de.ibm.com \
    --cc=jfrei@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).