blob: 9ea9223c5c5cd38c14e546dc388f70b3fd9be8d5 [file] [log] [blame]
Rusty Russella23ea922010-01-18 19:14:55 +05301/*
2 * Copyright (C) 2006, 2007, 2009 Rusty Russell, IBM Corporation
Rusty Russell31610432007-10-22 11:03:39 +10003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#include <linux/err.h>
19#include <linux/init.h>
20#include <linux/virtio.h>
21#include <linux/virtio_console.h>
22#include "hvc_console.h"
23
Rusty Russell21206ed2010-01-18 19:15:00 +053024struct port {
25 struct virtqueue *in_vq, *out_vq;
26 struct virtio_device *vdev;
27 /* This is our input buffer, and how much data is left in it. */
28 char *inbuf;
29 unsigned int used_len, offset;
Rusty Russell31610432007-10-22 11:03:39 +100030
Rusty Russell21206ed2010-01-18 19:15:00 +053031 /* The hvc device */
32 struct hvc_struct *hvc;
33};
Rusty Russell31610432007-10-22 11:03:39 +100034
Rusty Russell21206ed2010-01-18 19:15:00 +053035/* We have one port ready to go immediately, for a console. */
36static struct port console;
Christian Borntraeger91fcad12008-06-20 15:24:15 +020037
Rusty Russell971f3392010-01-18 19:14:56 +053038/* This is the very early arch-specified put chars function. */
39static int (*early_put_chars)(u32, const char *, int);
40
Rusty Russella23ea922010-01-18 19:14:55 +053041/*
42 * The put_chars() callback is pretty straightforward.
Rusty Russell31610432007-10-22 11:03:39 +100043 *
Rusty Russella23ea922010-01-18 19:14:55 +053044 * We turn the characters into a scatter-gather list, add it to the
45 * output queue and then kick the Host. Then we sit here waiting for
46 * it to finish: inefficient in theory, but in practice
47 * implementations will do it immediately (lguest's Launcher does).
48 */
Rusty Russell31610432007-10-22 11:03:39 +100049static int put_chars(u32 vtermno, const char *buf, int count)
50{
51 struct scatterlist sg[1];
52 unsigned int len;
Rusty Russell21206ed2010-01-18 19:15:00 +053053 struct port *port;
Rusty Russell31610432007-10-22 11:03:39 +100054
Rusty Russell971f3392010-01-18 19:14:56 +053055 if (unlikely(early_put_chars))
56 return early_put_chars(vtermno, buf, count);
57
Rusty Russell21206ed2010-01-18 19:15:00 +053058 port = &console;
59
Rusty Russell31610432007-10-22 11:03:39 +100060 /* This is a convenient routine to initialize a single-elem sg list */
61 sg_init_one(sg, buf, count);
62
Rusty Russell21206ed2010-01-18 19:15:00 +053063 /* This shouldn't fail: if it does, we lose chars. */
64 if (port->out_vq->vq_ops->add_buf(port->out_vq, sg, 1, 0, port) >= 0) {
Rusty Russell31610432007-10-22 11:03:39 +100065 /* Tell Host to go! */
Rusty Russell21206ed2010-01-18 19:15:00 +053066 port->out_vq->vq_ops->kick(port->out_vq);
67 while (!port->out_vq->vq_ops->get_buf(port->out_vq, &len))
Rusty Russell31610432007-10-22 11:03:39 +100068 cpu_relax();
69 }
70
71 /* We're expected to return the amount of data we wrote: all of it. */
72 return count;
73}
74
Rusty Russella23ea922010-01-18 19:14:55 +053075/*
76 * Create a scatter-gather list representing our input buffer and put
77 * it in the queue.
78 */
Rusty Russell21206ed2010-01-18 19:15:00 +053079static void add_inbuf(struct port *port)
Rusty Russell31610432007-10-22 11:03:39 +100080{
81 struct scatterlist sg[1];
Rusty Russell21206ed2010-01-18 19:15:00 +053082 sg_init_one(sg, port->inbuf, PAGE_SIZE);
Rusty Russell31610432007-10-22 11:03:39 +100083
Rusty Russell21206ed2010-01-18 19:15:00 +053084 /* Should always be able to add one buffer to an empty queue. */
85 if (port->in_vq->vq_ops->add_buf(port->in_vq, sg, 0, 1, port) < 0)
Rusty Russell31610432007-10-22 11:03:39 +100086 BUG();
Rusty Russell21206ed2010-01-18 19:15:00 +053087 port->in_vq->vq_ops->kick(port->in_vq);
Rusty Russell31610432007-10-22 11:03:39 +100088}
89
Rusty Russella23ea922010-01-18 19:14:55 +053090/*
91 * get_chars() is the callback from the hvc_console infrastructure
92 * when an interrupt is received.
Rusty Russell31610432007-10-22 11:03:39 +100093 *
Rusty Russella23ea922010-01-18 19:14:55 +053094 * Most of the code deals with the fact that the hvc_console()
95 * infrastructure only asks us for 16 bytes at a time. We keep
96 * in_offset and in_used fields for partially-filled buffers.
97 */
Rusty Russell31610432007-10-22 11:03:39 +100098static int get_chars(u32 vtermno, char *buf, int count)
99{
Rusty Russell21206ed2010-01-18 19:15:00 +0530100 struct port *port;
Rusty Russell31610432007-10-22 11:03:39 +1000101
Rusty Russell21206ed2010-01-18 19:15:00 +0530102 port = &console;
103
104 /* If we don't have an input queue yet, we can't get input. */
105 BUG_ON(!port->in_vq);
106
107 /* No more in buffer? See if they've (re)used it. */
108 if (port->offset == port->used_len) {
109 if (!port->in_vq->vq_ops->get_buf(port->in_vq, &port->used_len))
Rusty Russell31610432007-10-22 11:03:39 +1000110 return 0;
Rusty Russell21206ed2010-01-18 19:15:00 +0530111 port->offset = 0;
Rusty Russell31610432007-10-22 11:03:39 +1000112 }
113
114 /* You want more than we have to give? Well, try wanting less! */
Rusty Russell21206ed2010-01-18 19:15:00 +0530115 if (port->offset + count > port->used_len)
116 count = port->used_len - port->offset;
Rusty Russell31610432007-10-22 11:03:39 +1000117
118 /* Copy across to their buffer and increment offset. */
Rusty Russell21206ed2010-01-18 19:15:00 +0530119 memcpy(buf, port->inbuf + port->offset, count);
120 port->offset += count;
Rusty Russell31610432007-10-22 11:03:39 +1000121
122 /* Finished? Re-register buffer so Host will use it again. */
Rusty Russell21206ed2010-01-18 19:15:00 +0530123 if (port->offset == port->used_len)
124 add_inbuf(port);
Rusty Russell31610432007-10-22 11:03:39 +1000125
126 return count;
127}
Rusty Russell31610432007-10-22 11:03:39 +1000128
Rusty Russella23ea922010-01-18 19:14:55 +0530129/*
Christian Borntraegerc2983452008-11-25 13:36:26 +0100130 * virtio console configuration. This supports:
131 * - console resize
132 */
133static void virtcons_apply_config(struct virtio_device *dev)
134{
135 struct winsize ws;
136
137 if (virtio_has_feature(dev, VIRTIO_CONSOLE_F_SIZE)) {
138 dev->config->get(dev,
139 offsetof(struct virtio_console_config, cols),
140 &ws.ws_col, sizeof(u16));
141 dev->config->get(dev,
142 offsetof(struct virtio_console_config, rows),
143 &ws.ws_row, sizeof(u16));
Rusty Russell21206ed2010-01-18 19:15:00 +0530144 hvc_resize(console.hvc, ws);
Christian Borntraegerc2983452008-11-25 13:36:26 +0100145 }
146}
147
148/*
Rusty Russella23ea922010-01-18 19:14:55 +0530149 * we support only one console, the hvc struct is a global var We set
150 * the configuration at this point, since we now have a tty
Christian Borntraeger91fcad12008-06-20 15:24:15 +0200151 */
152static int notifier_add_vio(struct hvc_struct *hp, int data)
153{
154 hp->irq_requested = 1;
Rusty Russell21206ed2010-01-18 19:15:00 +0530155 virtcons_apply_config(console.vdev);
Christian Borntraegerc2983452008-11-25 13:36:26 +0100156
Christian Borntraeger91fcad12008-06-20 15:24:15 +0200157 return 0;
158}
159
160static void notifier_del_vio(struct hvc_struct *hp, int data)
161{
162 hp->irq_requested = 0;
163}
164
165static void hvc_handle_input(struct virtqueue *vq)
166{
Rusty Russell21206ed2010-01-18 19:15:00 +0530167 if (hvc_poll(console.hvc))
Christian Borntraeger91fcad12008-06-20 15:24:15 +0200168 hvc_kick();
169}
170
Rusty Russell971f3392010-01-18 19:14:56 +0530171/* The operations for the console. */
Rusty Russell1dff3992009-11-28 12:20:26 +0530172static const struct hv_ops hv_ops = {
Rusty Russell971f3392010-01-18 19:14:56 +0530173 .get_chars = get_chars,
174 .put_chars = put_chars,
175 .notifier_add = notifier_add_vio,
176 .notifier_del = notifier_del_vio,
177 .notifier_hangup = notifier_del_vio,
178};
179
180/*
181 * Console drivers are initialized very early so boot messages can go
182 * out, so we do things slightly differently from the generic virtio
183 * initialization of the net and block drivers.
184 *
185 * At this stage, the console is output-only. It's too early to set
186 * up a virtqueue, so we let the drivers do some boutique early-output
187 * thing.
188 */
189int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int))
190{
191 early_put_chars = put_chars;
192 return hvc_instantiate(0, 0, &hv_ops);
193}
194
Rusty Russella23ea922010-01-18 19:14:55 +0530195/*
196 * Once we're further in boot, we get probed like any other virtio
197 * device. At this stage we set up the output virtqueue.
Rusty Russell31610432007-10-22 11:03:39 +1000198 *
Rusty Russella23ea922010-01-18 19:14:55 +0530199 * To set up and manage our virtual console, we call hvc_alloc().
200 * Since we never remove the console device we never need this pointer
201 * again.
Rusty Russell31610432007-10-22 11:03:39 +1000202 *
Rusty Russella23ea922010-01-18 19:14:55 +0530203 * Finally we put our input buffer in the input queue, ready to
204 * receive.
205 */
Rusty Russell21206ed2010-01-18 19:15:00 +0530206static int __devinit virtcons_probe(struct virtio_device *vdev)
Rusty Russell31610432007-10-22 11:03:39 +1000207{
Michael S. Tsirkind2a7ddd2009-06-12 22:16:36 -0600208 vq_callback_t *callbacks[] = { hvc_handle_input, NULL};
209 const char *names[] = { "input", "output" };
210 struct virtqueue *vqs[2];
Rusty Russell21206ed2010-01-18 19:15:00 +0530211 struct port *port;
Rusty Russell31610432007-10-22 11:03:39 +1000212 int err;
Rusty Russell31610432007-10-22 11:03:39 +1000213
Rusty Russell21206ed2010-01-18 19:15:00 +0530214 port = &console;
215 if (port->vdev) {
216 dev_warn(&port->vdev->dev,
Amit Shahf5508042010-01-18 19:14:59 +0530217 "Multiple virtio-console devices not supported yet\n");
218 return -EEXIST;
219 }
Rusty Russell21206ed2010-01-18 19:15:00 +0530220 port->vdev = vdev;
Rusty Russell31610432007-10-22 11:03:39 +1000221
222 /* This is the scratch page we use to receive console input */
Rusty Russell21206ed2010-01-18 19:15:00 +0530223 port->used_len = 0;
224 port->inbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
225 if (!port->inbuf) {
Rusty Russell31610432007-10-22 11:03:39 +1000226 err = -ENOMEM;
227 goto fail;
228 }
229
Michael S. Tsirkind2a7ddd2009-06-12 22:16:36 -0600230 /* Find the queues. */
Michael S. Tsirkind2a7ddd2009-06-12 22:16:36 -0600231 err = vdev->config->find_vqs(vdev, 2, vqs, callbacks, names);
232 if (err)
Rusty Russell31610432007-10-22 11:03:39 +1000233 goto free;
Rusty Russell31610432007-10-22 11:03:39 +1000234
Rusty Russell21206ed2010-01-18 19:15:00 +0530235 port->in_vq = vqs[0];
236 port->out_vq = vqs[1];
Rusty Russell31610432007-10-22 11:03:39 +1000237
Rusty Russella23ea922010-01-18 19:14:55 +0530238 /*
239 * The first argument of hvc_alloc() is the virtual console
240 * number, so we use zero. The second argument is the
241 * parameter for the notification mechanism (like irq
242 * number). We currently leave this as zero, virtqueues have
243 * implicit notifications.
Rusty Russell31610432007-10-22 11:03:39 +1000244 *
Rusty Russella23ea922010-01-18 19:14:55 +0530245 * The third argument is a "struct hv_ops" containing the
246 * put_chars(), get_chars(), notifier_add() and notifier_del()
247 * pointers. The final argument is the output buffer size: we
248 * can do any size, so we put PAGE_SIZE here.
249 */
Rusty Russell21206ed2010-01-18 19:15:00 +0530250 port->hvc = hvc_alloc(0, 0, &hv_ops, PAGE_SIZE);
251 if (IS_ERR(port->hvc)) {
252 err = PTR_ERR(port->hvc);
Michael S. Tsirkind2a7ddd2009-06-12 22:16:36 -0600253 goto free_vqs;
Rusty Russell31610432007-10-22 11:03:39 +1000254 }
255
256 /* Register the input buffer the first time. */
Rusty Russell21206ed2010-01-18 19:15:00 +0530257 add_inbuf(port);
Rusty Russell971f3392010-01-18 19:14:56 +0530258
259 /* Start using the new console output. */
260 early_put_chars = NULL;
Rusty Russell31610432007-10-22 11:03:39 +1000261 return 0;
262
Michael S. Tsirkind2a7ddd2009-06-12 22:16:36 -0600263free_vqs:
264 vdev->config->del_vqs(vdev);
Rusty Russell31610432007-10-22 11:03:39 +1000265free:
Rusty Russell21206ed2010-01-18 19:15:00 +0530266 kfree(port->inbuf);
Rusty Russell31610432007-10-22 11:03:39 +1000267fail:
268 return err;
269}
270
271static struct virtio_device_id id_table[] = {
272 { VIRTIO_ID_CONSOLE, VIRTIO_DEV_ANY_ID },
273 { 0 },
274};
275
Christian Borntraegerc2983452008-11-25 13:36:26 +0100276static unsigned int features[] = {
277 VIRTIO_CONSOLE_F_SIZE,
278};
279
Rusty Russell31610432007-10-22 11:03:39 +1000280static struct virtio_driver virtio_console = {
Christian Borntraegerc2983452008-11-25 13:36:26 +0100281 .feature_table = features,
282 .feature_table_size = ARRAY_SIZE(features),
Rusty Russell31610432007-10-22 11:03:39 +1000283 .driver.name = KBUILD_MODNAME,
284 .driver.owner = THIS_MODULE,
285 .id_table = id_table,
286 .probe = virtcons_probe,
Christian Borntraegerc2983452008-11-25 13:36:26 +0100287 .config_changed = virtcons_apply_config,
Rusty Russell31610432007-10-22 11:03:39 +1000288};
289
290static int __init init(void)
291{
292 return register_virtio_driver(&virtio_console);
293}
294module_init(init);
295
296MODULE_DEVICE_TABLE(virtio, id_table);
297MODULE_DESCRIPTION("Virtio console driver");
298MODULE_LICENSE("GPL");