Statistics
| Branch: | Revision:

root / hw / virtio-console.c @ a15bb0d6

History | View | Annotate | Download (4.5 kB)

1
/*
2
 * Virtio Console and Generic Serial Port Devices
3
 *
4
 * Copyright Red Hat, Inc. 2009, 2010
5
 *
6
 * Authors:
7
 *  Amit Shah <amit.shah@redhat.com>
8
 *
9
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10
 * the COPYING file in the top-level directory.
11
 */
12

    
13
#include "qemu-char.h"
14
#include "qemu-error.h"
15
#include "virtio-serial.h"
16

    
17
typedef struct VirtConsole {
18
    VirtIOSerialPort port;
19
    CharDriverState *chr;
20
} VirtConsole;
21

    
22

    
23
/* Callback function that's called when the guest sends us data */
24
static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
25
{
26
    VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
27

    
28
    return qemu_chr_write(vcon->chr, buf, len);
29
}
30

    
31
/* Callback function that's called when the guest opens the port */
32
static void guest_open(VirtIOSerialPort *port)
33
{
34
    VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
35

    
36
    qemu_chr_guest_open(vcon->chr);
37
}
38

    
39
/* Callback function that's called when the guest closes the port */
40
static void guest_close(VirtIOSerialPort *port)
41
{
42
    VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
43

    
44
    qemu_chr_guest_close(vcon->chr);
45
}
46

    
47
/* Readiness of the guest to accept data on a port */
48
static int chr_can_read(void *opaque)
49
{
50
    VirtConsole *vcon = opaque;
51

    
52
    return virtio_serial_guest_ready(&vcon->port);
53
}
54

    
55
/* Send data from a char device over to the guest */
56
static void chr_read(void *opaque, const uint8_t *buf, int size)
57
{
58
    VirtConsole *vcon = opaque;
59

    
60
    virtio_serial_write(&vcon->port, buf, size);
61
}
62

    
63
static void chr_event(void *opaque, int event)
64
{
65
    VirtConsole *vcon = opaque;
66

    
67
    switch (event) {
68
    case CHR_EVENT_OPENED:
69
        virtio_serial_open(&vcon->port);
70
        break;
71
    case CHR_EVENT_CLOSED:
72
        virtio_serial_close(&vcon->port);
73
        break;
74
    }
75
}
76

    
77
static int generic_port_init(VirtConsole *vcon, VirtIOSerialPort *port)
78
{
79
    VirtIOSerialPortInfo *info = DO_UPCAST(VirtIOSerialPortInfo, qdev,
80
                                           vcon->port.dev.info);
81

    
82
    if (vcon->chr) {
83
        qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
84
                              vcon);
85
        info->have_data = flush_buf;
86
        info->guest_open = guest_open;
87
        info->guest_close = guest_close;
88
    }
89
    return 0;
90
}
91

    
92
/* Virtio Console Ports */
93
static int virtconsole_initfn(VirtIOSerialPort *port)
94
{
95
    VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
96

    
97
    return generic_port_init(vcon, port);
98
}
99

    
100
static int virtconsole_exitfn(VirtIOSerialPort *port)
101
{
102
    VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
103

    
104
    if (vcon->chr) {
105
        /*
106
         * Instead of closing the chardev, free it so it can be used
107
         * for other purposes.
108
         */
109
        qemu_chr_add_handlers(vcon->chr, NULL, NULL, NULL, NULL);
110
    }
111

    
112
    return 0;
113
}
114

    
115
static VirtIOSerialPortInfo virtconsole_info = {
116
    .qdev.name     = "virtconsole",
117
    .qdev.size     = sizeof(VirtConsole),
118
    .is_console    = true,
119
    .init          = virtconsole_initfn,
120
    .exit          = virtconsole_exitfn,
121
    .qdev.props = (Property[]) {
122
        DEFINE_PROP_UINT32("nr", VirtConsole, port.id, VIRTIO_CONSOLE_BAD_ID),
123
        DEFINE_PROP_CHR("chardev", VirtConsole, chr),
124
        DEFINE_PROP_STRING("name", VirtConsole, port.name),
125
        DEFINE_PROP_END_OF_LIST(),
126
    },
127
};
128

    
129
static void virtconsole_register(void)
130
{
131
    virtio_serial_port_qdev_register(&virtconsole_info);
132
}
133
device_init(virtconsole_register)
134

    
135
/* Generic Virtio Serial Ports */
136
static int virtserialport_initfn(VirtIOSerialPort *port)
137
{
138
    VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
139

    
140
    if (port->id == 0) {
141
        /*
142
         * Disallow a generic port at id 0, that's reserved for
143
         * console ports.
144
         */
145
        error_report("Port number 0 on virtio-serial devices reserved for virtconsole devices for backward compatibility.");
146
        return -1;
147
    }
148
    return generic_port_init(vcon, port);
149
}
150

    
151
static VirtIOSerialPortInfo virtserialport_info = {
152
    .qdev.name     = "virtserialport",
153
    .qdev.size     = sizeof(VirtConsole),
154
    .init          = virtserialport_initfn,
155
    .exit          = virtconsole_exitfn,
156
    .qdev.props = (Property[]) {
157
        DEFINE_PROP_UINT32("nr", VirtConsole, port.id, VIRTIO_CONSOLE_BAD_ID),
158
        DEFINE_PROP_CHR("chardev", VirtConsole, chr),
159
        DEFINE_PROP_STRING("name", VirtConsole, port.name),
160
        DEFINE_PROP_END_OF_LIST(),
161
    },
162
};
163

    
164
static void virtserialport_register(void)
165
{
166
    virtio_serial_port_qdev_register(&virtserialport_info);
167
}
168
device_init(virtserialport_register)